mirror of
https://github.com/temetro/temetro.git
synced 2026-08-06 17:07:40 +00:00
d237504af9
Add three UI locales (so/ar/de) with full ~1,660-key translations alongside en/fr, selectable in Settings → Profile. Arabic gets full right-to-left support: - config.ts registers the locales and exports a `dirFor` helper; an inline <head> script in layout.tsx sets <html dir/lang> before first paint (no RTL flash), and i18n-provider keeps them in sync on language change. - ~160 physical direction utilities converted to logical (ms/me/ps/pe/ start/end/text-start/text-end); directional chevrons/arrows get rtl:rotate-180; chat-bubble align variants fixed to logical. - IBM Plex Sans Arabic appended to the sans/heading font stacks for per-character Arabic fallback. - Language persists to the backend user_settings and re-applies on sign-in so it roams across devices (localStorage stays the offline source of truth). - New scripts/check-locales.mjs (npm run check-locales) enforces key/placeholder parity and Arabic CLDR plural completeness. Bump to 0.3.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import i18n from "i18next";
|
|
import LanguageDetector from "i18next-browser-languagedetector";
|
|
import { initReactI18next } from "react-i18next";
|
|
|
|
import en from "./locales/en/translation.json";
|
|
import fr from "./locales/fr/translation.json";
|
|
import so from "./locales/so/translation.json";
|
|
import ar from "./locales/ar/translation.json";
|
|
import de from "./locales/de/translation.json";
|
|
|
|
export const defaultNS = "translation";
|
|
|
|
// Add new languages here (and a matching JSON under locales/<lng>/translation.json).
|
|
export const resources = {
|
|
en: { translation: en },
|
|
fr: { translation: fr },
|
|
so: { translation: so },
|
|
ar: { translation: ar },
|
|
de: { translation: de },
|
|
} as const;
|
|
|
|
// Languages offered in the Settings → Profile switcher (label rendered there).
|
|
export const supportedLanguages = ["en", "fr", "so", "ar", "de"] as const;
|
|
|
|
// Right-to-left languages. Arabic is our only RTL locale today; keep this and the
|
|
// inline <head> script in app/layout.tsx (which can't import this module) in sync.
|
|
export const rtlLanguages = ["ar"] as const;
|
|
|
|
/** Writing direction for a BCP-47 language tag (e.g. "ar", "ar-SA"). */
|
|
export const dirFor = (lng: string | undefined): "rtl" | "ltr" =>
|
|
lng && rtlLanguages.some((r) => lng.startsWith(r)) ? "rtl" : "ltr";
|
|
|
|
if (!i18n.isInitialized) {
|
|
i18n
|
|
.use(LanguageDetector)
|
|
.use(initReactI18next)
|
|
.init({
|
|
resources,
|
|
defaultNS,
|
|
fallbackLng: "en",
|
|
// Keep this in sync with `resources` as languages grow.
|
|
supportedLngs: ["en", "fr", "so", "ar", "de"],
|
|
interpolation: { escapeValue: false },
|
|
detection: {
|
|
order: ["localStorage", "navigator", "htmlTag"],
|
|
caches: ["localStorage"],
|
|
},
|
|
});
|
|
}
|
|
|
|
export default i18n;
|