Skip to main content
Localization is available as an add-on to our Growth / Enterprise plans. The main Help page on this topic may be more helpful for a typical workflow.

Workflow overview

  1. Download a translation file for your Experiences (or export from the Experience list).
  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 the translated file(s) via the API or from the Localization page.
  5. Publish the Experiences to make translations live.

Supported file formats

FormatExtensionBest for
YAML.yamlHuman-readable, easy to edit manually
JSON.jsonMachine-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 format (e.g., "es", "fr", "pt-BR").

Merge tags in translations

Translations fully support Handlebars merge tags. You can use merge tags in your translated content:
translations:
  body:
    text: "Hola {{first_name}}, bienvenido a tu panel de control."

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
kindstringoptionalOne of tour, survey, launcher, tooltip
idIDoptionalThe ID of a Chameleon Experience
formatstringrequiredOne of yaml, json
experiencesarray<Object>optionalEach member of this array has two keys kind and id examples
experiences.$.kindstringoptionalOne of tour, survey, launcher, tooltip
experiences.$.idstringoptionalThe ID of a Chameleon Experience

HTTP Response

Downloading into .yaml
GET
# Example [A]
https://api.chameleon.io/v3/edit/tours/6f3c4232c712de665632a5f1/i18n.yaml
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"
Downloading into .json
GET
# Example [A]
https://api.chameleon.io/v3/edit/tours/6f3c4232c712de665632a5f1/i18n.json
{
  "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"
            }
          }
        }
      ]
    }
  ]
}
Example with mixed Experiences
POST
# Example [B]
https://api.chameleon.io/v3/edit/experiences/i18n.yaml
Request body
{
  "experiences": [
    { "kind": "tour", "id": "6f3c4232c712de665632a5ef" },
    { "kind": "survey", "id": "6312dfe6c4232c765632a5f0" },
    { "kind": "tour", "id": "62c7f3c42312de665632a5f1" },
    { "kind": "launcher", "id": "6de665632f3c4232c712a5f2" },
    { "kind": "tooltip", "id": "6f3c4232c712de665632a5f3" }
  ]
}

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

POST
https://api.chameleon.io/v3/edit/i18n
param-description
fileFileoptionalA single file to process for translations
filesarray<File>optionalMultiple files to process for translations

Example: Translating a Tour to Spanish

Step 1: Download the translation file:
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":
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:
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:
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:
LevelKeyDescription
RootidThe translation set ID
Rootlanguage.codeThe language code ("default" for primary, or a BCP 47 code)
Rootlanguage.optionsAll available language codes for the account
RootexperiencesArray of Experiences and their translatable content
ExperienceidThe Experience ID
ExperiencenameThe Experience name (for reference only, not translated)
ExperiencestepsArray of Steps with translatable fields
StepidThe Step ID
SteptranslationsObject 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.