diff --git a/config/i18n.ts b/config/i18n.ts index 9f8c8c4de..7a5b77d38 100644 --- a/config/i18n.ts +++ b/config/i18n.ts @@ -78,6 +78,26 @@ export const countryLocaleVariants: Record) { + return (choice: number, choicesLength: number) => { + const name = new Intl.PluralRules(locale).select(choice) + const plural = mapping[name] || 0 + + // In case translation doesn't have all plural forms, use the last available form + if (plural > choicesLength - 1) { + if (import.meta.dev) { + // oxlint-disable-next-line no-console -- warn logging + console.warn( + `Plural form index ${plural} for choice ${choice} exceeds available forms ${choicesLength} for locale ${locale}.`, + ) + } + return choicesLength - 1 + } + + return plural + } +} + const locales: (LocaleObjectData | (Omit & { code: string }))[] = [ { code: 'en', @@ -89,10 +109,7 @@ const locales: (LocaleObjectData | (Omit & { code: str file: 'ar.json', name: 'العربية', dir: 'rtl', - pluralRule: (choice: number) => { - const name = new Intl.PluralRules('ar-EG').select(choice) - return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name] - }, + pluralRule: createPluralRule('ar-EG', { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }), }, { code: 'az-AZ', @@ -148,10 +165,7 @@ const locales: (LocaleObjectData | (Omit & { code: str code: 'hu-HU', file: 'hu-HU.json', name: 'Magyar', - pluralRule: (choice: number) => { - const name = new Intl.PluralRules('hu-HU').select(choice) - return { zero: 0, one: 0, two: 1, few: 1, many: 1, other: 1 }[name] - }, + pluralRule: createPluralRule('hu-HU', { zero: 0, one: 0, two: 1, few: 1, many: 1, other: 1 }), }, { code: 'zh-CN', @@ -197,21 +211,13 @@ const locales: (LocaleObjectData | (Omit & { code: str code: 'ru-RU', file: 'ru-RU.json', name: 'Русский', - pluralRule: (choice: number) => { - const name = new Intl.PluralRules('ru-RU').select(choice) - return { zero: 2, one: 0, two: 1, few: 1, many: 2, other: 3 }[name] - }, + pluralRule: createPluralRule('ru-RU', { zero: 2, one: 0, two: 1, few: 1, many: 2, other: 3 }), }, { code: 'uk-UA', file: 'uk-UA.json', name: 'Українська', - pluralRule: (choice: number) => { - if (choice === 0) return 0 - - const name = new Intl.PluralRules('uk-UA').select(choice) - return { zero: 0, one: 1, two: 0, few: 2, many: 3, other: 4 }[name] - }, + pluralRule: createPluralRule('uk-UA', { zero: 0, one: 1, two: 0, few: 2, many: 3, other: 4 }), }, /*{ code: 'ru-RU', @@ -226,10 +232,7 @@ const locales: (LocaleObjectData | (Omit & { code: str code: 'cs-CZ', file: 'cs-CZ.json', name: 'Čeština', - pluralRule: (choice: number) => { - const name = new Intl.PluralRules('cs-CZ').select(choice) - return { zero: 2, one: 0, two: 1, few: 1, many: 2, other: 2 }[name] - }, + pluralRule: createPluralRule('cs-CZ', { zero: 2, one: 0, two: 1, few: 1, many: 2, other: 2 }), } /* { code: 'pl-PL', @@ -287,12 +290,7 @@ const locales: (LocaleObjectData | (Omit & { code: str code: 'pl-PL', file: 'pl-PL.json', name: 'Polski', - pluralRule: (choice: number) => { - if (choice === 0) return 0 - - const name = new Intl.PluralRules('pl-PL').select(choice) - return { zero: 0, one: 1, two: 0, few: 2, many: 3, other: 4 }[name] - }, + pluralRule: createPluralRule('pl-PL', { zero: 0, one: 1, two: 0, few: 2, many: 3, other: 4 }), }, { code: 'pt-BR',