locale upgrade
This commit is contained in:
133
lib/i18n-loader.ts
Normal file
133
lib/i18n-loader.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* i18n Loader with Directus + JSON Fallback
|
||||
* - Fetches from Directus first
|
||||
* - Falls back to JSON files if not found
|
||||
* - Caches results (5 min TTL)
|
||||
*/
|
||||
|
||||
import { getMessage, getContentPage } from './directus';
|
||||
import enMessages from '@/messages/en.json';
|
||||
import deMessages from '@/messages/de.json';
|
||||
|
||||
const jsonFallback = { en: enMessages, de: deMessages };
|
||||
|
||||
// Simple in-memory cache
|
||||
const cache = new Map<string, { value: any; expires: number }>();
|
||||
|
||||
function setCached(key: string, value: any, ttlSeconds = 300) {
|
||||
cache.set(key, { value, expires: Date.now() + ttlSeconds * 1000 });
|
||||
}
|
||||
|
||||
function getCached(key: string): any | null {
|
||||
const hit = cache.get(key);
|
||||
if (!hit) return null;
|
||||
if (Date.now() > hit.expires) {
|
||||
cache.delete(key);
|
||||
return null;
|
||||
}
|
||||
return hit.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a localized message by key
|
||||
* Tries: Directus (requested locale) → Directus (EN) → JSON (requested locale) → JSON (EN)
|
||||
*/
|
||||
export async function getLocalizedMessage(
|
||||
key: string,
|
||||
locale: string
|
||||
): Promise<string> {
|
||||
const cacheKey = `msg:${key}:${locale}`;
|
||||
const cached = getCached(cacheKey);
|
||||
if (cached !== null) return cached;
|
||||
|
||||
// Try Directus with requested locale
|
||||
const dbValue = await getMessage(key, locale);
|
||||
if (dbValue) {
|
||||
setCached(cacheKey, dbValue);
|
||||
return dbValue;
|
||||
}
|
||||
|
||||
// Fallback to EN in Directus if not EN already
|
||||
if (locale !== 'en') {
|
||||
const dbValueEn = await getMessage(key, 'en');
|
||||
if (dbValueEn) {
|
||||
setCached(cacheKey, dbValueEn);
|
||||
return dbValueEn;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to JSON file (normalize locale to 'en' or 'de')
|
||||
const normalizedLocale = locale.startsWith('de') ? 'de' : 'en';
|
||||
const jsonValue = getNestedValue(jsonFallback[normalizedLocale as 'en' | 'de'], key);
|
||||
if (jsonValue) {
|
||||
setCached(cacheKey, jsonValue);
|
||||
return jsonValue;
|
||||
}
|
||||
|
||||
// Fallback to EN JSON
|
||||
if (normalizedLocale !== 'en') {
|
||||
const jsonValueEn = getNestedValue(jsonFallback['en'], key);
|
||||
if (jsonValueEn) {
|
||||
setCached(cacheKey, jsonValueEn);
|
||||
return jsonValueEn;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: return the key itself
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a localized content page by slug
|
||||
* Tries: Directus (requested locale) → Directus (EN)
|
||||
*/
|
||||
export async function getLocalizedContent(
|
||||
slug: string,
|
||||
locale: string
|
||||
): Promise<any | null> {
|
||||
const cacheKey = `page:${slug}:${locale}`;
|
||||
const cached = getCached(cacheKey);
|
||||
if (cached !== null) return cached;
|
||||
if (cached === null && cache.has(cacheKey)) return null; // Already checked, not found
|
||||
|
||||
// Try Directus with requested locale
|
||||
const dbPage = await getContentPage(slug, locale);
|
||||
if (dbPage) {
|
||||
setCached(cacheKey, dbPage);
|
||||
return dbPage;
|
||||
}
|
||||
|
||||
// Fallback to EN in Directus
|
||||
if (locale !== 'en') {
|
||||
const dbPageEn = await getContentPage(slug, 'en');
|
||||
if (dbPageEn) {
|
||||
setCached(cacheKey, dbPageEn);
|
||||
return dbPageEn;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
setCached(cacheKey, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Get nested value from object
|
||||
* Example: "nav.home" → obj.nav.home
|
||||
*/
|
||||
function getNestedValue(obj: any, path: string): any {
|
||||
const keys = path.split('.');
|
||||
let value = obj;
|
||||
for (const key of keys) {
|
||||
value = value?.[key];
|
||||
if (value === undefined) return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cache (useful for webhooks/revalidation)
|
||||
*/
|
||||
export function clearI18nCache() {
|
||||
cache.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user