From 477592d176683f99281165928c2c587491c3e6fc Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 25 Oct 2025 21:55:53 +0300 Subject: [PATCH] fix(website/i18n): language detection not always working --- apps/website/src/i18n.spec.ts | 14 ++++++++++++++ apps/website/src/i18n.ts | 13 +++++++++++++ apps/website/src/index.tsx | 4 ++-- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 apps/website/src/i18n.spec.ts diff --git a/apps/website/src/i18n.spec.ts b/apps/website/src/i18n.spec.ts new file mode 100644 index 000000000..efc1e18e8 --- /dev/null +++ b/apps/website/src/i18n.spec.ts @@ -0,0 +1,14 @@ +import { describe, expect, it } from "vitest"; +import { mapLocale } from "./i18n"; + +describe("mapLocale", () => { + it("maps Chinese", () => { + expect(mapLocale("zh-TW")).toStrictEqual("zh-Hant"); + expect(mapLocale("zh-CN")).toStrictEqual("zh-Hans"); + }); + + it("maps languages without countries", () => { + expect(mapLocale("ro-RO")).toStrictEqual("ro"); + expect(mapLocale("ro")).toStrictEqual("ro"); + }); +}); diff --git a/apps/website/src/i18n.ts b/apps/website/src/i18n.ts index 0473de9f8..546907166 100644 --- a/apps/website/src/i18n.ts +++ b/apps/website/src/i18n.ts @@ -17,4 +17,17 @@ export const LOCALES: Locale[] = [ { id: "ar", name: "اَلْعَرَبِيَّةُ", rtl: true }, ].toSorted((a, b) => a.name.localeCompare(b.name)); +export function mapLocale(locale: string) { + if (!locale) return 'en'; + const lower = locale.toLowerCase(); + if (lower.startsWith('zh')) { + if (lower.includes('tw') || lower.includes('hk') || lower.includes('mo') || lower.includes('hant')) { + return 'zh-Hant'; + } + return 'zh-Hans'; + } + + // Default for everything else + return locale.split('-')[0]; // e.g. "en-US" -> "en" +} diff --git a/apps/website/src/index.tsx b/apps/website/src/index.tsx index fddf7e502..5bf94c392 100644 --- a/apps/website/src/index.tsx +++ b/apps/website/src/index.tsx @@ -10,7 +10,7 @@ import SupportUs from './pages/SupportUs/SupportUs.js'; import { createContext } from 'preact'; import { useLayoutEffect, useState } from 'preact/hooks'; import { default as i18next, changeLanguage } from 'i18next'; -import { LOCALES } from './i18n'; +import { LOCALES, mapLocale } from './i18n'; import HttpApi from 'i18next-http-backend'; import { initReactI18next } from "react-i18next"; @@ -40,7 +40,7 @@ export function App(props: {repoStargazersCount: number}) { export function LocaleProvider({ children }) { const { path } = useLocation(); - const localeId = path.split('/')[1] || navigator.language; + const localeId = mapLocale(path.split('/')[1] || navigator.language); const [ loaded, setLoaded ] = useState(false); useLayoutEffect(() => {