- Replaced @TIER: TRIVIAL with @COMPLEXITY: 1 - Replaced @TIER: STANDARD with @COMPLEXITY: 3 - Replaced @TIER: CRITICAL with @COMPLEXITY: 5 - Manually elevated specific critical/complex components to levels 2 and 4 - Ignored legacy, specs, and node_modules directories - Updated generated semantic map
83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
// [DEF:i18n:Module]
|
|
//
|
|
// @COMPLEXITY: 3
|
|
// @SEMANTICS: i18n, localization, svelte-store, translation
|
|
// @PURPOSE: Centralized internationalization management using Svelte stores.
|
|
// @LAYER: Infra
|
|
// @RELATION: DEPENDS_ON -> locales/ru.json
|
|
// @RELATION: DEPENDS_ON -> locales/en.json
|
|
//
|
|
// @INVARIANT: Locale must be either 'ru' or 'en'.
|
|
// @INVARIANT: Persistence is handled via LocalStorage.
|
|
|
|
// [SECTION: IMPORTS]
|
|
import { writable, derived } from 'svelte/store';
|
|
import ru from './locales/ru.json';
|
|
import en from './locales/en.json';
|
|
// [/SECTION: IMPORTS]
|
|
|
|
const translations = { ru, en };
|
|
type Locale = keyof typeof translations;
|
|
|
|
/**
|
|
* @purpose Determines the starting locale.
|
|
* @returns {Locale}
|
|
*/
|
|
const getInitialLocale = (): Locale => {
|
|
if (typeof localStorage !== 'undefined') {
|
|
const saved = localStorage.getItem('locale');
|
|
if (saved === 'ru' || saved === 'en') return saved as Locale;
|
|
}
|
|
return 'ru';
|
|
};
|
|
|
|
// [DEF:locale:Store]
|
|
/**
|
|
* @purpose Holds the current active locale string.
|
|
* @side_effect Writes to LocalStorage on change.
|
|
*/
|
|
export const locale = writable<Locale>(getInitialLocale());
|
|
|
|
if (typeof localStorage !== 'undefined') {
|
|
locale.subscribe((val) => localStorage.setItem('locale', val));
|
|
}
|
|
// [/DEF:locale:Store]
|
|
|
|
// [DEF:t:Store]
|
|
/**
|
|
* @purpose Derived store providing the translation dictionary.
|
|
* @relation BINDS_TO -> locale
|
|
*/
|
|
export const t = derived(locale, ($locale) => {
|
|
const dictionary = (translations[$locale] || translations.ru) as any;
|
|
return dictionary;
|
|
});
|
|
// [/DEF:t:Store]
|
|
|
|
// [DEF:_:Function]
|
|
/**
|
|
* @purpose Get translation by key path.
|
|
* @param key - Translation key path (e.g., 'nav.dashboard')
|
|
* @returns Translation string or key if not found
|
|
*/
|
|
export function _(key: string): string {
|
|
const currentLocale = getInitialLocale();
|
|
const dictionary = (translations[currentLocale] || translations.ru) as any;
|
|
|
|
// Navigate through nested keys
|
|
const keys = key.split('.');
|
|
let value: any = dictionary;
|
|
|
|
for (const k of keys) {
|
|
if (value && typeof value === 'object' && k in value) {
|
|
value = value[k];
|
|
} else {
|
|
return key; // Return key if translation not found
|
|
}
|
|
}
|
|
|
|
return typeof value === 'string' ? value : key;
|
|
}
|
|
// [/DEF:_:Function]
|
|
|
|
// [/DEF:i18n:Module]
|