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

feat: make non default locales optional #1109

Merged
merged 1 commit into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/core/dev-test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 12 additions & 2 deletions packages/core/src/actions/__tests__/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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', () => {
Expand Down
15 changes: 12 additions & 3 deletions packages/core/src/actions/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/constants/configSchema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const i18n = {
uniqueItems: true,
},
default_locale: localeType,
enforce_required_non_default: { type: 'boolean' },
},
};

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ export interface I18nSettings {
currentLocale: string;
defaultLocale: string;
locales: string[];
enforceRequiredNonDefault?: boolean;
}

export type Format = keyof typeof formatExtensions;
Expand Down Expand Up @@ -1306,6 +1307,7 @@ export interface I18nInfo {
locales: string[];
default_locale?: string;
structure: I18nStructure;
enforce_required_non_default?: boolean;
}

export interface ProcessedCodeLanguage {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/lib/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ export async function getI18nEntry<EF extends BaseField>(
i18nInfo = {
structure: I18N_STRUCTURE_SINGLE_FILE,
locales: [],
enforce_required_non_default: true,
};
}

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/reducers/__tests__/entryDraft.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ describe('entryDraft', () => {
locales: ['en', 'fr', 'es'],
defaultLocale: 'en',
currentLocale: 'en',
enforceRequiredNonDefault: true,
},
isMeta: false,
},
Expand Down Expand Up @@ -155,6 +156,7 @@ describe('entryDraft', () => {
locales: ['en', 'fr', 'es'],
defaultLocale: 'en',
currentLocale: 'en',
enforceRequiredNonDefault: true,
};

let state = entryDraftReducer(startState, {
Expand Down
12 changes: 11 additions & 1 deletion packages/docs/content/docs/i18n-support.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
},
```

Expand Down
Loading