Skip to content

Astro: Using Islands

One Astro page can host multiple Lingui integrations

Section titled “One Astro page can host multiple Lingui integrations”

An Astro app often contains three different authoring surfaces at once:

  • .astro pages and layouts
  • Svelte islands
  • React islands

They should not all use the same package.

  • Use lingui-for-astro for .astro files.
  • Use lingui-for-svelte inside Svelte islands.
  • Use official Lingui packages inside React islands.

This split matches how each renderer actually executes.

Astro pages usually render to static HTML, or become request-bound only when you opt into server or hybrid output. Svelte and React islands keep their own component runtime and hydration model. Trying to force one runtime API across all three makes the authoring model worse, not better.

The pieces that can be shared safely are:

  • catalogs
  • locale selection logic
  • plain TypeScript message descriptors

The translation call site should still use the package that matches the current renderer.

  1. Resolve the active locale at the Astro app boundary (middleware or frontmatter).
  2. Load the correct catalogs for the page render.
  3. Render .astro with lingui-for-astro.
  4. Pass locale into each island as a prop.
  5. Inside each island, call setLinguiContext with that locale.
src/pages/index.astro
---
import { t } from "lingui-for-astro/macro";
import MyIsland from "../components/MyIsland.svelte";
// locale is set in middleware via setLinguiContext
const locale = Astro.locals.lingui?.i18n.locale ?? "en";
---
<h1>{t`Welcome`}</h1>
<!-- Pass locale so the island uses the same locale as the page. -->
<MyIsland client:load {locale} />
src/components/MyIsland.svelte
<script lang="ts">
import { untrack } from "svelte";
import { setupI18n } from "@lingui/core";
import { setLinguiContext } from "lingui-for-svelte";
import { t } from "lingui-for-svelte/macro";
import { catalog } from "$lib/i18n/catalog";
const { locale = "en" } = $props();
const i18n = setupI18n({ locale: untrack(() => locale), messages: catalog });
setLinguiContext(i18n);
</script>
<p>{$t`Hello from a Svelte island`}</p>

Pass locale from the page, not translated strings, so the island can translate its own messages using the same locale, and react to future locale changes if needed.