parent
bbdbae2ea2
commit
53061710a9
@ -636,7 +636,33 @@ describe('config', () => {
|
||||
).toEqual({ structure: 'multiple_folders', locales: ['en', 'fr'], default_locale: 'fr' });
|
||||
});
|
||||
|
||||
it('should throw when i18n is set on files collection', () => {
|
||||
it('should throw when i18n structure is not single_file on files collection', () => {
|
||||
expect(() =>
|
||||
applyDefaults(
|
||||
fromJS({
|
||||
i18n: {
|
||||
structure: 'multiple_folders',
|
||||
locales: ['en', 'de'],
|
||||
},
|
||||
collections: [
|
||||
{
|
||||
files: [
|
||||
{
|
||||
name: 'file',
|
||||
file: 'file',
|
||||
i18n: true,
|
||||
fields: [{ name: 'title', widget: 'string', i18n: true }],
|
||||
},
|
||||
],
|
||||
i18n: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
).toThrow('i18n configuration for files collections is limited to single_file structure');
|
||||
});
|
||||
|
||||
it('should throw when i18n structure is set to multiple_folders and contains a single file collection', () => {
|
||||
expect(() =>
|
||||
applyDefaults(
|
||||
fromJS({
|
||||
@ -654,7 +680,56 @@ describe('config', () => {
|
||||
],
|
||||
}),
|
||||
),
|
||||
).toThrow('i18n configuration is not supported for files collection');
|
||||
).toThrow('i18n configuration for files collections is limited to single_file structure');
|
||||
});
|
||||
|
||||
it('should throw when i18n structure is set to multiple_files and contains a single file collection', () => {
|
||||
expect(() =>
|
||||
applyDefaults(
|
||||
fromJS({
|
||||
i18n: {
|
||||
structure: 'multiple_files',
|
||||
locales: ['en', 'de'],
|
||||
},
|
||||
collections: [
|
||||
{
|
||||
files: [
|
||||
{ name: 'file', file: 'file', fields: [{ name: 'title', widget: 'string' }] },
|
||||
],
|
||||
i18n: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
).toThrow('i18n configuration for files collections is limited to single_file structure');
|
||||
});
|
||||
|
||||
it('should set i18n value to translate on field when i18n=true for field in files collection', () => {
|
||||
expect(
|
||||
applyDefaults(
|
||||
fromJS({
|
||||
i18n: {
|
||||
structure: 'multiple_folders',
|
||||
locales: ['en', 'de'],
|
||||
},
|
||||
collections: [
|
||||
{
|
||||
files: [
|
||||
{
|
||||
name: 'file',
|
||||
file: 'file',
|
||||
i18n: true,
|
||||
fields: [{ name: 'title', widget: 'string', i18n: true }],
|
||||
},
|
||||
],
|
||||
i18n: {
|
||||
structure: 'single_file',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
).getIn(['collections', 0, 'files', 0, 'fields', 0, 'i18n']),
|
||||
).toEqual('translate');
|
||||
});
|
||||
|
||||
it('should set i18n value to translate on field when i18n=true for field', () => {
|
||||
|
@ -6,7 +6,7 @@ import * as publishModes from 'Constants/publishModes';
|
||||
import { validateConfig } from 'Constants/configSchema';
|
||||
import { selectDefaultSortableFields, traverseFields } from '../reducers/collections';
|
||||
import { resolveBackend } from 'coreSrc/backend';
|
||||
import { I18N, I18N_FIELD } from '../lib/i18n';
|
||||
import { I18N, I18N_FIELD, I18N_STRUCTURE } from '../lib/i18n';
|
||||
|
||||
export const CONFIG_REQUEST = 'CONFIG_REQUEST';
|
||||
export const CONFIG_SUCCESS = 'CONFIG_SUCCESS';
|
||||
@ -68,38 +68,53 @@ const setI18nField = field => {
|
||||
return field;
|
||||
};
|
||||
|
||||
const setI18nDefaults = (i18n, collection) => {
|
||||
if (i18n && collection.has(I18N)) {
|
||||
const collectionI18n = collection.get(I18N);
|
||||
if (collectionI18n === true) {
|
||||
collection = collection.set(I18N, i18n);
|
||||
} else if (collectionI18n === false) {
|
||||
collection = collection.delete(I18N);
|
||||
const setI18nDefaults = (defaultI18n, collectionOrFile) => {
|
||||
if (defaultI18n && collectionOrFile.has(I18N)) {
|
||||
const collectionOrFileI18n = collectionOrFile.get(I18N);
|
||||
if (collectionOrFileI18n === true) {
|
||||
collectionOrFile = collectionOrFile.set(I18N, defaultI18n);
|
||||
} else if (collectionOrFileI18n === false) {
|
||||
collectionOrFile = collectionOrFile.delete(I18N);
|
||||
} else {
|
||||
const locales = collectionI18n.get('locales', i18n.get('locales'));
|
||||
const defaultLocale = collectionI18n.get(
|
||||
const locales = collectionOrFileI18n.get('locales', defaultI18n.get('locales'));
|
||||
const defaultLocale = collectionOrFileI18n.get(
|
||||
'default_locale',
|
||||
collectionI18n.has('locales') ? locales.first() : i18n.get('default_locale'),
|
||||
collectionOrFileI18n.has('locales') ? locales.first() : defaultI18n.get('default_locale'),
|
||||
);
|
||||
collection = collection.set(I18N, i18n.merge(collectionI18n));
|
||||
collection = collection.setIn([I18N, 'locales'], locales);
|
||||
collection = collection.setIn([I18N, 'default_locale'], defaultLocale);
|
||||
collectionOrFile = collectionOrFile.set(I18N, defaultI18n.merge(collectionOrFileI18n));
|
||||
collectionOrFile = collectionOrFile.setIn([I18N, 'locales'], locales);
|
||||
collectionOrFile = collectionOrFile.setIn([I18N, 'default_locale'], defaultLocale);
|
||||
|
||||
throwOnMissingDefaultLocale(collection.get(I18N));
|
||||
throwOnMissingDefaultLocale(collectionOrFile.get(I18N));
|
||||
}
|
||||
|
||||
if (collectionI18n !== false) {
|
||||
if (collectionOrFileI18n !== false) {
|
||||
// set default values for i18n fields
|
||||
collection = collection.set('fields', traverseFields(collection.get('fields'), setI18nField));
|
||||
if (collectionOrFile.has('fields')) {
|
||||
collectionOrFile = collectionOrFile.set(
|
||||
'fields',
|
||||
traverseFields(collectionOrFile.get('fields'), setI18nField),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
collection = collection.delete(I18N);
|
||||
collection = collection.set(
|
||||
'fields',
|
||||
traverseFields(collection.get('fields'), field => field.delete(I18N)),
|
||||
collectionOrFile = collectionOrFile.delete(I18N);
|
||||
if (collectionOrFile.has('fields')) {
|
||||
collectionOrFile = collectionOrFile.set(
|
||||
'fields',
|
||||
traverseFields(collectionOrFile.get('fields'), field => field.delete(I18N)),
|
||||
);
|
||||
}
|
||||
}
|
||||
return collectionOrFile;
|
||||
};
|
||||
|
||||
const throwOnInvalidFileCollectionStructure = i18n => {
|
||||
if (i18n && i18n.get('structure') !== I18N_STRUCTURE.SINGLE_FILE) {
|
||||
throw new Error(
|
||||
`i18n configuration for files collections is limited to ${I18N_STRUCTURE.SINGLE_FILE} structure`,
|
||||
);
|
||||
}
|
||||
return collection;
|
||||
};
|
||||
|
||||
const throwOnMissingDefaultLocale = i18n => {
|
||||
@ -211,6 +226,8 @@ export function applyDefaults(config) {
|
||||
collection = collection.set('publish', true);
|
||||
}
|
||||
|
||||
collection = setI18nDefaults(i18n, collection);
|
||||
|
||||
const folder = collection.get('folder');
|
||||
if (folder) {
|
||||
if (collection.has('path') && !collection.has('media_folder')) {
|
||||
@ -238,15 +255,13 @@ export function applyDefaults(config) {
|
||||
} else {
|
||||
collection = collection.set('meta', Map());
|
||||
}
|
||||
|
||||
collection = setI18nDefaults(i18n, collection);
|
||||
}
|
||||
|
||||
const files = collection.get('files');
|
||||
if (files) {
|
||||
if (i18n && collection.has(I18N)) {
|
||||
throw new Error('i18n configuration is not supported for files collection');
|
||||
}
|
||||
const collectionI18n = collection.get(I18N);
|
||||
throwOnInvalidFileCollectionStructure(collectionI18n);
|
||||
|
||||
collection = collection.delete('nested');
|
||||
collection = collection.delete('meta');
|
||||
collection = collection.set(
|
||||
@ -258,6 +273,8 @@ export function applyDefaults(config) {
|
||||
'fields',
|
||||
traverseFields(file.get('fields'), setDefaultPublicFolder),
|
||||
);
|
||||
file = setI18nDefaults(collectionI18n, file);
|
||||
throwOnInvalidFileCollectionStructure(file.get(I18N));
|
||||
return file;
|
||||
}),
|
||||
);
|
||||
|
@ -400,6 +400,33 @@ describe('i18n', () => {
|
||||
raw: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('should default to empty data object when file is empty and structure is I18N_STRUCTURE.SINGLE_FILE', async () => {
|
||||
const data = {
|
||||
'src/content/index.md': {
|
||||
slug: 'index',
|
||||
path: 'src/content/index.md',
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
const getEntryValue = jest.fn(path => Promise.resolve(data[path]));
|
||||
|
||||
await expect(
|
||||
i18n.getI18nEntry(
|
||||
fromJS({
|
||||
i18n: { structure: i18n.I18N_STRUCTURE.SINGLE_FILE, locales, default_locale },
|
||||
}),
|
||||
...args,
|
||||
getEntryValue,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
slug: 'index',
|
||||
path: 'src/content/index.md',
|
||||
data: {},
|
||||
i18n: {},
|
||||
raw: '',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('groupEntries', () => {
|
||||
|
@ -244,7 +244,7 @@ const mergeValues = (
|
||||
};
|
||||
|
||||
const mergeSingleFileValue = (entryValue: EntryValue, defaultLocale: string, locales: string[]) => {
|
||||
const data = entryValue.data[defaultLocale];
|
||||
const data = entryValue.data[defaultLocale] || {};
|
||||
const i18n = locales
|
||||
.filter(l => l !== defaultLocale)
|
||||
.map(l => ({ locale: l, value: entryValue.data[l] }))
|
||||
|
@ -130,7 +130,7 @@ collections:
|
||||
|
||||
### Limitations
|
||||
|
||||
1. File collections are not supported.
|
||||
1. File collections support only `structure: single_file`.
|
||||
2. List widgets only support `i18n: true`. `i18n` configuration on sub fields is ignored.
|
||||
3. Object widgets only support `i18n: true` and `i18n` configuration should be done per field:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user