A compiled, Svelte-first i18n library with Gettext-like syntax and ICU plurals.
| Example | Online IDE |
|---|---|
| SSR | |
| SPA |
Please follow the Setup Guide to install and configure sveltext.
Import the t tag and write your text naturally.
<script lang="ts">
import { t } from 'sveltext';
let name = 'John Doe';
</script>
<h1>{t`Welcome back, ${name}!`}</h1>
Sometimes you need to define translated text outside of Svelte's render cycle, such as in Zod schemas, navigation arrays, or constant files.
The t function is not supported outside of a Svelte component. Message catalogs are loaded inside the Svelte context to prevent cross-request state pollution in SSR, which means the active catalog is only available within the component tree. Outside of it, no catalog is accessible.
Instead, use the msg tag. It marks the string for the CLI extractor and compiles it to a hash, while deferring the actual dictionary lookup until render time inside a component.
// src/lib/helpers.ts
import { msg } from 'sveltext';
export const errors = {
sync: msg`Error while syncing items`,
};
<script lang="ts">
import { t } from 'sveltext';
import { errors } from '$lib/helpers';
function goRefresh(success = true) {
if (success) {
itemCount = 1;
alert(t`Refreshed`);
return;
}
alert(t(errors.sync));
}
</script>
If you truly need translation on the server outside the component tree, use the pure runtime function _ and manually provide the message catalog (see the server code usage introduction).
sveltext catches missing plural categories at compile-time. If you forget any of the categories, the Vite build will fail and point you to the exact line.
<script lang="ts">
import { plural } from 'sveltext';
let count = 5;
</script>
<p>
{plural(count, {
one: '# Apple',
other: '# Apples',
})}
<!-- This will be inlined at compile time into the equivalent of t`5 Apples` -->
{plural(5, {
one: '# Apple',
other: '# Apples',
})}
</p>
Because sveltext is content-addressed, having the same Home t call 50 times in your app will only generate one entry in your dictionary. If you need the same word translated differently based on context, use the c() wrapper.
<script lang="ts">
import { c, t } from 'sveltext';
</script>
<h1>{t`Home`}</h1>
<p>{c('real_estate').t`Home`}</p>
<T> Component (Rich Text & Snippets)sveltext embraces Svelte 5's native {#snippet} architecture to translate strings with embedded HTML or components (like bold text or links).
Use the <T> component to interpolate rich UI elements without breaking the sentence structure for your translators.
<script lang="ts">
import { T, msg } from 'sveltext';
</script>
<T msg={msg`Toolbar: {refresh} {refreshFail}`}>
{#snippet refresh()}
<button type="button" onclick={() => goRefresh(true)}>
{t`Refresh`}
</button>
{/snippet}
{#snippet refreshFail()}
<button type="button" onclick={() => goRefresh(false)}>
{t`Refresh (fail)`}
</button>
{/snippet}
</T>
Because sveltext is Svelte 5 native, your interpolated snippets can contain fully interactive components, state bindings, or any complex UI you need.
_ on the serverTo use Sveltext while remaining safe from cross-request state pollution, use the pure runtime function _ and manually load and pass the message catalog when performing server-side actions.
import { msg, _ } from 'sveltext';
import type { MessageCatalog } from 'sveltext';
import type { Actions } from './$types';
const catalogLoaders = import.meta.glob<MessageCatalog>('../locales/*.po', { import: 'messages' });
export const actions = {
sendEmail: async (event) => {
const {
locals: { currentLocale },
} = event;
const messages = await catalogLoaders[`../locales/${currentLocale}.po`]();
const sveltextContext = { locale: currentLocale, messages };
const name = 'John';
const title = _(msg`Test Email to ${name}`, sveltextContext);
const body = _(msg`Hello ${name} from SvelteKit form actions!`, sveltextContext);
console.log(
`Sending email to the user with ${currentLocale}:\n\nTitle: ${title}\nBody: ${body}`,
);
},
} satisfies Actions;
Run the extraction script to scan your codebase for translatable messages.
npx sveltext extract
The API design and AOT-compilation philosophy were heavily inspired by Lingui, svelte-i18n-lingui and ttag. sveltext is a ground-up rewrite specifically designed to lerverage the Svelte 5 compiler and Vite ecosystem for zero-overhead integration.