Files
ss-tools/frontend/src/lib/i18n/index.ts
busya 274510fc38 refactor(semantics): migrate legacy @TIER to @COMPLEXITY annotations
- 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
2026-03-16 10:06:44 +03:00

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]