Skip to content

Astro: Getting Started

Terminal window
vp add @lingui/core lingui-for-astro
vp add -D @lingui/cli @lingui/conf unplugin-lingui-macro
astro.config.ts
import { defineConfig } from "astro/config";
import linguiForAstro from "lingui-for-astro/integration";
import linguiMacro from "unplugin-lingui-macro/vite";
export default defineConfig({
integrations: [linguiForAstro()],
vite: {
plugins: [linguiMacro()],
},
});
lingui.config.ts
import babelExtractor from "@lingui/cli/api/extractors/babel";
import { defineConfig } from "@lingui/conf";
import { astroExtractor } from "lingui-for-astro/extractor";
export default defineConfig({
locales: ["en", "ja"],
sourceLocale: "en",
catalogs: [{ path: "src/lib/i18n/locales/{locale}" }],
extractors: [astroExtractor, babelExtractor],
});

For server and hybrid output, call setLinguiContext from middleware before any page renders. This is where you load the compiled catalog for the current request.

src/middleware.ts
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();
});
src/pages/index.astro
---
import { Trans, t } from "lingui-for-astro/macro";
---
<h1>{t`Hello from Astro`}</h1>
<p><Trans>Macro-first translation in Astro</Trans></p>
  • Read i18n Context for how Astro.locals carries the i18n instance, how static and request-aware setup differ, and how to access it manually.
  • Read Using Islands if you have client framework islands that need translation.
  • Read Astro caveats for server/runtime boundaries.