# Internationalization

:::note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](/sdk-reference/web-sdk-reference).  Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade. <br /><br />Full rollout to all clients still TBD.
:::

The SDK supports 80+ languages for UI text and error messages.

## Setting the Language

Pass the `lang` property inside the `i18n` option when you call `setup()`:

```ts
import { setup } from '@incodetech/web';

await setup({
  apiURL: API_URL,
  token: session.token,
  i18n: {
    lang: 'es', // Spanish
  },
});
```

If a language was previously stored by the SDK (for example, when a user picked one from a language selector), that stored choice takes precedence over `lang`. Treat `lang` as the default for first-time users, not a hard override.

## How It Works

- The `lang` property sets the UI language for all SDK components within the flow
- Translations are loaded from Incode's CDN at runtime
- Error messages and instructions are automatically translated
- The language is also sent to the backend for server-side localization

## Custom Translations

Provide your own translation strings through the `i18n` option in `setup()`. Pass a `translations` object keyed by language code, then by translation key.

```ts
import { setup } from '@incodetech/web';

await setup({
  apiURL: API_URL,
  token: session.token,
  i18n: {
    translations: {
      en: {
        phone: { verify: 'Verify your phone number' },
        email: { willSendCode: 'We will email you a one-time code.' },
      },
      es: {
        phone: { verify: 'Verifica tu número de teléfono' },
      },
    },
  },
});
```

By default, your strings merge on top of Incode's CDN translations, so you only override the keys you list. Any key you omit keeps its default text.

**Keys** use dotted, camelCase paths in the form `module.description` (for example `phone.verify`). Write them as nested objects (above) or as flat dotted keys:

```ts
translations: {
  en: { 'phone.verify': 'Verify your phone number' },
}
```

Use `{{variableName}}` for values the SDK fills in at runtime — keep the placeholder name unchanged:

```ts
translations: {
  en: { selfie: { retryAttempts: 'You have {{count}} attempts left.' } },
}
```

Translation values are rendered without HTML escaping. Never interpolate user-controlled input directly into a translation string — doing so can introduce a cross-site scripting (XSS) vulnerability. Keep translation values as static, trusted content.

### Use only your own translations

To skip Incode's CDN and serve every string yourself, set `skipRemoteLoad: true`:

```ts
await setup({
  apiURL: API_URL,
  token: session.token,
  i18n: {
    skipRemoteLoad: true,
    translations: {
      en: {
        /* every string your flow displays */
      },
    },
  },
});
```

With `skipRemoteLoad: true`, any key you do not define renders the last segment of the key name in Start Case (for example, `phone.verify` renders as `Verify`). Provide a complete `en` bundle so the flow falls back to English for missing keys.

### Load translations from your own endpoint

To serve translation files from your own host or CDN, set `loadPath` to a URL template. The SDK fetches one file per language, replacing `{{lng}}` with the language code and `{{ns}}` with the namespace (always `default`):

```ts
await setup({
  apiURL: API_URL,
  token: session.token,
  i18n: {
    loadPath: 'https://cdn.example.com/locales/{{lng}}/{{ns}}.json',
  },
});
```

For example, loading Spanish requests `https://cdn.example.com/locales/es/default.json`. Each file must be a JSON object of translation keys, using the same `module.description` structure shown above.

Setting `loadPath` replaces Incode's CDN entirely — the SDK loads translations only from your endpoint and never contacts Incode's remote. You do not need `skipRemoteLoad` for this; reserve that flag for the inline-only case above (in fact, `skipRemoteLoad: true` disables remote loading altogether and would stop `loadPath` from being fetched).

## Supported Languages

The SDK loads translations from CDN at runtime for every code below.

| Code      | Language                  |
| --------- | ------------------------- |
| `en`      | English (default)         |
| `en-DG`   | English (Diego Garcia)    |
| `es`      | Spanish                   |
| `es-ES`   | Spanish (Spain)           |
| `es-MX`   | Spanish (Mexico)          |
| `es-419`  | Spanish (Latin America)   |
| `pt`      | Portuguese                |
| `pt-BR`   | Portuguese (Brazil)       |
| `pt-PT`   | Portuguese (Portugal)     |
| `fr`      | French                    |
| `fr-CA`   | French (Canada)           |
| `de`      | German                    |
| `it`      | Italian                   |
| `nl`      | Dutch                     |
| `pl`      | Polish                    |
| `ru`      | Russian                   |
| `ru-RU`   | Russian (Russia)          |
| `tr`      | Turkish                   |
| `ar`      | Arabic                    |
| `ar-EG`   | Arabic (Egypt)            |
| `ar-AE`   | Arabic (UAE)              |
| `zh`      | Chinese (Simplified)      |
| `zh-CN`   | Chinese (China)           |
| `zh-TW`   | Chinese (Taiwan)          |
| `zh-HANT` | Chinese (Traditional)     |
| `ja`      | Japanese                  |
| `ja-JP`   | Japanese (Japan)          |
| `ko`      | Korean                    |
| `ko-KP`   | Korean (North Korea)      |
| `vi`      | Vietnamese                |
| `id`      | Indonesian                |
| `jv`      | Javanese                  |
| `th`      | Thai                      |
| `th-TH`   | Thai (Thailand)           |
| `hi`      | Hindi                     |
| `bn`      | Bengali                   |
| `ne`      | Nepali                    |
| `ur`      | Urdu                      |
| `fa-IR`   | Persian (Iran)            |
| `uk`      | Ukrainian                 |
| `uk-UA`   | Ukrainian (Ukraine)       |
| `he`      | Hebrew                    |
| `el`      | Greek                     |
| `el-GR`   | Greek (Greece)            |
| `sr`      | Serbian                   |
| `sr-Latn` | Serbian (Latin)           |
| `sr-YU`   | Serbian (Yugoslavia)      |
| `hr`      | Croatian                  |
| `bs`      | Bosnian                   |
| `sl`      | Slovenian                 |
| `mk`      | Macedonian                |
| `hu`      | Hungarian                 |
| `ro`      | Romanian                  |
| `cs`      | Czech                     |
| `cs-CZ`   | Czech (Czechia)           |
| `sk`      | Slovak                    |
| `et`      | Estonian                  |
| `lv`      | Latvian                   |
| `lt`      | Lithuanian                |
| `da-DK`   | Danish (Denmark)          |
| `fi-FI`   | Finnish (Finland)         |
| `nb-NO`   | Norwegian Bokmål (Norway) |
| `sv-SE`   | Swedish (Sweden)          |
| `ca`      | Catalan                   |
| `ms`      | Malay                     |
| `tl`      | Filipino/Tagalog          |
| `tl-PH`   | Filipino (Philippines)    |
| `ceb`     | Cebuano                   |
| `my`      | Burmese                   |
| `km`      | Khmer                     |
| `lo`      | Lao                       |
| `ka`      | Georgian                  |
| `az`      | Azerbaijani               |
| `kk`      | Kazakh                    |
| `ky`      | Kyrgyz                    |
| `uz`      | Uzbek                     |
| `mn`      | Mongolian                 |
| `am`      | Amharic                   |
| `so`      | Somali                    |
| `sw`      | Swahili                   |
| `af-ZA`   | Afrikaans (South Africa)  |
| `ht`      | Haitian Creole            |
| `hmn`     | Hmong                     |

## See Also

- [Theming & Styling](/sdk-reference/web-sdk-2-theming/): Customize appearance
- [IncodeFlow Component](/sdk-reference/web-sdk-2-incodeflow-component/): Full props reference
