Skip to content
JavaScript localization guide

JavaScript localization, the i18next way.

JavaScript localization (l10n) adapts a JavaScript application (text, dates, currencies, plurals, layouts) for users in different languages or regions. The standard approach pairs an i18n library with a translation backend so non-developers can edit copy without code changes.

This guide uses i18next, the most-used i18n framework for JavaScript, with Locize, its native managed backend. Quickstart code for React, Next.js, Vue, Angular, Svelte, and vanilla JS / Node.js. Built by the team that created i18next. ~1,000 product teams ship multilingual JavaScript with this stack today.

Free 14-day trialNo credit card required
JavaScript localization with i18next — code example

What is JavaScript localization?

JavaScript localization (l10n) adapts a JavaScript application (text, formats, currencies, dates, plurals, layouts) for users in a different language or region. The engineering work that makes this possible is internationalization (i18n): extracting strings from code, using ICU formatters, handling Unicode, plurals, and gender.

What it is not

Not just translation. Translation is converting text. Localization adapts the whole experience: number formats, currency, RTL layouts, gendered language, plural rules.

Not the browser's built-in Intl. The Intl API formats numbers, dates, and plurals; useful, but it doesn't store, deliver, or manage your translation strings. You still need an i18n framework on top.

What you actually need

1. An i18n library for the runtime (i18next, FormatJS, …).

2. A strategy for translation files: bundled with the app, fetched at runtime, or both.

3. A way to keep translators and developers in sync as new keys are added.

4. Automation for the boring parts: missing-key detection, AI/MT pre-translation, review workflow.

Why i18next?

i18next is the most-used i18n framework for JavaScript. Here is the short version of why most teams pick it.

Universal across frameworks

React, Vue, Angular, Next.js, Svelte, Node.js, Electron: same core, different bindings. Switch frameworks without rewriting your localization layer.

Battle-tested in production

14+ years old, weekly downloads in the millions, used by everything from solo side projects to Fortune 500 software.

Plugin ecosystem

Backends (HTTP, fs, Locize), language detectors (browser, custom), ICU support, lazy loading, post-processors. Extensible without forking.

saveMissing built in

Add t('new.key') in code; the key shows up in your backend automatically. No manual extraction, no out-of-sync JSON files.

Native managed backend

Locize is built by the same team. The integration is one plugin and four lines of config, not a generic TMS with i18next support bolted on.

Quickstart by framework

Each card shows the install command, a minimal i18next + Locize setup, and a link to the dedicated walkthrough.

React

react-i18next
install
npm install i18next react-i18next i18next-browser-languagedetector i18next-locize-backend
i18n.js
import i18n from 'i18next'
import { initReactI18next, useTranslation } from 'react-i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import Backend from 'i18next-locize-backend'

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    saveMissing: true, // sends new keys to Locize
    backend: {
      projectId: '[PROJECT_ID]',
      apiKey: '[API_KEY]', // dev only — drop in production
    }
  })

// In a component:
function Welcome () {
  const { t } = useTranslation()
  return <h1>{t('welcome.title', 'Welcome')}</h1>
}

Next.js

App Router
install
npm install next-i18next i18next react-i18next i18next-locize-backend
i18n.config.ts
// i18n.config.ts — works for App Router, Pages Router, or both
import { defineConfig } from 'next-i18next'
import LocizeBackend from 'i18next-locize-backend'

export default defineConfig({
  supportedLngs: ['en', 'de'],
  fallbackLng: 'en',
  use: [LocizeBackend],
  i18nextOptions: {
    backend: {
      projectId: '[PROJECT_ID]',
      apiKey: '[API_KEY]', // dev only — drop in production
      referenceLng: 'en'
    },
    saveMissing: true // sends new keys to Locize
  }
})

// In a Server Component:
//   const { t } = await getT('common')
// In a Client Component:
//   const { t } = useT('common')
// Full App Router setup (proxy + layout) in the linked guide.

Vue

