Paraglide JS

New to Paraglide? Watch how it works in 6 minutes →

Using messages

Import messages from the generated messages.js file:

import { m } from "./paraglide/messages.js";

m.hello_world(); // "Hello World!"

Parameters

Pass parameters as an object:

// messages/en.json: { "greeting": "Hello {name}!" }

m.greeting({ name: "Samuel" }); // "Hello Samuel!"

Getting and setting the locale

import { getLocale, getTextDirection, setLocale } from "./paraglide/runtime.js";

getLocale(); // "en"
getTextDirection(); // "ltr" or "rtl" for current locale
setLocale("de"); // Updates the locale and starts a document navigation

[!NOTE]Locale switching uses a full document navigation, not framework reactivity. By default, setLocale() updates the configured locale strategies and then navigates to the localized URL when URL routing is enabled; otherwise, it reloads the current document. The new document renders the app and any document-level locale settings together.

Advanced: stay on the current document

[!WARNING]setLocale(locale, { reload: false }) is a client-only escape hatch, not a normal locale picker. It updates the configured locale strategies but does not re-render your framework, navigate to the localized URL, or update document state such as <html lang>, dir, title, or metadata.

Use it only for a fully client-rendered surface that you own and that must preserve non-restorable in-memory work—for example, an embedded widget, browser-extension options page, or persistent authoring or real-time workspace. If a custom strategy makes setLocale() asynchronous, await it before triggering every locale-dependent UI update through your own reactive state and synchronizing the document or root state you own.

Do not use it for an ordinary locale picker or to switch an SSR-, SSG-, or hydrated document. Never use it on a route whose active locale strategy includes url, or with experimentalPerLocaleBuild. With the url strategy, it leaves the old URL and document shell in place, so getLocale() can keep resolving the old locale; use a full document navigation instead.

await setLocale("de", { reload: false });

Forcing a locale

Override the locale for a specific message:

m.greeting({ name: "Samuel" }, { locale: "de" }); // "Hallo Samuel!"

[!TIP]Useful for server-side rendering where you might need to render content in multiple languages.

Routing

Use localizeHref() for URL localization. Works with any framework:

import { localizeHref } from "./paraglide/runtime.js";

localizeHref("/blog"); // "/en/blog" or "/de/blog" depending on locale
<!-- React/Solid/Vue/Svelte/etc. -->
<a href={localizeHref("/blog")}>Blog</a>

[!NOTE]If you route to a different locale, ensure a reload happens afterwards. See switching locales via links.


Adding messages

Messages are stored in messages/{locale}.json:

messages/en.json

{
  "greeting": "Hello {name}!"
}

messages/de.json

{
  "greeting": "Hallo {name}!"
}

[!NOTE]These examples use the default inlang message format. Paraglide works with any format plugin—see the plugin directory.

Adding locales

Add locales in project.inlang/settings.json:

{
  "baseLocale": "en",
  "locales": ["en", "de", "fr"]
}

Additional features

Message keys

Paraglide supports nested keys through bracket notation but recommends flat keys. For new messages, prefer stable random human-readable keys:

Flat random key (recommended):

{
  "calm_green_otter": "User Profile"
}
m.calm_green_otter();

Existing nested keys are also supported:

{
  "user": { "profile": { "title": "User Profile" } }
}
m["user.profile.title"]();

See message keys for the key-naming rationale and structure options.

Dynamic messages

Specify messages beforehand to preserve tree-shaking:

const messages = {
  greeting: m.greeting,
  goodbye: m.goodbye,
};

messages["greeting"](); // "Hello World!"

Type-safe localized strings

Message functions return LocalizedString, a special string type that TypeScript uses to distinguish translated text from regular strings:

import type { LocalizedString } from "./paraglide/runtime.js";

function PageTitle(props: { title: LocalizedString }) {
  return <h1>{props.title}</h1>;
}

<PageTitle title={m.welcome_title()} />  // ✅
<PageTitle title="Welcome" />            // ❌ Type error

Next steps