Skip to content
This repository was archived by the owner on Sep 9, 2024. It is now read-only.

Commit 1d0141f

Browse files
authored
feat: make non default locales optional (#1109)
1 parent 69fc27a commit 1d0141f

File tree

10 files changed

+49
-8
lines changed

10 files changed

+49
-8
lines changed

packages/core/dev-test/config.yml

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ i18n:
1919
# Optional, defaults to the first item in locales.
2020
# The locale to be used for fields validation and as a baseline for the entry.
2121
default_locale: en
22+
23+
# Optional, defaults to true.
24+
# Enforce required fields in non-default locales
25+
enforce_required_non_default: true
2226
collections:
2327
- name: posts
2428
label: Posts

packages/core/src/actions/__tests__/config.spec.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,12 @@ describe('config', () => {
697697
},
698698
],
699699
}).collections[0].i18n,
700-
).toEqual({ structure: 'multiple_folders', locales: ['en', 'de'], default_locale: 'en' });
700+
).toEqual({
701+
structure: 'multiple_folders',
702+
locales: ['en', 'de'],
703+
default_locale: 'en',
704+
enforce_required_non_default: true,
705+
});
701706
});
702707

703708
it('should not set root i18n on collection when collection i18n is not set', () => {
@@ -757,7 +762,12 @@ describe('config', () => {
757762
},
758763
],
759764
}).collections[0].i18n,
760-
).toEqual({ structure: 'multiple_folders', locales: ['en', 'fr'], default_locale: 'fr' });
765+
).toEqual({
766+
structure: 'multiple_folders',
767+
locales: ['en', 'fr'],
768+
default_locale: 'fr',
769+
enforce_required_non_default: true,
770+
});
761771
});
762772