i18next-vue
install
npm install i18next i18next-vue i18next-locize-backend
main.js
import { createApp } from 'vue'
import i18next from 'i18next'
import I18NextVue from 'i18next-vue'
import Backend from 'i18next-locize-backend'
import App from './App.vue'

await i18next
  .use(Backend)
  .init({
    fallbackLng: 'en',
    saveMissing: true,
    backend: {
      projectId: '[PROJECT_ID]',
      apiKey: '[API_KEY]'
    }
  })

createApp(App).use(I18NextVue, { i18next }).mount('#app')

// In a template:
// <h1>{{ $t('welcome.title') }}</h1>

Angular

angular-i18next
install
npm install i18next angular-i18next i18next-locize-backend
app.module.ts
import { APP_INITIALIZER, NgModule } from '@angular/core'
import { I18NextModule, ITranslationService, I18NEXT_SERVICE } from 'angular-i18next'
import LocizeBackend from 'i18next-locize-backend'

const i18nextInit = (i18next: ITranslationService) => () =>
  i18next
    .use(LocizeBackend)
    .init({
      fallbackLng: 'en',
      saveMissing: true,
      backend: {
        projectId: '[PROJECT_ID]',
        apiKey: '[API_KEY]'
      }
    })

@NgModule({
  imports: [I18NextModule.forRoot()],
  providers: [{
    provide: APP_INITIALIZER,
    useFactory: i18nextInit,
    deps: [I18NEXT_SERVICE],
    multi: true
  }]
})
export class AppModule {}

Svelte

i18next + stores
install
npm install i18next i18next-locize-backend
src/i18n.js
// src/i18n.js
import i18next from 'i18next'
import Backend from 'i18next-locize-backend'
import { writable } from 'svelte/store'

export const t = writable((k) => k)
export const lng = writable('en')

i18next
  .use(Backend)
  .init({
    fallbackLng: 'en',
    saveMissing: true,
    backend: {
      projectId: '[PROJECT_ID]',
      apiKey: '[API_KEY]'
    }
  }, () => {
    t.set(i18next.t.bind(i18next))
    lng.set(i18next.language)
  })

// In a component:
// import { t } from './i18n.js'
// <h1>{$t('welcome.title')}</h1>

Vanilla JS / Node.js

i18next core
install
npm install i18next i18next-locize-backend
i18n.js
import i18next from 'i18next'
import Backend from 'i18next-locize-backend'

await i18next
  .use(Backend)
  .init({
    fallbackLng: 'en',
    saveMissing: true,
    backend: {
      projectId: '[PROJECT_ID]',
      apiKey: '[API_KEY]'
    }
  })

console.log(i18next.t('welcome.title'))
// Works the same in browser and Node.js.

Need another framework or stack? See the full i18next supported-frameworks list, or non-i18next options in the integration docs.

Beyond JSON files: when to add a backend

You can ship multilingual JavaScript with just JSON files in your repo. Most teams outgrow that around the time a non-developer needs to fix a typo.

JSON files in your repo
  • ✔ Zero dependencies, zero cost.
  • ✔ Fine for solo projects or pre-launch demos.
  • ✖ Every translation update is a PR + deploy.
  • ✖ Translators need repo access (or you become their proxy).
  • ✖ Adding a language is a coordinated launch.
  • ✖ AI translation runs in someone's ChatGPT tab.
i18next + Locize backend
  • saveMissing auto-reports new keys; no manual extraction.
  • ✔ Translators work in a dedicated UI, no Git.
  • ✔ Translations served from a global CDN, no redeploy for typos.
  • ✔ AI auto-translate with glossary + style guide + TM context.
  • ✔ Branches, versions, review workflow, audit log built in.
  • ✔ Multi-tenant overrides for B2B SaaS.

The full loop with Locize: a developer writes t('new.key') saveMissing sends the key to Locize → Locize auto-translates it → translation lands on the CDN → your app picks it up. No commits in between.

Best practices checklist

