Skip to main content

Upgrading to v3

v3 takes i18n-keyless from 19 languages to 48, and lets you write your app in any of them.

Almost nothing changes in your code. Two language codes were renamed, and that is the whole breaking surface.

What changed

v2v3
Languages1948
Chinesecnzh-Hans (Simplified) and zh-Hant (Traditional)
Czechczcs
primary"fr" or "en" onlyany of the 48

The other 17 codes are spelled exactly as before. If your app does not ship Chinese or Czech, upgrading is a version bump and nothing else.

Upgrade

npm install i18n-keyless-react@^3.0.0
# or
npm install i18n-keyless-node@^3.0.0

Then rename the two codes wherever you wrote them by hand — your supported list, your language picker, any stored user preference:

 I18nKeyless.init({
API_KEY: 'YOUR_API_KEY',
storage: window.localStorage,
languages: {
primary: 'fr',
- supported: ['en', 'es', 'cn', 'cz'],
+ supported: ['en', 'es', 'zh-Hans', 'cs'],
},
});

TypeScript finds every one of them for you: cn and cz are no longer in Lang, so each site is a compile error until it is fixed.

A language your users already chose

If you persist the selected language, a user who picked Chinese has "cn" in storage and that is no longer a valid Lang. Map it once on the way out of storage:

import { resolveLang, type Lang } from 'i18n-keyless-react';

const LEGACY_CODES: Record<string, Lang> = { cn: 'zh-Hans', cz: 'cs' };

const stored = window.localStorage.getItem('my-app-language');
const language = LEGACY_CODES[stored ?? ''] ?? resolveLang(stored);

The legacy map has to come first: resolveLang('cn') returns undefined, because cn was never a BCP-47 tag — it is the old i18n-keyless spelling. Everything that is a real tag resolveLang handles for you, so zh-TW becomes zh-Hant and pt-AO becomes pt. See resolveLang.

Available from every package since 3.0.1

resolveLang and toAppStoreLocale are re-exported by i18n-keyless-react and i18n-keyless-node, so you import them from the same package as the rest of your SDK. On 3.0.0 they were only on i18n-keyless-core.

Your translations are not lost

Nothing needs to be re-translated. The Chinese and Czech text you have already paid for is the same text under the new code — the rename happened in our storage too, in the same migration.

You do not have to upgrade

The API answers each client in the codes that client understands, chosen from the version your SDK sends. A v2 app keeps receiving cn and cz and keeps working, indefinitely, with no change on your side. Upgrade when you want the other 29 languages, or a primary language other than French or English.

Do not mix the two in one app

The dialect is chosen per client, from the SDK version. Sending cn from one screen and zh-Hans from another, against the same API key, gives you two different keys for the same language.

New in v3

Beyond the languages themselves:

  • resolveLang — turn navigator.language, an Accept-Language entry or a device locale into a language you actually ship.
  • toAppStoreLocale — map a language onto its App Store Connect listing slot, to push localized metadata.
  • Regional variants where the translation genuinely differs: pt-BR, es-MX, fr-CA, en-GB, and zh-Hans / zh-Hant. You are billed per language you opt into, so ['pt', 'pt-BR'] is two translations and ['pt'] is one.