Load Compiled Catalogs
After running lingui compile, each locale produces a compiled catalog file (.ts or .js).
This guide covers how to import those files and wire them into the Lingui runtime.
Recommended catalog setup file
Section titled “Recommended catalog setup file”Keep all locale imports and the SupportedLocale type in one place:
import { messages as en } from "./locales/en";import { messages as ja } from "./locales/ja";
export const catalog = { en, ja,} as const;
export type SupportedLocale = keyof typeof catalog;The SupportedLocale type is derived from the object keys, so adding or removing a locale
automatically updates the type. No need to keep a separate locale list in sync with lingui.config.
Static imports
Section titled “Static imports”Static imports are the simplest approach. All catalog files are included in the initial bundle and switching is synchronous.
Bundle all locales at init
Section titled “Bundle all locales at init”Pass the full catalog map to setupI18n. All messages are available immediately. Use activate()
to switch. No load() call is needed.
import { setupI18n } from "@lingui/core";import { catalog, type SupportedLocale } from "./catalog";
export const i18n = setupI18n({ locale: "en", messages: catalog,});
export function switchLocale(next: SupportedLocale): void { i18n.activate(next);}Import this shared instance in your root layout and pass it to setLinguiContext:
<script lang="ts"> import { setLinguiContext } from "lingui-for-svelte"; import { i18n } from "$lib/i18n/instance";
const { children } = $props(); setLinguiContext(i18n);</script>
{@render children()}import { defineMiddleware } from "astro:middleware";import { setupI18n } from "@lingui/core";import { setLinguiContext } from "lingui-for-astro";import { catalog } from "./lib/i18n/catalog";
export const onRequest = defineMiddleware((context, next) => { const locale = resolveLocale(context); // your locale resolution logic const i18n = setupI18n({ locale, messages: catalog }); setLinguiContext(context.locals, i18n); return next();});Load one locale at a time
Section titled “Load one locale at a time”Statically import all catalogs but call loadAndActivate with one locale at a time. Bundle size is
the same as the bundle-all approach, but the API matches the lazy-load pattern if you plan to
migrate later.
const i18n = setupI18n();i18n.loadAndActivate({ locale: "en", messages: catalog.en });
function switchLocale(next: SupportedLocale): void { i18n.loadAndActivate({ locale: next, messages: catalog[next] });}Dynamic imports
Section titled “Dynamic imports”Dynamic imports let your bundler split each catalog into a separate chunk. Only the requested locale is fetched, which reduces the initial bundle size.
const i18n = setupI18n();
async function loadLocale(locale: SupportedLocale): Promise<void> { const { messages } = await import(`./locales/${locale}.ts`); i18n.loadAndActivate({ locale, messages });}In Svelte
Section titled “In Svelte”Svelte <script> blocks do not support top-level await. Load the initial locale with a static
import to keep setup synchronous, then use dynamic imports only for subsequent locale switches.
<script lang="ts"> import { setupI18n } from "@lingui/core"; import { setLinguiContext } from "lingui-for-svelte";
// Initial locale: static import so setup stays synchronous. import { messages as enMessages } from "$lib/i18n/locales/en"; import type { SupportedLocale } from "$lib/i18n/catalog";
const i18n = setupI18n(); i18n.loadAndActivate({ locale: "en", messages: enMessages }); setLinguiContext(i18n);
async function switchLocale(next: SupportedLocale): Promise<void> { const { messages } = await import(`$lib/i18n/locales/${next}.ts`); i18n.loadAndActivate({ locale: next, messages }); }</script>In Astro
Section titled “In Astro”Astro middleware runs in an async function, so dynamic imports work without any extra wiring.
import { defineMiddleware } from "astro:middleware";import { setupI18n } from "@lingui/core";import { setLinguiContext } from "lingui-for-astro";import type { SupportedLocale } from "./lib/i18n/catalog";
export const onRequest = defineMiddleware(async (context, next) => { const locale = resolveLocale(context) as SupportedLocale; const { messages } = await import(`./lib/i18n/locales/${locale}.ts`); const i18n = setupI18n(); i18n.loadAndActivate({ locale, messages }); setLinguiContext(context.locals, i18n); return next();});Which approach to use
Section titled “Which approach to use”| Static imports | Dynamic imports | |
|---|---|---|
| Initial bundle size | All locales included | Only the first locale |
| Switching | Synchronous | Asynchronous (await) |
| Svelte top-level setup | Straightforward | Initial locale must be statically imported |
| Astro middleware | Straightforward | Straightforward (async already) |
| When to use | Default for most apps | When catalog size is a concern |