Questions to answer before you commit to a setup. Each one usually nudges you toward i18next + a backend.

  • Which frameworks do you target? If more than one, pick a core (i18next) that works across all of them.
  • Bundle translations or fetch them? Bundle for very small apps; fetch for anything you'll iterate on. CDN delivery scales further than HTTP from your origin.
  • Where do new keys come from? Developers writing t(), designers in Figma, content writers in a CMS: pipe them all into one source of truth.
  • Who edits translations? If non-developers, they need a UI, not Git. If only developers, JSON files are still viable.
  • What about RTL, plurals, gender, ICU? i18next supports all of these via plugins. Plan early, retrofitting is painful.
  • How will you handle missing translations in production? Set a sensiblefallbackLng, log misses, and consider a CDN-side fallback chain.
  • Can your AI agent help? The Locize MCP server lets Cursor, Claude Code, and other AI agents read/write translations directly from your IDE.

More on framework specifics: i18next supported frameworks · supported i18n formats.

What it costs

Public pricing. No sales call. Pick a plan when the trial ends, or stay on Free if your project is small.

Free
$0/mo

Small personal projects: 1 user, 2 languages, 100k CDN downloads.

Starter
$7/mo

5 users, 5 languages, 1M CDN downloads, 50k AI tokens.

Growth: most popular
$49/mo

10 users, 10 languages, 3 branches, 5 tenants, review workflow, glossary, style guide.

Professional
$99/mo

Unlimited users, 20 languages, BYOK AI, SSO add-on.

14 days, all features unlocked, no credit card. There's also a usage-based plan if you prefer paying for what you use.

Frequently asked questions

If your question is missing, email support@locize.com

What is JavaScript localization?

JavaScript localization (l10n) is the process of adapting a JavaScript application (text, formats, currencies, dates, plurals, layouts) for users in a different language or region. The engineering work that makes this possible is internationalization (i18n): extracting strings from code, using ICU formatters, handling Unicode, plurals, and gender. i18next is the most-used i18n framework for JavaScript.

Which i18n library should I use for JavaScript?

For most JavaScript and TypeScript projects, i18next is the most pragmatic choice. It works across React (react-i18next), Vue (i18next-vue), Angular (angular-i18next), Next.js (next-i18next or App Router with custom setup), Svelte, and vanilla JS / Node. It supports plurals, interpolation, namespaces, language detection, and connects directly to a managed backend like Locize.

How do I add multiple languages to a React app?

Install i18next, react-i18next, and a backend (e.g. i18next-locize-backend), initialize i18next with your project credentials, then use the useTranslation hook in components: const { t } = useTranslation(); return <h1>{t('welcome')}</h1>. See the React quickstart on this page for a complete code example.

Does i18next work with Next.js App Router?

Yes. The App Router requires a slightly different setup than the legacy Pages Router because i18next runs on both the server and client. We have a dedicated guide that walks through the server-side init, client hydration, and language detection. See the "i18next + Next.js App Router" blog post linked in the Next.js quickstart on this page.

i18next vs. react-intl, next-intl, or FormatJS: which is better?

i18next has broader framework support, a richer plugin ecosystem (language detection, lazy loading, ICU, multiple backends), and a managed backend (Locize) built by the same team. react-intl / FormatJS is purer ICU MessageFormat but more limited in lifecycle features. next-intl is App-Router-native but more locked-in. Trade-offs explained in our "react-intl vs. react-i18next" and "next-intl vs. next-i18next" blog posts.

How do I avoid bundling translation files into my JavaScript app?

Configure i18next with a network backend like i18next-locize-backend. Translations are then fetched at runtime from a CDN. Your bundle stays small, you can update translations without redeploying, and you can add a language without shipping new code.

How do I keep translation keys in sync between code and translators?

Enable i18next's saveMissing feature. New keys you add in code are automatically reported to your translation backend (e.g. Locize). Combined with Automatic Translation, new keys can also be auto-translated into all target languages using your project's glossary, style guide, and TM as context.

Ready to localize your JavaScript app?
Spin up a free project, drop in i18next-locize-backend, and ship translations continuously.