refactor(api): tidy the api and shared packages (#2733)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-13 17:37:48 +02:00
1 parent 580401d2dc
commit 5afbf67a70
333 files changed
+10180 -7910

No files matched your search

@@ -1,13 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type {TemplateCompiler} from '@fluxer/i18n/src/runtime/I18nTypes';
import type MessageFormat from '@messageformat/core';
export function compileTemplate<TValue, TVariables>(
compiler: TemplateCompiler<TValue, TVariables>,
template: TValue,
variables: TVariables,
mf: MessageFormat,
): TValue {
return compiler(template, variables, mf);
}
+18 -31
View File
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type {I18nResult, TemplateCompiler} from '@fluxer/i18n/src/runtime/I18nTypes';
import {getEffectiveStaticLocale} from '@fluxer/i18n/src/runtime/StaticLocale';
import MessageFormat from '@messageformat/core';
import {renderTemplate} from '@fluxer/i18n/src/runtime/RenderTemplate';
import {getEffectiveStaticLocale, hasStaticLocale} from '@fluxer/i18n/src/runtime/StaticLocale';
import type MessageFormat from '@messageformat/core';
export type StaticLocaleMessages<TKey extends string, TValue> = Partial<Record<TKey, TValue>>;
@@ -28,20 +29,11 @@ export function createStaticI18n<TKey extends string, TValue, TVariables>(
): StaticI18nModule<TKey, TValue, TVariables> {
const loadedLocales = new Set<string>([config.defaultLocale]);
const messageFormatCache = new Map<string, MessageFormat>();
function getMessageFormat(locale: string): MessageFormat {
const cached = messageFormatCache.get(locale);
if (cached) {
return cached;
}
const messageFormat = new MessageFormat(locale);
messageFormatCache.set(locale, messageFormat);
return messageFormat;
}
return {
getTemplate(key: TKey, locale: string | null, variables: TVariables): I18nResult<TKey, TValue> {
const effectiveLocale = getEffectiveStaticLocale(config, locale);
loadedLocales.add(effectiveLocale);
const sourceTemplate = config.defaultMessages[key];
const sourceTemplate = Object.hasOwn(config.defaultMessages, key) ? config.defaultMessages[key] : undefined;
if (sourceTemplate === undefined) {
return {
ok: false,
@@ -53,7 +45,11 @@ export function createStaticI18n<TKey extends string, TValue, TVariables>(
locale: effectiveLocale,
};
}
const translatedTemplate = config.localeMessages[effectiveLocale]?.[key];
const localeMessages = Object.hasOwn(config.localeMessages, effectiveLocale)
? config.localeMessages[effectiveLocale]
: undefined;
const translatedTemplate =
localeMessages != null && Object.hasOwn(localeMessages, key) ? localeMessages[key] : undefined;
const template = translatedTemplate ?? sourceTemplate;
const validationError = config.validateVariables?.(key, template, variables);
if (validationError) {
@@ -67,27 +63,18 @@ export function createStaticI18n<TKey extends string, TValue, TVariables>(
locale: effectiveLocale,
};
}
try {
return {
ok: true,
value: compile(template, variables, getMessageFormat(effectiveLocale)),
locale: effectiveLocale,
};
} catch (error) {
return {
ok: false,
error: {
kind: 'compile-failed',
key,
message: error instanceof Error ? error.message : 'Failed to compile template',
},
locale: effectiveLocale,
};
}
return renderTemplate({
key,
locale: effectiveLocale,
template,
variables,
compile,
messageFormatCache,
});
},
hasLocale(locale: string): boolean {
const normalizedLocale = config.normalizeLocale?.(locale) ?? locale;
return normalizedLocale === config.defaultLocale || config.localeMessages[normalizedLocale] !== undefined;
return hasStaticLocale(config, normalizedLocale);
},
getLoadedLocales(): Set<string> {
return new Set(loadedLocales);
+9 -29
View File
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {compileTemplate} from '@fluxer/i18n/src/runtime/CompileTemplate';
import {getEffectiveLocale} from '@fluxer/i18n/src/runtime/GetEffectiveLocale';
import type {I18nResult, I18nState, TemplateCompiler} from '@fluxer/i18n/src/runtime/I18nTypes';
import {loadLocaleIfNotLoaded} from '@fluxer/i18n/src/runtime/LoadLocale';
import MessageFormat from '@messageformat/core';
import {renderTemplate} from '@fluxer/i18n/src/runtime/RenderTemplate';
export function getTemplate<TKey extends string, TValue, TVariables>(
state: I18nState<TKey, TValue, TVariables>,
@@ -41,31 +40,12 @@ export function getTemplate<TKey extends string, TValue, TVariables>(
locale: effectiveLocale,
};
}
try {
const compiled = compileTemplate(compile, template, variables, getMessageFormat(state, effectiveLocale));
return {ok: true, value: compiled, locale: effectiveLocale};
} catch (error) {
return {
ok: false,
error: {
kind: 'compile-failed',
key,
message: error instanceof Error ? error.message : 'Failed to compile template',
},
locale: effectiveLocale,
};
}
}
function getMessageFormat<TKey extends string, TValue, TVariables>(
state: I18nState<TKey, TValue, TVariables>,
locale: string,
): MessageFormat {
const cached = state.messageFormatCache.get(locale);
if (cached) {
return cached;
}
const mf = new MessageFormat(locale);
state.messageFormatCache.set(locale, mf);
return mf;
return renderTemplate({
key,
locale: effectiveLocale,
template,
variables,
compile,
messageFormatCache: state.messageFormatCache,
});
}
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type {I18nResult, TemplateCompiler} from '@fluxer/i18n/src/runtime/I18nTypes';
import MessageFormat from '@messageformat/core';
interface TemplateRenderOptions<TKey extends string, TValue, TVariables> {
key: TKey;
locale: string;
template: TValue;
variables: TVariables;
compile: TemplateCompiler<TValue, TVariables>;
messageFormatCache: Map<string, MessageFormat>;
}
export function renderTemplate<TKey extends string, TValue, TVariables>({
key,
locale,
template,
variables,
compile,
messageFormatCache,
}: TemplateRenderOptions<TKey, TValue, TVariables>): I18nResult<TKey, TValue> {
try {
let messageFormat = messageFormatCache.get(locale);
if (!messageFormat) {
messageFormat = new MessageFormat(locale);
messageFormatCache.set(locale, messageFormat);
}
return {
ok: true,
value: compile(template, variables, messageFormat),
locale,
};
} catch (error) {
return {
ok: false,
error: {
kind: 'compile-failed',
key,
message: error instanceof Error ? error.message : 'Failed to compile template',
},
locale,
};
}
}
+11 -4
View File
@@ -2,6 +2,16 @@
import type {StaticI18nConfig} from '@fluxer/i18n/src/runtime/CreateStaticI18n';
export function hasStaticLocale<TKey extends string, TValue, TVariables>(
config: StaticI18nConfig<TKey, TValue, TVariables>,
normalizedLocale: string,
): boolean {
return (
normalizedLocale === config.defaultLocale ||
(Object.hasOwn(config.localeMessages, normalizedLocale) && config.localeMessages[normalizedLocale] !== undefined)
);
}
export function getEffectiveStaticLocale<TKey extends string, TValue, TVariables>(
config: StaticI18nConfig<TKey, TValue, TVariables>,
locale: string | null | undefined,
@@ -10,10 +20,7 @@ export function getEffectiveStaticLocale<TKey extends string, TValue, TVariables
return config.defaultLocale;
}
const normalizedLocale = config.normalizeLocale?.(locale) ?? locale;
if (normalizedLocale === config.defaultLocale) {
return config.defaultLocale;
}
if (config.localeMessages[normalizedLocale] === undefined) {
if (!hasStaticLocale(config, normalizedLocale)) {
config.onWarning?.(`Unsupported locale, falling back to ${config.defaultLocale}: ${locale}`);
return config.defaultLocale;
}