Plain JS/TS Setup
Plain .js, .ts, .jsx, and .tsx files use @lingui/core/macro with unplugin-lingui-macro
for the build transform and @lingui/cli/api/extractors/babel for extraction.
This also applies to .svelte.js and .svelte.ts files. Those go through the plain JS/TS
pipeline, not the Svelte syntax transform.
Install
Section titled “Install”vp add -D unplugin-lingui-macronpm install -D unplugin-lingui-macropnpm add -D unplugin-lingui-macroyarn add -D unplugin-lingui-macro@lingui/cli and @lingui/conf are required for extraction and catalog compilation. If you
followed a framework getting-started guide they are already installed.
Configure the build transform
Section titled “Configure the build transform”Add linguiMacro() to Vite plugins. In a framework project, place it before the framework plugin.
import linguiMacro from "unplugin-lingui-macro/vite";import { defineConfig } from "vite";
export default defineConfig({ plugins: [ linguiMacro(), // sveltekit(), svelte(), etc. ],});For Astro, add it under vite.plugins in astro.config.ts.
Configure extraction
Section titled “Configure extraction”Add the Babel extractor to lingui.config.ts. In a project that already has a framework extractor,
list both.
import { defineConfig } from "@lingui/conf";import babelExtractor from "@lingui/cli/api/extractors/babel";// import { svelteExtractor } from "lingui-for-svelte/extractor";// import { astroExtractor } from "lingui-for-astro/extractor";
export default defineConfig({ locales: ["en", "ja"], sourceLocale: "en", catalogs: [{ path: "src/lib/i18n/locales/{locale}" }], extractors: [ babelExtractor, // svelteExtractor, // astroExtractor, ],});Define message descriptors, not translated strings
Section titled “Define message descriptors, not translated strings”In plain JS/TS, t and plural resolve through @lingui/core’s global i18n instance, not
the instance registered via setLinguiContext in your Svelte or Astro code. In a framework app
that does not configure the global instance, calling t directly in a .ts file will either
fail or translate against the wrong locale.
The recommended approach is to define message descriptors with msg or defineMessage, and
translate them in framework code where the i18n context is available. This matches Lingui’s
Lazy Translations pattern.
import { defineMessage, msg } from "@lingui/core/macro";
// Descriptors only. No translation happens here.export const labels = { greeting: msg`Hello`, submit: msg`Submit`,} as const;
export const welcomeMessage = defineMessage({ id: "welcome", message: "Welcome back",});Then translate the descriptors in framework code where the context is set:
<script lang="ts"> import { t } from "lingui-for-svelte/macro"; import { labels } from "./labels";</script>
<p>{$t(labels.greeting)}</p><button>{$t(labels.submit)}</button>---import { t } from "lingui-for-astro/macro";import { labels } from "../lib/labels";---
<p>{t(labels.greeting)}</p>See Share Messages Across Files for more patterns, and msg and defineMessage for the full descriptor API.
See also
Section titled “See also”- Extract, Compile, and Verify - why transform and extraction are separate and must both be configured
- Share Messages Across Files - descriptor patterns for cross-file and cross-framework reuse
- Svelte: Getting Started - for Svelte-specific setup
- Astro: Getting Started - for Astro-specific setup