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

# Advanced capabilities

> Use Hinglish code-switching and text normalizers to control how Sonic speaks specialized content.

Sonic handles most transcripts as-is. The capabilities below cover cases where you want finer control over mixed-language speech and how written forms are spoken.

## Hinglish

Sonic supports code-switching between Hindi and English (Hinglish) in a single generation. Pass the transcript in conventional written form — Devanagari, Latin script, or a mix — and the model switches languages naturally mid-sentence.

```python theme={null}
from cartesia import Cartesia

client = Cartesia(api_key="your-api-key")
response = client.tts.generate(
    model_id="sonic-3.6",
    transcript="आपका order confirm हो गया है। Delivery expected by Friday.",
    voice="a0e99841-438c-4a64-b679-ae501e7d6091",
    language="hi",
)
audio = response.read()
```

### Romanized Hindi and Indic text

Sonic reads Hindi and other Indic languages written in Latin script — Hinglish and other transliterated text — and follows romanized transcripts materially better in Sonic 3.6.

Write romanized text the way it's naturally typed, and keep English words in their standard spelling:

```text theme={null}
Aapka order confirm ho gaya hai. Delivery kal shaam tak hogi.
```

Set the `language` field to the language of the transcript (`hi` for Hinglish) even when the text is romanized.

Quality varies with how scripts are mixed in the transcript:

| Script mix                     | Example                            | `language`    | `normalization` |
| ------------------------------ | ---------------------------------- | ------------- | --------------- |
| Pure Devanagari                | `आपका औडर आ गया है।`               | `hi`          | `hi-IN`         |
| Pure English                   | `Your order has arrived.`          | `en` or `hi`  | `en-IN`         |
| Pure romanized Hindi           | `Aapka order aa gaya hai.`         | `hi`          | `en-IN`         |
| Romanized Hindi + English      | `Aapka order confirm ho gaya hai.` | `hi`          | `en-IN`         |
| Devanagari + English loanwords | `आपका order confirm हो गया है।`    | `hi`          | `hi-IN`         |
| Devanagari + romanized Hindi   | `आपका order aa gaya hai.`          | Not supported | —               |
| All three scripts              | `आपका order confirm ho gaya है।`   | Not supported | —               |

For pure English transcripts, either `en` or `hi` works as the language: the more Indian words the sentence carries — names, places, product terms — the more the `hi` setting pronounces them correctly.

<Tip>
  Experiment with these settings to find what sounds best for your content. Both `language` and `normalization` are set per generation, so you can vary them transcript by transcript rather than picking one combination for your whole integration.
</Tip>

### Worked examples

These fields control different parts of generation:

* `language` or `locale` identifies the transcript's language and optional region. A regional locale selects the matching accent when the voice supports it; otherwise, the voice uses its default accent for that language. Both fields accept language codes such as `en` and locale codes such as `en-GB`. Set one, never both.
* `accent` overrides locale-based accent selection. It must match one of the voice's supported accents. [Learn more here](/build-with-cartesia/capability-guides/multilingual-voices#add-a-deliberate-accent).
* `normalization` sets how dates, times, and numbers are read. Use `auto` (default), `off`, or a language or locale code.

#### Hindi voice, English digit reading

An OTP or confirmation code inside a Hindi transcript should read digit-by-digit the English way: `4821` as "four eight two one" rather than as a Hindi number.

```json theme={null}
{
  "model_id": "sonic-3.6",
  "transcript": "आपका OTP 4821 है।",
  "voice": "a0e99841-438c-4a64-b679-ae501e7d6091",
  "locale": "hi",
  "normalization": "en-IN",
  "output_format": { "container": "mp3", "sample_rate": 44100, "bit_rate": 128000 }
}
```

#### Romanized Hindi with English read-outs

The highest-traffic combination: a Hinglish transcript spoken with a Hindi-Indian accent while dates, times, and digits follow English-Indian conventions.

