62 lines
3.2 KiB
JavaScript
62 lines
3.2 KiB
JavaScript
/**
|
|
* languages.js — the language list for the app wrapper's locale dropdown.
|
|
*
|
|
* PORTED from dx-life's single source of truth: `config/languages.ts`
|
|
* (LANGUAGES / ENABLED_LANGUAGES / hideFromSwitcher). Kept DELIBERATELY MINIMAL:
|
|
* dx-life's version also carries DeepL codes, Bible translation ids, glossary ids
|
|
* and font flags — all of which belong to the CMS/translation pipeline, not to a
|
|
* map wrapper. Only the four fields the switcher actually renders are kept, plus
|
|
* `dir` (RTL) because the wrapper has to flip layout direction.
|
|
*
|
|
* WHY NOT A LIBRARY: the switcher is ~30 lines of state over this array. Adding a
|
|
* dependency to render a <select> would be more complexity, not less — and every
|
|
* candidate assumes a router (dx-life's uses `switchLocalePath()` because it
|
|
* routes /es, /fr …). The wrapper is a STATIC app with no locale routing: it just
|
|
* needs to emit a code. So: same DATA, simpler MECHANISM.
|
|
*
|
|
* THE CONTRACT (already built into the bundles — do not reinvent):
|
|
* ProfileLoader reads `profile-config.locale` (falls back to `.lang`), lowercases
|
|
* it, strips any region suffix ('pt-BR' -> 'pt'), drives the bundle's i18n global
|
|
* locale from it, and provides `lang` to descendants. So switching language =
|
|
* re-setting profile-config.locale on the mounted element. Nothing else.
|
|
*/
|
|
|
|
export const LANGUAGES = [
|
|
{ code: 'en', name: 'English', nativeName: 'English', flag: '🇺🇸' },
|
|
{ code: 'es', name: 'Spanish', nativeName: 'Español', flag: '🇪🇸' },
|
|
{ code: 'fr', name: 'French', nativeName: 'Français', flag: '🇫🇷' },
|
|
{ code: 'pt', name: 'Portuguese', nativeName: 'Português', flag: '🇵🇹' },
|
|
{ code: 'ar', name: 'Arabic', nativeName: 'العربية', flag: '🇸🇦', dir: 'rtl' },
|
|
{ code: 'ru', name: 'Russian', nativeName: 'Русский', flag: '🇷🇺' },
|
|
// Present in dx-life but hidden from its public switcher (hideFromSwitcher: true).
|
|
// Kept here, flagged, so the list stays a faithful mirror of the source of truth.
|
|
{ code: 'de', name: 'German', nativeName: 'Deutsch', flag: '🇩🇪', hideFromSwitcher: true },
|
|
{ code: 'hi', name: 'Hindi', nativeName: 'हिन्दी', flag: '🇮🇳', hideFromSwitcher: true },
|
|
// enabled:false in dx-life (routable/translatable but not offered): it, zh, ro.
|
|
]
|
|
|
|
/** Languages offered in the dropdown. */
|
|
export const SWITCHER_LANGUAGES = LANGUAGES.filter(l => !l.hideFromSwitcher)
|
|
|
|
export function getLanguage(code) {
|
|
return LANGUAGES.find(l => l.code === code)
|
|
}
|
|
|
|
/** Normalise any incoming tag to a supported code ('pt-BR' -> 'pt'; unknown -> 'en'). */
|
|
export function normaliseLocale(tag) {
|
|
const base = String(tag || '').split('-')[0].toLowerCase()
|
|
return LANGUAGES.some(l => l.code === base) ? base : 'en'
|
|
}
|
|
|
|
/** Persisted choice (survives reload), defaulting to the browser language. */
|
|
const KEY = 'doxa-maps:locale'
|
|
export function loadLocale() {
|
|
try {
|
|
const saved = localStorage.getItem(KEY)
|
|
if (saved) return normaliseLocale(saved)
|
|
} catch (_) { /* storage may be unavailable */ }
|
|
return normaliseLocale(navigator?.language)
|
|
}
|
|
export function saveLocale(code) {
|
|
try { localStorage.setItem(KEY, code) } catch (_) { /* non-fatal */ }
|
|
}
|