feat: make non default locales optional (#1109)

This commit is contained in:
Daniel Lautzenheiser 2024-04-26 12:32:10 -04:00 committed by GitHub
parent 69fc27ab6b
commit 1d0141fcc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 49 additions and 8 deletions

View File

@ -19,6 +19,10 @@ i18n:
# Optional, defaults to the first item in locales.
# The locale to be used for fields validation and as a baseline for the entry.
default_locale: en
# Optional, defaults to true.
# Enforce required fields in non-default locales
enforce_required_non_default: true
collections:
- name: posts
label: Posts

View File

@ -697,7 +697,12 @@ describe('config', () => {
},
],
}).collections[0].i18n,
).toEqual({ structure: 'multiple_folders', locales: ['en', 'de'], default_locale: 'en' });
).toEqual({
structure: 'multiple_folders',
locales: ['en', 'de'],
default_locale: 'en',
enforce_required_non_default: true,
});
});
it('should not set root i18n on collection when collection i18n is not set', () => {
@ -757,7 +762,12 @@ describe('config', () => {
},
],
}).collections[0].i18n,
).toEqual({ structure: 'multiple_folders', locales: ['en', 'fr'], default_locale: 'fr' });
).toEqual({
structure: 'multiple_folders',
locales: ['en', 'fr'],
default_locale: 'fr',
enforce_required_non_default: true,
});
});
it('should throw when i18n structure is not single_file on files collection', () => {

View File

@ -92,17 +92,24 @@ function setI18nField<T extends BaseField = UnknownField>(field: T) {
function getI18nDefaults(
collectionOrFileI18n: boolean | Partial<I18nInfo>,
{ default_locale, locales = ['en'], structure = I18N_STRUCTURE_SINGLE_FILE }: Partial<I18nInfo>,
{
default_locale,
locales = ['en'],
structure = I18N_STRUCTURE_SINGLE_FILE,
enforce_required_non_default = true,
}: Partial<I18nInfo>,
): I18nInfo {
if (typeof collectionOrFileI18n === 'boolean') {
return { default_locale, locales, structure };
return { default_locale, locales, structure, enforce_required_non_default };
} else {
const mergedI18n: I18nInfo = deepmerge(
{ default_locale, locales, structure },
{ default_locale, locales, structure, enforce_required_non_default },
collectionOrFileI18n,
);
mergedI18n.locales = collectionOrFileI18n.locales ?? locales;
mergedI18n.default_locale = collectionOrFileI18n.default_locale || locales?.[0];
mergedI18n.enforce_required_non_default =
collectionOrFileI18n.enforce_required_non_default || true;
throwOnMissingDefaultLocale(mergedI18n);
return mergedI18n;
}
@ -202,6 +209,7 @@ function applyCollectionFileDefaults(
locales: collectionI18n.locales,
default_locale: collectionI18n.default_locale,
structure: collectionI18n.structure,
enforce_required_non_default: collectionI18n.enforce_required_non_default,
});
file.i18n = fileI18n;
} else {
@ -315,6 +323,7 @@ export function applyDefaults<EF extends BaseField = UnknownField>(
if (i18n) {
i18n.default_locale = i18n.default_locale ?? i18n.locales[0];
i18n.enforce_required_non_default = i18n.enforce_required_non_default ?? true;
}
throwOnMissingDefaultLocale(i18n);

View File

@ -124,7 +124,8 @@ const EditorControl: FC<EditorControlProps> = ({
(!dirty && !submitted) ||
disabled ||
i18nDisabled ||
(forList && field.widget === 'object' && field.fields.length === 1)
(forList && field.widget === 'object' && field.fields.length === 1) ||
(i18n?.enforceRequiredNonDefault === false && i18n?.currentLocale !== i18n?.defaultLocale)
) {
return;
}

View File

@ -88,11 +88,12 @@ const EditorControlPane: FC<EditorControlPaneProps> = ({
const i18n = useMemo(() => {
if (hasI18n(collection)) {
const { locales, default_locale } = getI18nInfo(collection);
const { locales, default_locale, enforce_required_non_default } = getI18nInfo(collection);
return {
currentLocale: locale ?? locales?.[0],
locales,
defaultLocale: default_locale,
enforceRequiredNonDefault: enforce_required_non_default,
} as I18nSettings;
}

View File

@ -40,6 +40,7 @@ const i18n = {
uniqueItems: true,
},
default_locale: localeType,
enforce_required_non_default: { type: 'boolean' },
},
};

View File

@ -267,6 +267,7 @@ export interface I18nSettings {
currentLocale: string;
defaultLocale: string;
locales: string[];
enforceRequiredNonDefault?: boolean;
}
export type Format = keyof typeof formatExtensions;
@ -1306,6 +1307,7 @@ export interface I18nInfo {
locales: string[];
default_locale?: string;
structure: I18nStructure;
enforce_required_non_default?: boolean;
}
export interface ProcessedCodeLanguage {

View File

@ -343,6 +343,7 @@ export async function getI18nEntry<EF extends BaseField>(
i18nInfo = {
structure: I18N_STRUCTURE_SINGLE_FILE,
locales: [],
enforce_required_non_default: true,
};
}

View File

@ -115,6 +115,7 @@ describe('entryDraft', () => {
locales: ['en', 'fr', 'es'],
defaultLocale: 'en',
currentLocale: 'en',
enforceRequiredNonDefault: true,
},
isMeta: false,
},
@ -155,6 +156,7 @@ describe('entryDraft', () => {
locales: ['en', 'fr', 'es'],
defaultLocale: 'en',
currentLocale: 'en',
enforceRequiredNonDefault: true,
};
let state = entryDraftReducer(startState, {

View File

@ -25,6 +25,10 @@ i18n:
# Optional, defaults to the first item in locales.
# The locale to be used for fields validation and as a baseline for the entry.
default_locale: en
# Optional, defaults to true.
# Enforce required fields in non-default locales
enforce_required_non_default: false
```
```js
@ -44,7 +48,13 @@ i18n: {
* Optional, defaults to the first item in locales.
* The locale to be used for fields validation and as a baseline for the entry.
*/
default_locale: 'en'
default_locale: 'en',
/**
* Optional, defaults to true.
* Enforce required fields in non-default locales
*/
enforce_required_non_default: false
},
```