@starterapp/i18n-core
Locale configuration, fallback chains, and Accept-Language negotiation helpers.
@starterapp/i18n-core owns StarterApp’s locale metadata. It exposes pure utilities for registering locales, managing fallback chains, and interpreting Accept-Language headers. Import it from server-only contexts (middleware, Server Components, scripts, tests).
Heads up
This package is server-only. Importing it in the browser throws an error.
Locale Registry
export const DEFAULT_LOCALE = "en";
export function registerLocaleDefinition(definition: LocaleDefinition): void;
export function getLocaleDefinition(localeId: string): LocaleDefinition | null;
export function getEnabledLocaleIds(): string[];
export function enableLocale(localeId: string): void;
export function resetEnabledLocales(): void;
export function isI18nEnabled(): boolean;
Pro Tip
Only English ships in the base config. Apps register additional locales with registerLocaleDefinition() and provide their own dictionaries.
Fallback & Negotiation
export function getFallbackChain(localeId: string): string[];
export function parseAcceptLanguage(header?: string): AcceptLanguagePreference[];
export function selectLocaleFromAcceptLanguage(
preferences: AcceptLanguagePreference[],
permittedLocales: string[]
): string | null;
These utilities power the middleware helpers in @starterapp/i18n-next, keeping Accept-Language parsing and fallback ordering consistent.
Usage Examples
Registering a Locale
import { registerLocaleDefinition } from "@starterapp/i18n-core";
registerLocaleDefinition({
id: "es",
label: "Español",
dir: "ltr",
fallback: ["es", "en"],
enabled: true,
coverageThreshold: 0.95,
});
Reading Enabled Locales in Middleware
import { DEFAULT_LOCALE, isI18nEnabled } from "@starterapp/i18n-core";
const activeLocale = isI18nEnabled()
? request.headers.get("x-starterapp-locale") ?? DEFAULT_LOCALE
: DEFAULT_LOCALE;
Testing Helpers
Use resetEnabledLocales() and registerLocaleDefinition() in Vitest to keep tests isolated:
import {
enableLocale,
registerLocaleDefinition,
resetEnabledLocales,
} from "@starterapp/i18n-core";
beforeEach(() => {
resetEnabledLocales();
registerLocaleDefinition({
id: "es",
label: "Español",
dir: "ltr",
fallback: ["es", "en"],
enabled: true,
coverageThreshold: 0.95,
});
enableLocale("es");
});
The negotiation unit tests in the package demonstrate both single-locale and multi-locale flows.