> ## Documentation Index
> Fetch the complete documentation index at: https://developers.chameleon.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Localization / Internationalization

> The content of Chameleon Experiences can be Localized / Internationalized into a reasonable number of languages

> Localization is available as an add-on to our Growth / Enterprise plans.
>
> The main [Help page](https://help.chameleon.io/en/articles/5868890) on this topic may be more helpful for a typical workflow.

***

## Workflow overview

1. [Download](/apis/translation#i18ns-show) a translation file for your Experiences (or export from the [Experience list](https://app.chameleon.io)).
2. **Translate** the content into your target languages using your preferred translation tool or service.
3. **Rename** the file to include the language code (e.g., `translation-es.yaml`, `translation-fr.json`).
4. [Upload](/apis/translation#i18ns-create) the translated file(s) via the API or from the [Localization page](https://app.chameleon.io/settings/translations).
5. **Publish** the Experiences to make translations live.

### Supported file formats

| Format | Extension | Best for                                           |
| ------ | --------- | -------------------------------------------------- |
| YAML   | `.yaml`   | Human-readable, easy to edit manually              |
| JSON   | `.json`   | Machine-readable, easy to process programmatically |

### How language targeting works

Chameleon determines the user's language from the `browser_l` property (the browser's `Accept-Language` header). The `language.options` array in the translation file shows all configured language codes for your account.

* `"default"` is always the primary language (your original Experience content).
* Language codes follow [BCP 47](https://en.wikipedia.org/wiki/IETF_language_tag) format (e.g., `"es"`, `"fr"`, `"pt-BR"`).

### Merge tags in translations

Translations fully support [Handlebars merge tags](/concepts/personalizing). You can use merge tags in your translated content:

```yaml theme={null}
translations:
  body:
    text: "Hola {{first_name}}, bienvenido a tu panel de control."
```

***

<a id="i18ns-show" />

## Downloading Translation files

#### HTTP Request

```
# Translation file for a single experience [A]
GET|POST https://api.chameleon.io/v3/edit/:kind/:id/i18n(.:format)

# Translation file for all experiences of a specific kind
GET|POST https://api.chameleon.io/v3/edit/:kind/i18n(.:format)

# Translation file for a mixture of many different experience types [B]
GET|POST https://api.chameleon.io/v3/edit/experiences/i18n(.:format)
```

| param                |                | -        | description                                                                                                       |
| -------------------- | -------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `kind`               | string         | optional | One of `tour`, `survey`, `launcher`, `tooltip`                                                                    |
| `id`                 | ID             | optional | The ID of a Chameleon Experience                                                                                  |
| `format`             | string         | required | One of `yaml`, `json`                                                                                             |
| `experiences`        | array\<Object> | optional | Each member of this array has two keys `kind` and `id` [examples](/apis/translation#example-download-experiences) |
| `experiences.$.kind` | string         | optional | One of `tour`, `survey`, `launcher`, `tooltip`                                                                    |
| `experiences.$.id`   | string         | optional | The ID of a Chameleon Experience                                                                                  |

#### HTTP Response

<a id="example-download-model-yaml" />

###### Downloading into `.yaml`

```http title="GET" theme={null}
# Example [A]
https://api.chameleon.io/v3/edit/tours/6f3c4232c712de665632a5f1/i18n.yaml
```

```yaml theme={null}
id: "6f3c4232c712de665632a419"

language:
  code: "default"
  options: ["default", "es", "fr"]

experiences:
  -
    id: "6f3c4232c712de665632a5f1"
    name: "01 Onboarding 🚧"
    steps:
      -
        id: "6f3c4232c712de665632a5f2"
        translations:
          title:
            text: "Hello and Welcome!"
          body:
            text: "The best place to get started is right here, Import your first 100 data points"
          dismiss_text:
            text: "not now"
          buttons:6f3c4232c5632a5f3712de66:text:
            text: "Show me"
      -
        id: "6f3c4232c712de665632a5f3"
        translations:
          body:
            text: "Drag and drop your data here"
```

<a id="example-download-json" />

###### Downloading into `.json`

```http title="GET" theme={null}
# Example [A]
https://api.chameleon.io/v3/edit/tours/6f3c4232c712de665632a5f1/i18n.json
```

```json theme={null}
{
  "id": "6f3c4232c712de665632a419",
  "language": {
    "code": "default",
    "options": ["default", "es", "fr"]
  },
  "experiences": [
    {
      "id": "6f3c4232c712de665632a5f1",
      "name": "01 Onboarding 🚧",
      "steps": [
        {
          "id": "6f3c4232c712de665632a5f2",
          "translations": {
            "title": {
              "text": "Hello and Welcome!"
            },
            "body": {
              "text": "The best place to get started is right here, Import your first 100 data points"
            },
            "dismiss_text": {
              "text": "not now"
            }
          }
        },
        {
          "id": "6f3c4232c712de665632a5f2",
          "translations": {
            "body": {
              "text": "Drag and drop your data here"
            }
          }
        }
      ]
    }
  ]
}
```

<a id="example-download-experiences" />

##### Example with mixed Experiences

```http title="POST" theme={null}
# Example [B]
https://api.chameleon.io/v3/edit/experiences/i18n.yaml
```

###### Request body

```json theme={null}
{
  "experiences": [
    { "kind": "tour", "id": "6f3c4232c712de665632a5ef" },
    { "kind": "survey", "id": "6312dfe6c4232c765632a5f0" },
    { "kind": "tour", "id": "62c7f3c42312de665632a5f1" },
    { "kind": "launcher", "id": "6de665632f3c4232c712a5f2" },
    { "kind": "tooltip", "id": "6f3c4232c712de665632a5f3" }
  ]
}
```

<a id="i18ns-create" />

## Uploading Translation files

Upload one or more translated files. Each file should be a renamed copy of the downloaded translation file with translated text values.

**Important:** The `language.code` in the uploaded file **must** be changed to the target language code (e.g., `"es"`, `"fr"`). If it remains `"default"`, it will overwrite your primary language content.

#### HTTP Request

```http title="POST" theme={null}
https://api.chameleon.io/v3/edit/i18n
```

| param   |              | -        | description                                |
| ------- | ------------ | -------- | ------------------------------------------ |
| `file`  | File         | optional | A single file to process for translations  |
| `files` | array\<File> | optional | Multiple files to process for translations |

### Example: Translating a Tour to Spanish

**Step 1:** Download the translation file:

```bash theme={null}
curl -H "X-Account-Secret: CHAMELEON_SECRET" \
  https://api.chameleon.io/v3/edit/tours/6f3c4232c712de665632a5f1/i18n.yaml \
  -o onboarding-tour.yaml
```

**Step 2:** Copy and translate the file. Change `language.code` from `"default"` to `"es"`:

```yaml theme={null}
id: "6f3c4232c712de665632a419"

language:
  code: "es"
  options: ["default", "es", "fr"]

experiences:
  -
    id: "6f3c4232c712de665632a5f1"
    name: "01 Onboarding 🚧"
    steps:
      -
        id: "6f3c4232c712de665632a5f2"
        translations:
          title:
            text: "¡Hola y bienvenido!"
          body:
            text: "El mejor lugar para comenzar es aquí, importa tus primeros 100 puntos de datos"
          dismiss_text:
            text: "ahora no"
```

**Step 3:** Upload the translated file:

```bash theme={null}
curl -X POST -H "X-Account-Secret: CHAMELEON_SECRET" \
  https://api.chameleon.io/v3/edit/i18n \
  -F file=@onboarding-tour-es.yaml
```

### Uploading multiple files at once

Upload translations for several languages in a single request:

```bash theme={null}
curl -X POST -H "X-Account-Secret: CHAMELEON_SECRET" \
  https://api.chameleon.io/v3/edit/i18n \
  -F 'files[]=@onboarding-tour-es.yaml' \
  -F 'files[]=@onboarding-tour-fr.yaml'
```

### Translation file structure

The translation file contains a nested structure:

| Level      | Key                | Description                                                                          |
| ---------- | ------------------ | ------------------------------------------------------------------------------------ |
| Root       | `id`               | The translation set ID                                                               |
| Root       | `language.code`    | The language code (`"default"` for primary, or a BCP 47 code)                        |
| Root       | `language.options` | All available language codes for the account                                         |
| Root       | `experiences`      | Array of Experiences and their translatable content                                  |
| Experience | `id`               | The Experience ID                                                                    |
| Experience | `name`             | The Experience name (for reference only, not translated)                             |
| Experience | `steps`            | Array of Steps with translatable fields                                              |
| Step       | `id`               | The Step ID                                                                          |
| Step       | `translations`     | Object containing translatable fields (`title`, `body`, `dismiss_text`, button text) |

> Only the `text` values within `translations` should be changed. Do not modify `id` fields or the structure of the file.
