/** * 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(); 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 { 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 { 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(); }