mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 07:05:24 +00:00
feat: AI translations at release, 7 new languages and regional fallback
This commit is contained in:
1 parent
6873bc92bb
commit
874ad9f4fd
11 files changed
+356
-134
No files matched your search
+19
-41
@@ -3,46 +3,14 @@ import { initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
|
||||
import enTranslation from "../locales/en.json";
|
||||
import { TRANSLATED_LANGUAGES } from "./languages";
|
||||
|
||||
type LocaleModule = { default: ResourceKey };
|
||||
|
||||
/** i18n code -> translated file name, shared by core and plugin locales. */
|
||||
export const LOCALE_FILES = {
|
||||
af: "af_ZA",
|
||||
ar: "ar_SA",
|
||||
bn: "bn_BD",
|
||||
bg: "bg_BG",
|
||||
ca: "ca_ES",
|
||||
cs: "cs_CZ",
|
||||
da: "da_DK",
|
||||
de: "de_DE",
|
||||
el: "el_GR",
|
||||
"es-ES": "es_ES",
|
||||
fi: "fi_FI",
|
||||
fr: "fr_FR",
|
||||
he: "he_IL",
|
||||
hi: "hi_IN",
|
||||
hu: "hu_HU",
|
||||
id: "id_ID",
|
||||
it: "it_IT",
|
||||
ja: "ja_JP",
|
||||
ko: "ko_KR",
|
||||
nl: "nl_NL",
|
||||
no: "no_NO",
|
||||
pl: "pl_PL",
|
||||
"pt-PT": "pt_PT",
|
||||
"pt-BR": "pt_BR",
|
||||
ro: "ro_RO",
|
||||
ru: "ru_RU",
|
||||
sr: "sr_SP",
|
||||
"sv-SE": "sv_SE",
|
||||
th: "th_TH",
|
||||
tr: "tr_TR",
|
||||
uk: "uk_UA",
|
||||
vi: "vi_VN",
|
||||
"zh-CN": "zh_CN",
|
||||
"zh-TW": "zh_TW",
|
||||
} as const satisfies Record<string, string>;
|
||||
export const LOCALE_FILES: Record<string, string> = Object.fromEntries(
|
||||
TRANSLATED_LANGUAGES.map(({ code, file }) => [code, file]),
|
||||
);
|
||||
|
||||
const translatedFiles = import.meta.glob<LocaleModule>(
|
||||
"../locales/translated/*.json",
|
||||
@@ -94,8 +62,20 @@ export function normalizeLanguageCode(language?: string | null): string {
|
||||
);
|
||||
if (exactMatch) return exactMatch;
|
||||
|
||||
const baseLanguage = normalized.split("-")[0];
|
||||
return supportedLngs.includes(baseLanguage) ? baseLanguage : "en";
|
||||
const baseLanguage = normalized.split("-")[0].toLowerCase();
|
||||
if (supportedLngs.includes(baseLanguage)) return baseLanguage;
|
||||
|
||||
// Regional variants we don't ship (es-MX, pt, sv) use the closest one we do.
|
||||
if (baseLanguage === "zh") {
|
||||
return /-(tw|hk|mo|hant)\b/i.test(normalized) ? "zh-TW" : "zh-CN";
|
||||
}
|
||||
if (baseLanguage === "nb" || baseLanguage === "nn") return "no";
|
||||
if (baseLanguage === "pt") return "pt-BR";
|
||||
return (
|
||||
supportedLngs.find((supported) =>
|
||||
supported.toLowerCase().startsWith(`${baseLanguage}-`),
|
||||
) ?? "en"
|
||||
);
|
||||
}
|
||||
|
||||
const localeBackend: BackendModule = {
|
||||
@@ -106,9 +86,7 @@ const localeBackend: BackendModule = {
|
||||
|
||||
if (namespace !== CORE_NAMESPACE) {
|
||||
const file =
|
||||
normalizedLanguage === "en"
|
||||
? "en"
|
||||
: (LOCALE_FILES as Record<string, string>)[normalizedLanguage];
|
||||
normalizedLanguage === "en" ? "en" : LOCALE_FILES[normalizedLanguage];
|
||||
if (!pluginLocaleResolver || !file) {
|
||||
callback(null, {});
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import languages from "../locales/languages.json";
|
||||
|
||||
/** One translated language. The translator in Termix-Registry keeps a copy of this list. */
|
||||
export interface Language {
|
||||
code: string;
|
||||
file: string;
|
||||
name: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export const TRANSLATED_LANGUAGES: readonly Language[] = languages;
|
||||
|
||||
/** Every language the app can show, English first, for language pickers. */
|
||||
export const LANGUAGES: readonly { code: string; label: string }[] = [
|
||||
{ code: "en", label: "English" },
|
||||
...TRANSLATED_LANGUAGES.map(({ code, label }) => ({ code, label })),
|
||||
];
|
||||
Reference in new issue
Block a user