Ask your question and get a summary of the document by referencing this page and the AI provider of your choice
If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
New Intlayer v9 - What's new?
Welcome to Intlayer v9! This major release marks a huge milestone in simplifying the migration path to Intlayer with Compat Adapter Packages for major i18n libraries (react-i18next, next-intl, vue-i18n, etc.) and adds support for rich content structures: Collections and Variants.
Table of contents
Compat Adapter Packages
Migrating to Intlayer from popular i18n libraries is now easier than ever. We have created five compat packages that expose the exact same public APIs as standard i18n libraries but delegate all translation work to Intlayer at runtime.
Expose Same Public API with Strict Typing
By replacing imports, you get all the benefits of Intlayer (including compile-time type safety against your actual dictionaries) with minimal code changes:
@intlayer/i18next@intlayer/react-i18next@intlayer/next-intl@intlayer/react-intl@intlayer/next-i18next@intlayer/vue-i18n@intlayer/lingui
For example, simply change:
Copy the code to the clipboard
import { useTranslation } from "react-i18next";to:
Copy the code to the clipboard
import { useTranslation } from "@intlayer/react-i18next";Your keys will now be strictly typed against your Intlayer dictionaries, offering full dot-path auto-completion in your IDE!
Bundler Alias Plugins (Vite, Next.js, Turbopack)
To allow migrating without rewriting all your import statements manually, each compat adapter package includes a custom bundler plugin (Vite or Next.js) under the /plugin subpath.
These plugins automatically rewrite existing imports (e.g. react-i18next or next-intl) to their @intlayer/* equivalents at build time.
Next.js (Webpack / Turbopack) Example
Instead of withIntlayer, wrap your Next.js configuration with the compat plugin:
Copy the code to the clipboard
import { createNextI18nPlugin } from "@intlayer/next-i18next/plugin";import type { NextConfig } from "next";const withIntlayer = createNextI18nPlugin();const nextConfig: NextConfig = {};export default withIntlayer(nextConfig);Vite (React, Vue, Solid, Svelte) Example
Copy the code to the clipboard
import vueI18nVitePlugin from "@intlayer/vue-i18n/plugin";export default defineConfig({ plugins: [vueI18nVitePlugin()],});Mutualized Runtime Resolver
All compat adapters now route translation resolution through a single, highly optimized runtime parser: @intlayer/core/messageFormat.
- Interpolate Message: Resolves standard
{{var}}(whitespace & dot-paths), ICU formatted args ({v, number, percent}etc.), and bare{var}templates. - Message Node Resolver: Resolves nested nodes:
insert(),plural()(CLDR plural rules),enu()(enumeration),gender(), HTML tags, arrays, and callable function nodes. - Tokenized Tag Parser: Supports inline XML/HTML tags and numbered tags (e.g.,
<1>children</1>) to power rich-text rendering out of the box.
Feature Spec: Collections & Variants
Intlayer v9 expands beyond static key-value objects, allowing dictionaries to declare dynamic layout structures that are fully typed end-to-end.
1. Collections
Define a CMS-managed list of ordered items (e.g. FAQs, products, or blog lists). Each item lives in its own .content.ts file with the same key and an item number:
Copy the code to the clipboard
import { t, type Dictionary } from "intlayer";export default { key: "faq", item: 1, content: { question: t({ en: "What is Intlayer?", fr: "Qu'est-ce qu'Intlayer ?" }), answer: t({ en: "An i18n toolkit.", fr: "Une boîte à outils i18n." }), },} satisfies Dictionary;Copy the code to the clipboard
import { t, type Dictionary } from "intlayer";export default { key: "faq", item: 2, content: { question: t({ en: "Is it free?", fr: "Est-ce gratuit ?" }), answer: t({ en: "Yes, open-source.", fr: "Oui, open-source." }), },} satisfies Dictionary;Usage:
Copy the code to the clipboard
// Fetch all items as an arrayconst allFaqs = useIntlayer("faq"); // -> { question: string, answer: string }[]// Fetch a single item by indexconst faq = useIntlayer("faq", { item: 2 }); // -> { question: string, answer: string }2. Variants
Deliver A/B tests, seasonal headers, feature flags, or custom landing pages:
String variants (e.g. A/B testing)
Copy the code to the clipboard
import { t, type Dictionary } from "intlayer";export default { key: "hero-banner", variant: "default", content: { control: t({ en: "Welcome", fr: "Bienvenue" }), black_friday: t({ en: "Shop now", fr: "Acheter maintenant" }), },} satisfies Dictionary;Usage:
Copy the code to the clipboard
const banner = useIntlayer("hero-banner", { variant: "black_friday" });Object variants (e.g. Dynamic Records)
Copy the code to the clipboard
import { t, type Dictionary } from "intlayer";export default { key: "product-copy", variant: { id: "prod_123", category: "books", }, content: { title: t({ en: "Clean Code", fr: "Code Propre" }), },} satisfies Dictionary;Usage:
Copy the code to the clipboard
// Fetches only the requested record dynamically (requires Suspense)const product = useIntlayer("product-copy", { variant: { id: "prod_123", category: "books" },});Vite Plugin: Bundled Compiler & Proxy
The intlayer() Vite plugin now bundles the compiler and the locale-routing proxy directly, so most projects only need a single plugin in vite.config.ts:
Copy the code to the clipboard
import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({ plugins: [intlayer()],});- Compiler: Activates automatically when
compiler.enabledis set totrueand acompiler.outputpath is configured. You no longer need to registerintlayerCompiler()separately. - Proxy: Activates automatically based on the new
routing.enableProxyoption (trueby default). It wires the locale detection / redirect / rewrite middleware in development, preview, and production SSR. You no longer need to registerintlayerProxy()separately.
routing.enableProxy option
A new routing.enableProxy option controls whether the locale-routing proxy is plugged in. It defaults to true. Disable it when you want to handle locale routing yourself:
Copy the code to the clipboard
import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = { routing: { enableProxy: false, // Default: true },};export default config;The standalone intlayerCompiler() and intlayerProxy() plugins remain exported for advanced setups. Registering them alongside intlayer() is safe — each plugin deduplicates itself and runs only once.
Compiler disabled by default
Starting with Intlayer v9, the compiler is disabled by default (compiler.enabled now defaults to false). To opt in to build-time extraction of your .content.ts files, set compiler.enabled: true in your configuration:
Copy the code to the clipboard
import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = { compiler: { enabled: true, // Default: false — required to enable the compiler since v9 output: ({ fileName }) => `./${fileName}.content.ts`, },};export default config;When the compiler is disabled, Intlayer skips the build-time extraction step and relies on your already-declared dictionaries. Enable it only when you want the bundler plugin (@intlayer/swc, @intlayer/babel, or the intlayer() Vite plugin) to extract content automatically.
React Native: single-package imports
In a React Native or Expo app, you no longer need to juggle both react-intlayer and react-native-intlayer. The react-native-intlayer package now re-exports the full react-intlayer API (hooks, utilities, and the /format, /html, and /markdown subpaths), and its IntlayerProvider automatically applies the React Native polyfills.
Import everything from the single react-native-intlayer package:
Copy the code to the clipboard
import { IntlayerProvider, useIntlayer, useLocale,} from "react-native-intlayer";Copy the code to the clipboard
npm install intlayer react-native-intlayerImporting fromreact-intlayerkeeps working, butreact-native-intlayeris now the recommended single entry point for React Native — its provider ships the polyfills the web-orientedreact-intlayerprovider does not.
CMS SDK: use Intlayer as a headless content database
Intlayer v9 ships a clean, auto-authenticating SDK in @intlayer/api to interact with the CMS programmatically — fetch projects, fetch dictionaries, and push or update them from your own server, scripts, or CI. Authentication (OAuth2 client_credentials) is handled and refreshed for you.
The SDK is split into two separate imports so your bundle includes only the domains you actually use:
createIntlayerCMS— a lightweight authenticator holding the credentials and the managed token (no domain client bundled).dictionaryEndpoint,projectEndpoint, … — per-domain endpoint binders, each imported from its own subpath.
Copy the code to the clipboard
import { createIntlayerCMS } from "@intlayer/api";import { dictionaryEndpoint } from "@intlayer/api/dictionary";const cms = createIntlayerCMS();// Readconst { data: dictionaries } = await dictionaryEndpoint(cms).getDictionaries();// Write — use the CMS like a databaseawait dictionaryEndpoint(cms).pushDictionaries([myDictionary]);Security: the CMS credentials grant write access to your content. Only ever create the authenticator on the server side — never shipclientId/clientSecretto the browser.
Self-Hosting
Intlayer v9 ships first-class support for running your own Intlayer instance with a single command. No Intlayer Cloud account required.
Copy the code to the clipboard
curl -fsSL https://intlayer.org/install.sh | shThe installer downloads a docker-compose.yml and a .env, auto-generates the required secrets, and runs docker compose up -d. Everything — the dashboard, the API, the database, object storage, and transactional email — runs locally in containers.
Migration notes from v8
If you are upgrading from v8, note that the v9 does not include breaking changes. But here are the key changes:
- Compiler disabled by default:
compiler.enablednow defaults tofalse. If you rely on build-time extraction of your.content.tsfiles, setcompiler.enabled: truein yourintlayer.config.ts. - Vite plugin: The compiler and locale-routing proxy are now bundled into
intlayer(). If you previously registeredintlayerCompiler()orintlayerProxy()manually, you can remove them — they are deduplicated automatically, so keeping them is harmless. Userouting.enableProxy: falseto opt out of the proxy. - Locales & Dialects: If using external i18n dependencies, add their respective compat adapter plugins in your configuration or bundler setup to automatically rewrite imports.
- Custom Selectors: When calling
useIntlayer, the second parameter is now reserved for an option object containing{ locale, item, variant }. If you previously passed a locale string directly, you can still do so, but using the options object is recommended for advanced selections. - React Native:
react-native-intlayernow re-exports the entirereact-intlayerAPI. In a React Native app, import everything fromreact-native-intlayerand drop the directreact-intlayerdependency. Existingreact-intlayerimports continue to work.