```json theme={null}
{
  "model_id": "sonic-3.6",
  "transcript": "Aapka order 14/08/2026 ko deliver hoga, confirmation code 4821 hai.",
  "voice": "a0e99841-438c-4a64-b679-ae501e7d6091",
  "locale": "hi-IN",
  "normalization": "en-IN",
  "output_format": { "container": "mp3", "sample_rate": 44100, "bit_rate": 128000 }
}
```

## Locale codes

Pass a locale code such as `en-GB` through [`locale`](/api-reference/tts/bytes#body-locale-one-of-0).

### When should I use a locale instead of a language?

For Sonic 3.6 and later, use [`locale`](/api-reference/tts/bytes#body-locale-one-of-0). The older [`language`](/api-reference/tts/bytes#body-language-one-of-0) field remains supported for existing integrations. Both accept base language and regional locale codes, but you cannot set both. The value controls regional behavior: `en` leaves the region unspecified, while `en-GB` selects a British accent when the voice supports it and uses British text-normalization conventions. If the voice does not support that regional accent, it uses its default English accent.

Set `normalization` separately to override the reading conventions. For example, with a voice that supports a British accent, `locale: "en-GB"` with `normalization: "en-US"` selects that accent and reads dates and numbers using US conventions.

To override locale-based accent selection, use [`accent`](/build-with-cartesia/capability-guides/multilingual-voices#using-a-multilingual-voice).

### Which locales are supported?

You can pass any base language code from [Sonic 3.6 language support](/build-with-cartesia/tts-models/latest#language-support), or one of these regional locale codes:

<table>
  <thead>
    <tr>
      <td>Base Language</td>
      <td>Supported Locales</td>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>English (`en`)</td>
      <td>`en-GB`, `en-US*`, `en-IN`,`en-IE`,`en-ZA`,`en-NZ`,`en-SG`,`en-AU`</td>
    </tr>

    <tr>
      <td>Spanish (`es`)</td>
      <td>`es-ES*`, `es-MX`, `es-US` </td>
    </tr>

    <tr>
      <td>French (`fr`)</td>
      <td>`fr-FR*`, `fr-CA`</td>
    </tr>

    <tr>
      <td>Dutch (`nl`)</td>
      <td>`nl-NL*`, `nl-BE`</td>
    </tr>

    <tr>
      <td>Portuguese  (`pt`)</td>
      <td>`pt-PT`, `pt-BR*`</td>
    </tr>

    <tr>
      <td>Bulgarian (`bg`)</td>
      <td>`bg-BG`</td>
    </tr>

    <tr>
      <td>Bengali (`bn`)</td>
      <td>`bn-IN`</td>
    </tr>

    <tr>
      <td>Czech (`cs`)</td>
      <td>`cs-CZ`</td>
    </tr>

    <tr>
      <td>Danish (`da`)</td>
      <td>`da-DK`</td>
    </tr>

    <tr>
      <td>German (`de`)</td>
      <td>`de-DE`</td>
    </tr>

    <tr>
      <td>Greek (`el`)</td>
      <td>`el-GR`</td>
    </tr>

    <tr>
      <td>Finnish (`fi`)</td>
      <td>`fi-FI`</td>
    </tr>

    <tr>
      <td>Gujarati (`gu`)</td>
      <td>`gu-IN`</td>
    </tr>

    <tr>
      <td>Hebrew (`he`)</td>
      <td>`he-IL`</td>
    </tr>

    <tr>
      <td>Hindi (`hi`)</td>
      <td>`hi-IN`</td>
    </tr>

    <tr>
      <td>Croatian (`hr`)</td>
      <td>`hr-HR`</td>
    </tr>

    <tr>
      <td>Hungarian (`hu`)</td>
      <td>`hu-HU`</td>
    </tr>

    <tr>
      <td>Indonesian (`id`)</td>
      <td>`id-ID`</td>
    </tr>

    <tr>
      <td>Italian (`it`)</td>
      <td>`it-IT`</td>
    </tr>

    <tr>
      <td>Japanese (`ja`)</td>
      <td>`ja-JP`</td>
    </tr>

    <tr>
      <td>Georgian (`ka`)</td>
      <td>`ka-GE`</td>
    </tr>

    <tr>
      <td>Kannada (`kn`)</td>
      <td>`kn-IN`</td>
    </tr>

    <tr>
      <td>Korean (`ko`)</td>
      <td>`ko-KR`</td>
    </tr>

    <tr>
      <td>Malayalam (`ml`)</td>
      <td>`ml-IN`</td>
    </tr>

    <tr>
      <td>Marathi (`mr`)</td>
      <td>`mr-IN`</td>
    </tr>

    <tr>
      <td>Malay (`ms`)</td>
      <td>`ms-MY`</td>
    </tr>

    <tr>
      <td>Norwegian (`no`)</td>
      <td>`no-NO`</td>
    </tr>

    <tr>
      <td>Odia (`or`)</td>
      <td>`or-IN`</td>
    </tr>

    <tr>
      <td>Punjabi (`pa`)</td>
      <td>`pa-IN`</td>
    </tr>

    <tr>
      <td>Polish (`pl`)</td>
      <td>`pl-PL`</td>
    </tr>

    <tr>
      <td>Romanian (`ro`)</td>
      <td>`ro-RO`</td>
    </tr>

    <tr>
      <td>Russian (`ru`)</td>
      <td>`ru-RU`</td>
    </tr>

    <tr>
      <td>Slovak (`sk`)</td>
      <td>`sk-SK`</td>
    </tr>

    <tr>
      <td>Swedish (`sv`)</td>
      <td>`sv-SE`</td>
    </tr>

    <tr>
      <td>Tamil (`ta`)</td>
      <td>`ta-IN`</td>
    </tr>

    <tr>
      <td>Telugu (`te`)</td>
      <td>`te-IN`</td>
    </tr>

    <tr>
      <td>Thai (`th`)</td>
      <td>`th-TH`</td>
    </tr>

    <tr>
      <td>Tagalog (`tl`)</td>
      <td>`tl-PH`</td>
    </tr>

    <tr>
      <td>Turkish (`tr`)</td>
      <td>`tr-TR`</td>
    </tr>

    <tr>
      <td>Ukrainian (`uk`)</td>
      <td>`uk-UA`</td>
    </tr>

    <tr>
      <td>Urdu (`ur`)</td>
      <td>`ur-IN`</td>
    </tr>

    <tr>
      <td>Vietnamese (`vi`)</td>
      <td>`vi-VN`</td>
    </tr>

    <tr>
      <td>Chinese (`zh`)</td>
      <td>`zh-CN`</td>
    </tr>
  </tbody>
</table>

If you pass a base language code for English, Spanish, French, Dutch, or Portuguese, Cartesia uses the locale marked with an asterisk (`*`) above.

## Turning normalization off

Setting `normalization` to `"off"` skips automatic normalization. Turn it off when you pre-normalize text yourself, need a custom read-out for a symbol (for example, `#` as "number"), or need all-caps words spoken as words rather than spelled out letter by letter.

Note that explicit tags and other input validation still work with normalization off:

* [SSML tags](/build-with-cartesia/capability-guides/ssml-tags) and [generation controls](/build-with-cartesia/capability-guides/volume-speed-emotion)
* [Pronunciation dictionaries](/build-with-cartesia/capability-guides/custom-pronunciations)
* Transcript buffering
* Input validation: potentially malicious character sequences may be blocked for security and stability reasons

Normalization is set at the request level. If most of a transcript should be normalized but one span shouldn't, write out that span as it should be spoken (along with any other written forms in the transcript that would have needed normalizing) and send the request with normalization off.
