From bf3649942c820e0906a61facbb8ef49201480e18 Mon Sep 17 00:00:00 2001 From: Isaias Tavares Date: Sun, 12 Apr 2026 18:54:26 -0300 Subject: [PATCH] refactor(i18n): add locale to SUPPORTED_LANGUAGES and derive LOCALES from it LOCALES is now built via Object.fromEntries from SUPPORTED_LANGUAGES, so adding a new language only requires one change in supportedLanguages.ts. Also types translations as Record so TypeScript enforces that every supported language has a translation entry. --- client/src/i18n/TranslationContext.tsx | 14 +++++++++--- client/src/i18n/supportedLanguages.ts | 30 +++++++++++++------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/client/src/i18n/TranslationContext.tsx b/client/src/i18n/TranslationContext.tsx index 83a2a127..f18dcf20 100644 --- a/client/src/i18n/TranslationContext.tsx +++ b/client/src/i18n/TranslationContext.tsx @@ -14,14 +14,22 @@ import ar from './translations/ar' import br from './translations/br' import cs from './translations/cs' import pl from './translations/pl' -import { SUPPORTED_LANGUAGES } from './supportedLanguages' +import { SUPPORTED_LANGUAGES, SupportedLanguageCode } from './supportedLanguages' export { SUPPORTED_LANGUAGES } type TranslationStrings = Record -const translations: Record = { de, en, es, fr, hu, it, ru, zh, 'zh-TW': zhTw, nl, ar, br, cs, pl } -const LOCALES: Record = { de: 'de-DE', en: 'en-US', es: 'es-ES', fr: 'fr-FR', hu: 'hu-HU', it: 'it-IT', ru: 'ru-RU', zh: 'zh-CN', 'zh-TW': 'zh-TW', nl: 'nl-NL', ar: 'ar-SA', br: 'pt-BR', cs: 'cs-CZ', pl: 'pl-PL' } +// Keyed by SupportedLanguageCode so TypeScript enforces all languages have a translation. +const translations: Record = { + de, en, es, fr, hu, it, ru, zh, 'zh-TW': zhTw, nl, ar, br, cs, pl, +} + +// Derived from SUPPORTED_LANGUAGES — add new languages there, not here. +const LOCALES: Record = Object.fromEntries( + SUPPORTED_LANGUAGES.map(l => [l.value, l.locale]) +) + const RTL_LANGUAGES = new Set(['ar']) export function getLocaleForLanguage(language: string): string { diff --git a/client/src/i18n/supportedLanguages.ts b/client/src/i18n/supportedLanguages.ts index 496e34b2..28d957b8 100644 --- a/client/src/i18n/supportedLanguages.ts +++ b/client/src/i18n/supportedLanguages.ts @@ -1,20 +1,20 @@ export const SUPPORTED_LANGUAGES = [ - { value: 'de', label: 'Deutsch' }, - { value: 'en', label: 'English' }, - { value: 'es', label: 'Español' }, - { value: 'fr', label: 'Français' }, - { value: 'hu', label: 'Magyar' }, - { value: 'nl', label: 'Nederlands' }, - { value: 'br', label: 'Português (Brasil)' }, - { value: 'cs', label: 'Česky' }, - { value: 'pl', label: 'Polski' }, - { value: 'ru', label: 'Русский' }, - { value: 'zh', label: '简体中文' }, - { value: 'zh-TW', label: '繁體中文' }, - { value: 'it', label: 'Italiano' }, - { value: 'ar', label: 'العربية' }, + { value: 'de', label: 'Deutsch', locale: 'de-DE' }, + { value: 'en', label: 'English', locale: 'en-US' }, + { value: 'es', label: 'Español', locale: 'es-ES' }, + { value: 'fr', label: 'Français', locale: 'fr-FR' }, + { value: 'hu', label: 'Magyar', locale: 'hu-HU' }, + { value: 'nl', label: 'Nederlands', locale: 'nl-NL' }, + { value: 'br', label: 'Português (Brasil)', locale: 'pt-BR' }, + { value: 'cs', label: 'Česky', locale: 'cs-CZ' }, + { value: 'pl', label: 'Polski', locale: 'pl-PL' }, + { value: 'ru', label: 'Русский', locale: 'ru-RU' }, + { value: 'zh', label: '简体中文', locale: 'zh-CN' }, + { value: 'zh-TW', label: '繁體中文', locale: 'zh-TW' }, + { value: 'it', label: 'Italiano', locale: 'it-IT' }, + { value: 'ar', label: 'العربية', locale: 'ar-SA' }, ] as const export type SupportedLanguageCode = typeof SUPPORTED_LANGUAGES[number]['value'] -export const SUPPORTED_LANGUAGE_CODES = SUPPORTED_LANGUAGES.map(l => l.value) +export const SUPPORTED_LANGUAGE_CODES: string[] = SUPPORTED_LANGUAGES.map(l => l.value)