mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
feat(i18n): deep-merge EN fallback to fill missing locale keys (B/G1)
Export deepMergeFallback and apply it in getRequestConfig so all 39 non-EN locales receive EN text for any key absent in their JSON file. Locale-specific translations always win; EN fills gaps only.
This commit is contained in:
@@ -3,23 +3,57 @@ import { cookies, headers } from "next/headers";
|
||||
import { LOCALES, DEFAULT_LOCALE, LOCALE_COOKIE } from "./config";
|
||||
import type { Locale } from "./config";
|
||||
|
||||
const FALLBACK_LOCALE = "en";
|
||||
|
||||
/**
|
||||
* Deep merge that mutates `target` with values from `source`.
|
||||
* If both have an object at the same key, recurse.
|
||||
* Otherwise prefer the existing value in `target` (locale-specific wins).
|
||||
*/
|
||||
export function deepMergeFallback(
|
||||
target: Record<string, unknown>,
|
||||
source: Record<string, unknown>
|
||||
): Record<string, unknown> {
|
||||
for (const [key, sourceValue] of Object.entries(source)) {
|
||||
const targetValue = target[key];
|
||||
if (
|
||||
sourceValue !== null &&
|
||||
typeof sourceValue === "object" &&
|
||||
!Array.isArray(sourceValue) &&
|
||||
targetValue !== null &&
|
||||
typeof targetValue === "object" &&
|
||||
!Array.isArray(targetValue)
|
||||
) {
|
||||
deepMergeFallback(targetValue as Record<string, unknown>, sourceValue as Record<string, unknown>);
|
||||
} else if (targetValue === undefined) {
|
||||
target[key] = sourceValue;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
export default getRequestConfig(async () => {
|
||||
// 1. Try cookie
|
||||
const cookieStore = await cookies();
|
||||
let locale: string = cookieStore.get(LOCALE_COOKIE)?.value || "";
|
||||
|
||||
// 2. Try custom header (set by middleware)
|
||||
if (!locale) {
|
||||
const headerStore = await headers();
|
||||
locale = headerStore.get("x-locale") || "";
|
||||
}
|
||||
|
||||
// 3. Validate & fallback
|
||||
if (!LOCALES.includes(locale as Locale)) {
|
||||
locale = DEFAULT_LOCALE;
|
||||
}
|
||||
|
||||
const messages = (await import(`./messages/${locale}.json`)).default;
|
||||
const localeMessages = (await import(`./messages/${locale}.json`)).default;
|
||||
|
||||
// G1: fall back to EN for any missing key. EN is loaded only once per request
|
||||
// and only when the active locale is not EN itself (no-op).
|
||||
let messages = localeMessages as Record<string, unknown>;
|
||||
if (locale !== FALLBACK_LOCALE) {
|
||||
const fallbackMessages = (await import(`./messages/${FALLBACK_LOCALE}.json`)).default as Record<string, unknown>;
|
||||
messages = deepMergeFallback({ ...localeMessages }, fallbackMessages);
|
||||
}
|
||||
|
||||
return {
|
||||
locale,
|
||||
|
||||
Reference in New Issue
Block a user