<!-- Source: https://docs.squirro.com/en/latest/technical/neo/dev-guide/translations.html -->
# Translations

> **Warning**
>
> Project Neo is currently in [Technical Preview](../../../a-z/squirro-glossary.md#term-Technical-Preview). Features described in this section may change before general availability.

Bundles can provide localized strings and override host UI text. No host code changes are required. The CLI scaffolds everything you need.

## Setup

Run this command once in your bundle:

```bash
neo-ui translations init
```

Running the command creates the following files:

- `src/translations/en.json`, `de.json`, `fr.json`, and `it.json`

  Translation files for each supported language.
- `src/translations/use-translation.ts`

  A typed `useExtTranslation()` hook pre-bound to your bundle namespace.

It also updates `src/manifest.ts` to import and pass the translation files. After running the command, the manifest includes:

```typescript
import en from './translations/en.json' with { type: 'json' };
import de from './translations/de.json' with { type: 'json' };
import fr from './translations/fr.json' with { type: 'json' };
import it from './translations/it.json' with { type: 'json' };

const manifest: BundleManifest = {
  name: 'my-dashboards',
  dashboards: [...],
  translations: { en, de, fr, it },
};
```

> **Note**
>
> This command fails if translations are already configured in the project.

## Your Own Strings

Keys without a colon go into the `ext-{name}` namespace. Use them for strings that belong to your bundle:

```json
{
  "dashboard.title": "Analytics",
  "dashboard.empty": "No data available for this period"
}
```

In your component:

```jsx
import { useExtTranslation } from '../translations/use-translation';

function Analytics() {
  const { t } = useExtTranslation();
  return <h1>{t('dashboard.title')}</h1>;
}
```

The `use-translation.ts` file created by `neo-ui translations init` exports a pre-bound hook pointing to your bundle namespace.

## Overriding Host Strings

Keys with a colon (`namespace:key`) override the matching key in the host application. Use this to customize host UI text:

```json
{
  "chat:welcome.inputPlaceholder": "Search legislation and case law..."
}
```

## Discovering Keys to Override

There are two ways to find the key behind any piece of text in the host UI.

### Option 1: Dev Translate Keys

When running `neo-ui dev`, the host language selector (in the bottom-left corner) shows an extra option: Dev: Translate Keys. Selecting it replaces all visible text in the UI with its `namespace:key` identifier. Copy any key directly from the UI and add it to your translation JSON file. Switch back to a supported language to restore normal text.

### Option 2: CLI Key Search

```bash
neo-ui translations keys --search welcome
```

That command lists all host translation keys matching the search term. Use the `namespace:key` format shown in the output directly in your JSON files:

```text
chat:welcome.inputPlaceholder
chat:welcome.title
common:actions.save
common:actions.cancel
...
247 keys listed.
```

For more information, see the [CLI Reference](cli-reference.md#neo-extensions-cli-reference) page.

## Adding Translations to Your Own Dashboards

Provide translations for all supported languages by editing each JSON file in `src/translations/`:

| File | Language |
| --- | --- |
| `en.json` | English |
| `de.json` | German |
| `fr.json` | French |
| `it.json` | Italian |

Keys must be identical across all files. Missing keys fall back to English.

## Adding More Languages

The four built-in languages (English, German, French, and Italian) are always present and cannot be re-added. To support a language beyond the four built-ins, run `neo-ui translations add-locale`:

```bash
neo-ui translations add-locale es
```

That command prompts for a display name. To provide the display name directly, pass the `--label` option:

```bash
neo-ui translations add-locale pt-BR --label "Português (Brasil)"
```

The command copies `en.json` to `src/translations/<code>.json` as your starting point and wires the locale into `src/manifest.ts` (the import, the `translations` object, and a `localeLabels` entry that sets the name shown in the host language selector). Then translate the strings in the new JSON file.

## How It Works

When the host loads your bundle manifest, it reads the `translations` field and registers the strings with the shared `i18next` instance:

- Keys without a colon are added under the `ext-{bundleName}` namespace, isolated from host keys.
- Keys with a colon (for example, `chat:welcome.title`) are merged into the matching host namespace, overriding the host value for that key.

That registration happens at load time. No additional setup is needed in your dashboard components beyond using the `useExtTranslation()` hook for your own strings.
