57 lines
2.0 KiB
TypeScript
57 lines
2.0 KiB
TypeScript
import i18n from 'i18next';
|
|
import { globalStorageAdapter } from './setup';
|
|
|
|
/**
|
|
* Changes the active language, saves the preference locally, and optionally syncs with the backend.
|
|
*
|
|
* @param newLng The new language code (e.g., 'en', 'id')
|
|
* @param syncCallback An optional callback to sync the preference to the backend. It receives the new language and the previous language.
|
|
*/
|
|
export async function changeLanguage(
|
|
newLng: string,
|
|
syncCallback?: (newLng: string, prevLng: string) => Promise<void>,
|
|
): Promise<void> {
|
|
const prevLng = i18n.language;
|
|
|
|
if (prevLng === newLng) return;
|
|
|
|
// 1. Update local storage & i18next optimistically
|
|
if (globalStorageAdapter) {
|
|
await globalStorageAdapter.setLanguage(newLng);
|
|
}
|
|
await i18n.changeLanguage(newLng);
|
|
|
|
// 2. Trigger optional backend sync
|
|
if (syncCallback) {
|
|
try {
|
|
await syncCallback(newLng, prevLng);
|
|
} catch (error) {
|
|
console.error('[i18n] Backend sync failed, rolling back language', error);
|
|
// Rollback on failure
|
|
if (globalStorageAdapter) {
|
|
await globalStorageAdapter.setLanguage(prevLng);
|
|
}
|
|
await i18n.changeLanguage(prevLng);
|
|
throw error; // Rethrow so the caller can show an error toast
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Injects tenant-specific vocabulary overrides dynamically at runtime.
|
|
*
|
|
* Uses a deep-merge strategy. Overrides are applied to the currently active language,
|
|
* or across all loaded languages if needed.
|
|
*
|
|
* @param namespace The i18n namespace to override (e.g., 'common', 'booking')
|
|
* @param overrides A deeply nested object containing the overridden string keys and values.
|
|
* @param lng Specific language to override. Defaults to currently active language.
|
|
*/
|
|
export function applyTenantOverrides(namespace: string, overrides: Record<string, unknown>, lng?: string): void {
|
|
const targetLng = lng || i18n.language;
|
|
|
|
// deep: true -> merges with existing keys rather than replacing the whole namespace
|
|
// overwrite: true -> allows replacing existing specific keys
|
|
i18n.addResourceBundle(targetLng, namespace, overrides, true, true);
|
|
}
|