763773
it('should throw when i18n structure is not single_file on files collection', () => {

packages/core/src/actions/config.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,24 @@ function setI18nField<T extends BaseField = UnknownField>(field: T) {
9292

9393
function getI18nDefaults(
9494
collectionOrFileI18n: boolean | Partial<I18nInfo>,
95-
{ default_locale, locales = ['en'], structure = I18N_STRUCTURE_SINGLE_FILE }: Partial<I18nInfo>,
95+
{
96+
default_locale,
97+
locales = ['en'],
98+
structure = I18N_STRUCTURE_SINGLE_FILE,
99+
enforce_required_non_default = true,
100+
}: Partial<I18nInfo>,
96101
): I18nInfo {
97102
if (typeof collectionOrFileI18n === 'boolean') {
98-
return { default_locale, locales, structure };
103+
return { default_locale, locales, structure, enforce_required_non_default };
99104
} else {
100105
const mergedI18n: I18nInfo = deepmerge(
101-
{ default_locale, locales, structure },
106+
{ default_locale, locales, structure, enforce_required_non_default },
102107
collectionOrFileI18n,
103108
);
104109
mergedI18n.locales = collectionOrFileI18n.locales ?? locales;
105110
mergedI18n.default_locale = collectionOrFileI18n.default_locale || locales?.[0];
111+
mergedI18n.enforce_required_non_default =
112+
collectionOrFileI18n.enforce_required_non_default || true;
106113
throwOnMissingDefaultLocale(mergedI18n);
107114
return mergedI18n;
108115
}
@@ -202,6 +209,7 @@ function applyCollectionFileDefaults(
202209
locales: collectionI18n.locales,
203210
default_locale: collectionI18n.default_locale,
204211
structure: collectionI18n.structure,
212+
enforce_required_non_default: collectionI18n.enforce_required_non_default,
205213
});
206214
file.i18n = fileI18n;
207215
} else {
@@ -315,6 +323,7 @@ export function applyDefaults<EF extends BaseField = UnknownField>(
315323

316324
if (i18n) {
317325
i18n.default_locale = i18n.default_locale ?? i18n.locales[0];
326+
i18n.enforce_required_non_default = i18n.enforce_required_non_default ?? true;
318327
}
319328

320329
throwOnMissingDefaultLocale(i18n);

packages/core/src/components/entry-editor/editor-control-pane/EditorControl.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ const EditorControl: FC<EditorControlProps> = ({
124124
(!dirty && !submitted) ||
125125
disabled ||
126126
i18nDisabled ||
127-
(forList && field.widget === 'object' && field.fields.length === 1)
127+
(forList && field.widget === 'object' && field.fields.length === 1) ||
128+
(i18n?.enforceRequiredNonDefault === false && i18n?.currentLocale !== i18n?.defaultLocale)
128129
) {
129130
return;
130131
}

packages/core/src/components/entry-editor/editor-control-pane/EditorControlPane.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,12 @@ const EditorControlPane: FC<EditorControlPaneProps> = ({
8888

8989
const i18n = useMemo(() => {
9090
if (hasI18n(collection)) {
91-
const { locales, default_locale } = getI18nInfo(collection);
91+
const { locales, default_locale, enforce_required_non_default } = getI18nInfo(collection);
9292
return {
9393
currentLocale: locale ?? locales?.[0],
9494
locales,
9595
defaultLocale: default_locale,
96+
enforceRequiredNonDefault: enforce_required_non_default,
9697
} as I18nSettings;
9798
}
9899

packages/core/src/constants/configSchema.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const i18n = {
4040
uniqueItems: true,
4141
},
4242
default_locale: localeType,
43+
enforce_required_non_default: { type: 'boolean' },
4344
},
4445
};
4546

packages/core/src/interface.ts

+2
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ export interface I18nSettings {
267267
currentLocale: string;
268268
defaultLocale: string;
269269
locales: string[];
270+
enforceRequiredNonDefault?: boolean;
270271
}
271272

272273
export type Format = keyof typeof formatExtensions;
@@ -1306,6 +1307,7 @@ export interface I18nInfo {
13061307
locales: string[];
13071308
default_locale?: string;
13081309
structure: I18nStructure;
1310+
enforce_required_non_default?: boolean;
13091311
}
13101312

13111313
export interface ProcessedCodeLanguage {

packages/core/src/lib/i18n.ts

+1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ export async function getI18nEntry<EF extends BaseField>(
343343
i18nInfo = {
344344
structure: I18N_STRUCTURE_SINGLE_FILE,
345345
locales: [],
346+
enforce_required_non_default: true,
346347
};
347348
}
348349

packages/core/src/reducers/__tests__/entryDraft.spec.ts

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ describe('entryDraft', () => {
115115
locales: ['en', 'fr', 'es'],
116116
defaultLocale: 'en',
117117
currentLocale: 'en',
118+
enforceRequiredNonDefault: true,
118119
},
119120
isMeta: false,
120121
},
@@ -155,6 +156,7 @@ describe('entryDraft', () => {
155156
locales: ['en', 'fr', 'es'],
156157
defaultLocale: 'en',
157158
currentLocale: 'en',
159+
enforceRequiredNonDefault: true,
158160
};
159161

160162
let state = entryDraftReducer(startState, {

packages/docs/content/docs/i18n-support.mdx

+11-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ i18n:
2525
# Optional, defaults to the first item in locales.
2626
# The locale to be used for fields validation and as a baseline for the entry.
2727
default_locale: en
28+
29+
# Optional, defaults to true.
30+
# Enforce required fields in non-default locales
31+
enforce_required_non_default: false
2832
```
2933
3034
```js
@@ -44,7 +48,13 @@ i18n: {
4448
* Optional, defaults to the first item in locales.
4549
* The locale to be used for fields validation and as a baseline for the entry.
4650
*/
47-
default_locale: 'en'
51+
default_locale: 'en',
52+
53+
/**
54+
* Optional, defaults to true.
55+
* Enforce required fields in non-default locales
56+
*/
57+
enforce_required_non_default: false
4858
},
4959
```
5060

0 commit comments

Comments
 (0)