feat(electrobun): 10 locales + system language auto-detection
This commit is contained in:
parent
aae86a4001
commit
7a8df2c216
1 changed files with 30 additions and 4 deletions
|
|
@ -21,9 +21,16 @@ export interface LocaleMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AVAILABLE_LOCALES: LocaleMeta[] = [
|
export const AVAILABLE_LOCALES: LocaleMeta[] = [
|
||||||
{ tag: 'en', label: 'English', nativeLabel: 'English', dir: 'ltr' },
|
{ tag: 'en', label: 'English', nativeLabel: 'English', dir: 'ltr' },
|
||||||
{ tag: 'pl', label: 'Polish', nativeLabel: 'Polski', dir: 'ltr' },
|
{ tag: 'de', label: 'German', nativeLabel: 'Deutsch', dir: 'ltr' },
|
||||||
{ tag: 'ar', label: 'Arabic', nativeLabel: '\u0627\u0644\u0639\u0631\u0628\u064a\u0629', dir: 'rtl' },
|
{ tag: 'es', label: 'Spanish', nativeLabel: 'Español', dir: 'ltr' },
|
||||||
|
{ tag: 'fr', label: 'French', nativeLabel: 'Français', dir: 'ltr' },
|
||||||
|
{ tag: 'ja', label: 'Japanese', nativeLabel: '日本語', dir: 'ltr' },
|
||||||
|
{ tag: 'pl', label: 'Polish', nativeLabel: 'Polski', dir: 'ltr' },
|
||||||
|
{ tag: 'uk', label: 'Ukrainian', nativeLabel: 'Українська', dir: 'ltr' },
|
||||||
|
{ tag: 'zh', label: 'Chinese', nativeLabel: '中文', dir: 'ltr' },
|
||||||
|
{ tag: 'ar', label: 'Arabic', nativeLabel: 'العربية', dir: 'rtl' },
|
||||||
|
{ tag: 'he', label: 'Hebrew', nativeLabel: 'עברית', dir: 'rtl' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// ── Reactive state ───────────────────────────────────────────────────────────
|
// ── Reactive state ───────────────────────────────────────────────────────────
|
||||||
|
|
@ -44,8 +51,15 @@ let _intl: IntlShape<string> = createIntl({ locale: 'en', messages: {} }, cache)
|
||||||
|
|
||||||
const loaders: Record<string, () => Promise<Messages>> = {
|
const loaders: Record<string, () => Promise<Messages>> = {
|
||||||
en: () => import('../../locales/en.json').then(m => m.default as Messages),
|
en: () => import('../../locales/en.json').then(m => m.default as Messages),
|
||||||
|
de: () => import('../../locales/de.json').then(m => m.default as Messages),
|
||||||
|
es: () => import('../../locales/es.json').then(m => m.default as Messages),
|
||||||
|
fr: () => import('../../locales/fr.json').then(m => m.default as Messages),
|
||||||
|
ja: () => import('../../locales/ja.json').then(m => m.default as Messages),
|
||||||
pl: () => import('../../locales/pl.json').then(m => m.default as Messages),
|
pl: () => import('../../locales/pl.json').then(m => m.default as Messages),
|
||||||
|
uk: () => import('../../locales/uk.json').then(m => m.default as Messages),
|
||||||
|
zh: () => import('../../locales/zh.json').then(m => m.default as Messages),
|
||||||
ar: () => import('../../locales/ar.json').then(m => m.default as Messages),
|
ar: () => import('../../locales/ar.json').then(m => m.default as Messages),
|
||||||
|
he: () => import('../../locales/he.json').then(m => m.default as Messages),
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Public API ───────────────────────────────────────────────────────────────
|
// ── Public API ───────────────────────────────────────────────────────────────
|
||||||
|
|
@ -140,8 +154,9 @@ export async function initI18n(): Promise<void> {
|
||||||
// Load PluralRules polyfill for WebKitGTK (needed for Arabic 6-form plurals)
|
// Load PluralRules polyfill for WebKitGTK (needed for Arabic 6-form plurals)
|
||||||
await import('@formatjs/intl-pluralrules/polyfill-force.js').catch(() => {});
|
await import('@formatjs/intl-pluralrules/polyfill-force.js').catch(() => {});
|
||||||
|
|
||||||
let savedLocale = 'en';
|
let savedLocale: string | null = null;
|
||||||
|
|
||||||
|
// 1. Try saved preference from settings
|
||||||
try {
|
try {
|
||||||
const result = await appRpc?.request['settings.get']({ key: 'locale' });
|
const result = await appRpc?.request['settings.get']({ key: 'locale' });
|
||||||
if (result?.value && loaders[result.value]) {
|
if (result?.value && loaders[result.value]) {
|
||||||
|
|
@ -149,5 +164,16 @@ export async function initI18n(): Promise<void> {
|
||||||
}
|
}
|
||||||
} catch { /* use default */ }
|
} catch { /* use default */ }
|
||||||
|
|
||||||
|
// 2. If no saved preference, detect system language
|
||||||
|
if (!savedLocale) {
|
||||||
|
const systemLang = navigator.language ?? navigator.languages?.[0] ?? 'en';
|
||||||
|
const langBase = systemLang.split('-')[0].toLowerCase(); // 'en-US' → 'en'
|
||||||
|
if (loaders[langBase]) {
|
||||||
|
savedLocale = langBase;
|
||||||
|
} else {
|
||||||
|
savedLocale = 'en'; // fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await setLocale(savedLocale);
|
await setLocale(savedLocale);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue