跳转到内容

Paraglide JS

此内容尚不支持你的语言。

NPM Downloads GitHub Issues Contributors Discord

🪂 Paraglide JS

Compiler-first i18n for TanStack Start, SvelteKit, and Vite apps.
Type-safe message functions, tree-shakable translations, and first-class SSR.

Documentation · Quick Start · Report Bug

Used in production by

Kraft Heinz    Bose    Disney    ETH Zurich    Brave    Michelin    idealista    Architonic    Finanzen100    0.email

Framework-authored and framework-tested

Svelte SvelteKit's official i18n integration
TanStack TanStack Router's e2e-tested i18n example

messages/en.json
{
"greeting": "Hello {name}!"
}
import { m } from "./paraglide/messages.js";
m.greeting({ name: "World" }); // "Hello World!" — fully typesafe

The compiler turns your messages into typed ESM functions. Vite, Rollup, and other modern bundlers can tree-shake unused translations before they reach the browser. Expect up to 70% smaller i18n bundle sizes compared to runtime i18n libraries (e.g. 47 KB vs 205 KB).

Vite-NativeDesigned for Vite and modern ESM bundlers. Works with TanStack Start, SvelteKit, React Router, Astro, Vue, Solid, and vanilla JS/TS.
Smaller i18n BundleUp to 70% smaller i18n bundle size than runtime i18n libraries.
Tree-ShakableMessages compile to ESM functions, so unused translations are eliminated by your bundler.
Fully TypesafeAutocomplete for message keys and parameters. Typos become compile errors.
Built-in i18n RoutingURL-based locale detection and localized paths out of the box.
Open Localization FormatBuilt on inlang: project.inlang/settings.json configures locales, plugins, and file patterns while translations stay in version-controlled files like messages/en.json.

React React · Vue Vue · TanStack TanStack Start · Svelte SvelteKit · React Router React Router · Astro Astro · JavaScript Vanilla JS/TS

Paraglide works in SSR apps with request-scoped locale handling. The server middleware detects the locale from each request and uses AsyncLocalStorage so getLocale() and message functions resolve the right locale even during concurrent requests.

import { paraglideMiddleware } from "./paraglide/server.js";
import { getLocale } from "./paraglide/runtime.js";
import { m } from "./paraglide/messages.js";
export function handle(request: Request) {
return paraglideMiddleware(request, async () => {
const html = `
<html lang="${getLocale()}">
<body>${m.greeting({ name: "Ada" })}</body>
</html>
`;
return new Response(html, {
headers: { "content-type": "text/html" },
});
});
}

SSR Docs → · Middleware Docs →

Paraglide coexists with your router. Your app keeps canonical routes like /about, while Paraglide maps browser-facing localized URLs like /en/about or /de/ueber to those canonical routes.

Use your framework or router for route definitions, loaders, navigation, and route typing. Use Paraglide for locale detection, localized URL generation, and message functions.

import { deLocalizeUrl, localizeUrl } from "./paraglide/runtime.js";
// Incoming request: localized URL -> canonical app route
deLocalizeUrl("https://example.com/de/ueber").href; // https://example.com/about
// Outgoing link: canonical app route -> localized URL
localizeUrl("https://example.com/about", { locale: "de" }).href; // https://example.com/de/ueber

For routers with rewrite hooks, call deLocalizeUrl() on incoming URLs and localizeUrl() on outgoing URLs. For file-based routers, keep your file routes canonical and localize at the routing boundary.

i18n Routing Docs →

TanStack Start uses the same boundary pattern: TanStack Router owns the route tree, loaders, navigation, and typed links. Paraglide handles locale detection, localized URL mapping, and message functions.

import { paraglideMiddleware } from "./paraglide/server.js";
import handler from "@tanstack/react-start/server-entry";
export default {
fetch(req: Request): Promise<Response> {
return paraglideMiddleware(req, () => handler.fetch(req));
},
};

Route code stays TanStack-native: TanStack Router owns route trees, loaders, server functions, navigation, and typed links. TanStack runs Paraglide in e2e tests on every router commit, and the guide covers router rewrites, localized links, prerendering, and SSR behavior.

TanStack Start i18n guide →

Terminal window
npx @inlang/paraglide-js init

The CLI sets up everything:

  • Creates your message files
  • Configures your bundler (Vite, Webpack, etc.)
  • Generates typesafe message functions

Then use your messages:

import { m } from "./paraglide/messages.js";
import { setLocale, getLocale } from "./paraglide/runtime.js";
// Use messages (typesafe, with autocomplete)
m.hello_world();
m.greeting({ name: "Ada" });
// Get/set locale
getLocale(); // "en"
setLocale("de"); // switches to German

Full Getting Started Guide →

For <Trans>-style rich text and component interpolation, use typed markup with your framework adapter.

import { ParaglideMessage } from "@inlang/paraglide-js-react";
import { m } from "./paraglide/messages.js";
export function ContactCta() {
return (
<ParaglideMessage
message={m.cta}
markup={{
link: ({ children }) => <a href="/contact">{children}</a>,
strong: ({ children }) => <strong>{children}</strong>,
}}
/>
);
}

The markup names come from your message and are type-checked, so translators control where links and emphasis appear while your React app controls how they render.

Markup Docs → · React · Svelte · Vue · Solid

Paraglide compiles an inlang project into tree-shakable message functions. Your bundler eliminates unused messages at build time.

┌────────────────┐
│ Inlang Project │
└───────┬────────┘
┌────────────────────────┐
│ Paraglide Compiler │
└───────────┬────────────┘
┌──────────────────────────┐
│ ./paraglide/messages.js │
│ ./paraglide/runtime.js │
└──────────────────────────┘

Watch: How Paraglide JS works in 6 minutes →

Paraglide supports locale-aware formatting via declaration formatters:

  • plural (Intl.PluralRules) for plural and ordinal categories
  • number (Intl.NumberFormat) for numbers, currency, compact notation, and more
  • datetime (Intl.DateTimeFormat) for dates/times with locale-aware output
  • relativetime (Intl.RelativeTimeFormat) for values like “yesterday”, “in 2 days”, or “3 hr. ago”

Gender and custom selects are supported via the variants system.

// Pluralization example
m.items_in_cart({ count: 1 }); // "1 item in cart"
m.items_in_cart({ count: 5 }); // "5 items in cart"
// Works correctly for complex locales (Russian, Arabic, etc.)

Message format is plugin-based — use the default inlang format, or switch to i18next, JSON, or ICU MessageFormat via plugins. If your team relies on ICU MessageFormat 1 syntax, use the inlang-icu-messageformat-1 plugin.

Formatting Docs → · Pluralization & Variants Docs →

Runtime i18n libraries like i18next resolve message keys from dictionaries while your app runs. Paraglide compiles messages into typed ESM functions before your app ships.

That means Vite can tree-shake unused translations, TypeScript can autocomplete message keys and parameters, and your components call plain functions instead of resolving strings through a runtime lookup layer.

In the Paraglide benchmark, typical scenarios shipped 47-144 KB with Paraglide vs 205-422 KB with i18next. With 5 locales, 100 used messages, and 200 total messages, Paraglide shipped 47 KB while i18next shipped 205 KB.

Tree-shaking also keeps Paraglide stable as your message catalog grows. In the benchmark, using 100 messages shipped 47 KB with Paraglide whether the project had 200, 500, or 1,000 total messages. The i18next runtime bundle grew from 205 KB to 414 KB.

FeatureParaglideLinguii18next
ArchitectureCompiler-first ESM message functionsExtraction + compiled catalogsRuntime dictionaries
i18n bundle sizeUp to 70% smaller via message-level tree-shakingCompiled catalogsRuntime dictionaries
Tree-shakable✅ Message functionsCatalog-based
Typesafe✅ Generated message functionsMacro/component workflowPartial
Framework supportTanStack Start, SvelteKit, React Router, Astro, Vue, Solid, vanilla JS/TSReact, Vue, Astro, Svelte, Node.js, vanilla JSBroad via wrappers
Routing + SSR✅ Middleware, request isolation, and URL helpersUse your framework/routerUse your framework/router
Rich text✅ Typed markup adapters✅ Rich-text componentsVia framework wrappers
ICU MessageFormat 1Via pluginVia plugin

Full Comparison →

Yes. Paraglide’s message format is plugin-based. You can use the default inlang format, JSON, i18next, XLIFF, or ICU MessageFormat 1 via the ICU plugin.

Paraglide works best when message keys are known at build time, because that enables type safety and tree-shaking. For dynamic menus or CMS entries, use explicit mappings from CMS/content IDs to generated message functions, or let the CMS return already-localized content for the active locale. If most translations are only known at runtime, a runtime i18n library may be a better fit.

Yes. Paraglide can compile existing i18next translation files through the i18next plugin, so you can keep your translation format while moving app code from i18next.t("key") to typed message functions over time.

“Paraglide JS is by far the best option when it comes to internationalization. Nothing better on the market.”

Ancient-Background17 · Reddit

“Just tried Paraglide JS. This is how i18n should be done! Totally new level of DX.”

Patrik Engborg · @patrikengborg

“I was messing with various i18n frameworks and must say Paraglide was the smoothest experience. SSG and SSR worked out of the box.”

Dalibor Hon · Discord

“I migrated from i18next. Paraglide reduced my i18n bundle from 40KB to ~2KB.”

Daniel · Why I Replaced i18next with Paraglide JS

Paraglide compiles messages from inlang, the open project file format for localization. In concrete terms, project.inlang/settings.json defines your locales, plugins, and translation file patterns; your translations stay as version-controlled files in your repo, such as messages/en.json, locales/en.json, or XLIFF files. Existing formats can be imported/exported through plugins. No account required; inlang tools are optional:

ToolDescription
SherlockVS Code extension for inline translation editing
CLIMachine translate from the terminal
FinkTranslation editor for non-developers
ParrotManage translations in Figma

Explore the inlang ecosystem →

We welcome contributions! See CONTRIBUTING.md for guidelines.

MIT — see LICENSE

t1