Files
homarr/packages/translation/src/request.ts
T
Thomas Camlong 33293ba1cf refactor: simplify Phase 1 infrastructure code
- cache-invalidation: extract isExpectedRevalidateError helper
- integration-data-cache: flatten early-return chain, extract eviction
- redis-handler: extract StoredEntry type, readStreamBody, ensureConnected
- svg-purify: single getOwnPropertyDescriptor lookup per prop
- session-scoped-providers: simplify auth flow
- retryable-loader: use function declarations
- translation/request: replace spread-in-reduce with for loop
2026-08-07 21:04:42 +02:00

52 lines
1.9 KiB
TypeScript

import deepmerge from "deepmerge";
import { getRequestConfig } from "next-intl/server";
import type { TranslationObject } from ".";
import { fallbackLocale, isLocaleSupported } from ".";
import type { SupportedLanguage } from "./config";
import { createLanguageMapping } from "./mapping";
// ponytail: module-level memo — one merged object per locale used (~250-400 KB each).
// Ceiling: ~2 MB for 5 active locales. Upgrade: evict when size > 8.
const mergedMessages = new Map<SupportedLanguage, Promise<TranslationObject>>();
function loadMessagesAsync(locale: SupportedLanguage): Promise<TranslationObject> {
const existing = mergedMessages.get(locale);
if (existing) return existing;
const promise = (async () => {
const languageMap = createLanguageMapping();
const current = removeEmptyTranslations((await languageMap[locale]()).default) as TranslationObject;
if (locale === fallbackLocale) return current;
const fallback = (await languageMap[fallbackLocale]()).default;
return deepmerge(fallback, current) as TranslationObject;
})();
mergedMessages.set(locale, promise);
void promise.catch(() => {
if (mergedMessages.get(locale) === promise) mergedMessages.delete(locale);
});
return promise;
}
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale: SupportedLanguage =
requested && isLocaleSupported(requested) ? (requested as SupportedLanguage) : fallbackLocale;
return { locale, messages: await loadMessagesAsync(locale) };
});
function removeEmptyTranslations(translations: Record<string, unknown>): Record<string, unknown> {
const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(translations)) {
if (typeof value === "string") {
if (value.trim() !== "") result[key] = value;
continue;
}
result[key] = removeEmptyTranslations(value as Record<string, unknown>);
}
return result;
}