mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
chore(lib): extract shared allMessages and resolveKey between context and server-translator
Lifts the per-locale message map and the dotted-key resolver out of `src/lib/i18n/context.tsx` and `src/lib/i18n/server-translator.ts` into a new `src/lib/i18n/shared-resolve.ts`. The two surfaces had each carried their own private copy of the same data structure and the same six-step path resolver; the maps drifted twice when a new locale was added during v1.4.18 and v1.4.25 polishing passes. Pinning both call-sites to a shared module keeps client and server fallback semantics in lockstep and shrinks the surface a future locale addition has to touch from two files to one.
This commit is contained in:
1 parent
3a7599c846
commit
3ec1f44d74
3 files changed
+61
-66
No files matched your search
@@ -11,41 +11,7 @@ import {
|
||||
} from "react";
|
||||
import { locales, defaultLocale, type Locale } from "./config";
|
||||
import { makeFormatters, type Formatters } from "../format-locale";
|
||||
|
||||
import deMessages from "../../../messages/de.json";
|
||||
import enMessages from "../../../messages/en.json";
|
||||
import frMessages from "../../../messages/fr.json";
|
||||
import esMessages from "../../../messages/es.json";
|
||||
import itMessages from "../../../messages/it.json";
|
||||
import plMessages from "../../../messages/pl.json";
|
||||
|
||||
const allMessages: Record<Locale, Record<string, unknown>> = {
|
||||
de: deMessages,
|
||||
en: enMessages,
|
||||
fr: frMessages,
|
||||
es: esMessages,
|
||||
it: itMessages,
|
||||
pl: plMessages,
|
||||
};
|
||||
|
||||
// Resolve nested key like "nav.dashboard" from a message object
|
||||
function resolveKey(
|
||||
messages: Record<string, unknown>,
|
||||
key: string,
|
||||
): string | undefined {
|
||||
const parts = key.split(".");
|
||||
let current: unknown = messages;
|
||||
|
||||
for (const part of parts) {
|
||||
if (current && typeof current === "object" && part in current) {
|
||||
current = (current as Record<string, unknown>)[part];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return typeof current === "string" ? current : undefined;
|
||||
}
|
||||
import { allMessages, resolveKey } from "./shared-resolve";
|
||||
|
||||
interface I18nContextValue {
|
||||
locale: Locale;
|
||||
|
||||
@@ -1,35 +1,5 @@
|
||||
import deMessages from "../../../messages/de.json";
|
||||
import enMessages from "../../../messages/en.json";
|
||||
import frMessages from "../../../messages/fr.json";
|
||||
import esMessages from "../../../messages/es.json";
|
||||
import itMessages from "../../../messages/it.json";
|
||||
import plMessages from "../../../messages/pl.json";
|
||||
import { defaultLocale, type Locale } from "./config";
|
||||
|
||||
const allMessages: Record<Locale, Record<string, unknown>> = {
|
||||
de: deMessages,
|
||||
en: enMessages,
|
||||
fr: frMessages,
|
||||
es: esMessages,
|
||||
it: itMessages,
|
||||
pl: plMessages,
|
||||
};
|
||||
|
||||
function resolveKey(
|
||||
messages: Record<string, unknown>,
|
||||
key: string,
|
||||
): string | undefined {
|
||||
const parts = key.split(".");
|
||||
let current: unknown = messages;
|
||||
for (const part of parts) {
|
||||
if (current && typeof current === "object" && part in current) {
|
||||
current = (current as Record<string, unknown>)[part];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return typeof current === "string" ? current : undefined;
|
||||
}
|
||||
import { allMessages, resolveKey } from "./shared-resolve";
|
||||
|
||||
export interface ServerTranslator {
|
||||
locale: Locale;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Shared message-bundle map and nested-key resolver used by both the
|
||||
* client-side `I18nProvider` in `context.tsx` and the server-side
|
||||
* `getServerTranslator()` in `server-translator.ts`.
|
||||
*
|
||||
* v1.4.27 B7 / BL-P4-11-S10 — the two surfaces previously each carried
|
||||
* their own private copy of `allMessages` plus a near-identical
|
||||
* `resolveKey` helper. The maps drifted twice during v1.4.18 / v1.4.25
|
||||
* polishing passes when a new locale was added; pinning both call-sites
|
||||
* to the same import keeps client and server fallback semantics in
|
||||
* lockstep and shrinks the surface a future locale addition has to
|
||||
* touch from two to one.
|
||||
*/
|
||||
import deMessages from "../../../messages/de.json";
|
||||
import enMessages from "../../../messages/en.json";
|
||||
import frMessages from "../../../messages/fr.json";
|
||||
import esMessages from "../../../messages/es.json";
|
||||
import itMessages from "../../../messages/it.json";
|
||||
import plMessages from "../../../messages/pl.json";
|
||||
import { type Locale } from "./config";
|
||||
|
||||
/**
|
||||
* Single source of truth for the per-locale message bundle.
|
||||
*
|
||||
* Both the client provider and the server translator import this map.
|
||||
* The bundles ship as static JSON imports so they tree-shake into the
|
||||
* client chunk that needs them and into the server chunk that needs
|
||||
* them without duplicating.
|
||||
*/
|
||||
export const allMessages: Record<Locale, Record<string, unknown>> = {
|
||||
de: deMessages,
|
||||
en: enMessages,
|
||||
fr: frMessages,
|
||||
es: esMessages,
|
||||
it: itMessages,
|
||||
pl: plMessages,
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve a dotted key (`nav.dashboard`) inside a flat-or-nested
|
||||
* message object. Returns `undefined` when the key path doesn't land
|
||||
* on a string leaf so the caller can chain a fallback bundle (English,
|
||||
* raw key) without ambiguity.
|
||||
*/
|
||||
export function resolveKey(
|
||||
messages: Record<string, unknown>,
|
||||
key: string,
|
||||
): string | undefined {
|
||||
const parts = key.split(".");
|
||||
let current: unknown = messages;
|
||||
for (const part of parts) {
|
||||
if (current && typeof current === "object" && part in current) {
|
||||
current = (current as Record<string, unknown>)[part];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return typeof current === "string" ? current : undefined;
|
||||
}
|
||||
Reference in new issue
Block a user