mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix(i18n): deep-merge en.json as fallback for locales missing keys
D12 of master-plan-21 assumed next-intl had a built-in fallback to EN
already configured. It did not — request.ts loaded only
messages/${locale}.json and no getMessageFallback was defined, so any
key absent in the user's locale rendered the key path literally
(for example "memory.concept.title").
Plan 21 added 156 memory.* keys to en and pt-BR but the other 39
locales kept only the pre-existing 36 memory.* keys, so users on those
locales saw raw key paths across the new Memory studio.
Fix: load en.json as the base and deep-merge the locale-specific
messages on top. Existing translations are untouched; only missing
keys fall back to English. Satisfies §7 "i18n 41 locales".
This commit is contained in:
@@ -3,6 +3,34 @@ import { cookies, headers } from "next/headers";
|
||||
import { LOCALES, DEFAULT_LOCALE, LOCALE_COOKIE } from "./config";
|
||||
import type { Locale } from "./config";
|
||||
|
||||
// Deep-merge fallback messages so locales that lack newer keys (e.g. memory.*
|
||||
// added by plan 21) silently fall back to EN instead of rendering the key path.
|
||||
function mergeMessages(
|
||||
fallback: Record<string, unknown>,
|
||||
override: Record<string, unknown>
|
||||
): Record<string, unknown> {
|
||||
const out: Record<string, unknown> = { ...fallback };
|
||||
for (const [k, v] of Object.entries(override)) {
|
||||
const baseVal = out[k];
|
||||
if (
|
||||
v !== null &&
|
||||
typeof v === "object" &&
|
||||
!Array.isArray(v) &&
|
||||
baseVal !== null &&
|
||||
typeof baseVal === "object" &&
|
||||
!Array.isArray(baseVal)
|
||||
) {
|
||||
out[k] = mergeMessages(
|
||||
baseVal as Record<string, unknown>,
|
||||
v as Record<string, unknown>
|
||||
);
|
||||
} else {
|
||||
out[k] = v;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export default getRequestConfig(async () => {
|
||||
// 1. Try cookie
|
||||
const cookieStore = await cookies();
|
||||
@@ -19,10 +47,16 @@ export default getRequestConfig(async () => {
|
||||
locale = DEFAULT_LOCALE;
|
||||
}
|
||||
|
||||
const messages = (await import(`./messages/${locale}.json`)).default;
|
||||
const enMessages = (await import("./messages/en.json"))
|
||||
.default as Record<string, unknown>;
|
||||
if (locale === "en") {
|
||||
return { locale, messages: enMessages };
|
||||
}
|
||||
const localeMessages = (await import(`./messages/${locale}.json`))
|
||||
.default as Record<string, unknown>;
|
||||
|
||||
return {
|
||||
locale,
|
||||
messages,
|
||||
messages: mergeMessages(enMessages, localeMessages),
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user