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

# i18n config

> Field-by-field guide for the i18n config file used by run, status, and sync commands.

## File overview

`i18n.yml` controls locales, file mapping, model profiles, and optional advanced routing. `i18n.jsonc` is still supported for compatibility.

## Starter config

```yaml theme={null}
locales:
  source: en-US
  targets:
    - es-ES

buckets:
  ui:
    files:
      - from: packages/ui/lang/{{source}}.json
        to: apps/web/lang/{{target}}.json

llm:
  profiles:
    default:
      provider: openai
      model: gpt-5.2
```

This is the shape written by `hyperlocalise init`.

When `groups` is omitted, Hyperlocalise automatically uses one implicit `default` group with:

* all locales from `locales.targets`
* all bucket names from `buckets`

## Locales

* `locales.source`: source locale.
* `locales.targets`: list of target locales.
* optional `locales.fallbacks`: fallback order per locale.

## Buckets

`buckets` map source files to target output templates.

Each file mapping uses:

* `from`: source path template
* `to`: target path template

Use `{{source}}`, `{{target}}`, and `{{localeDir}}` in templates. `{{localeDir}}` resolves to an empty segment when target equals source, and to the target locale otherwise.

### PHP array locale mapping patterns

Laravel-style locale arrays can be mapped directly when each file returns one static PHP array.

```yaml theme={null}
buckets:
  app:
    files:
      - from: resources/lang/en/messages.php
        to: resources/lang/{{target}}/messages.php
      - from: resources/lang/en/validation.php
        to: resources/lang/{{target}}/validation.php
```

Supported PHP locale files must begin with `<?php` and return a static `[...]` or `array(...)` literal. Hyperlocalise translates string leaves, flattens nested keys with dotted paths, and preserves comments, ordering, and array syntax when writing. Dynamic PHP such as variables, function calls, constants, `declare(...)`, or interpolated double-quoted strings is intentionally rejected.

Supported locale file extensions include `.json`, `.jsonc`, `.yaml`, `.yml`, `.php`, `.xml`, `.resx`, `.arb`, `.xlf`, `.xlif`, `.xliff`, `.po`, `.html`, `.liquid`, `.md`, `.mdx`, `.strings`, `.stringsdict`, `.csv`, `.srt`, and `.vtt`.

YAML/YML locale files should be mapping-shaped files with string leaves. Nested mappings become dotted keys, sequences become `[index]` keys, and writeback rewrites existing string leaves while preserving key order/comments where possible. Mapping keys cannot contain `.`, `[`, or `]` because those characters are reserved for flattened paths. Non-string scalar leaves such as numbers, booleans, nulls, timestamps, anchors, and aliases are rejected to avoid silently corrupting metadata.

```yaml theme={null}
buckets:
  ui:
    files:
      - from: packages/ui/lang/{{source}}.yaml
        to: apps/web/lang/{{target}}.yaml
```

Generic XML mappings can point at non-Android XML locale files:

```yaml theme={null}
buckets:
  xml:
    files:
      - from: locales/en-US.xml
        to: locales/[locale].xml
```

XML entries must be text-only leaf elements keyed by `key`, `id`, or `name`, or nested path-shaped leaves. Android `<resources>` files, mixed-content XML, and CDATA-preserving writeback are not handled by the generic XML parser.

### CSV file mapping patterns

Use bucket file mappings to model CSV workflows.

Per-locale files:

```json theme={null}
{
  "from": "translations/en.csv",
  "to": "translations/[locale].csv"
}
```

Shared multi-locale file:

```json theme={null}
{
  "from": "translations/catalog.csv",
  "to": "translations/catalog.csv"
}
```

For shared multi-locale CSV files, keep one key column and one target locale column that `run` can update consistently.

### Fluent file mapping patterns

Use `.ftl` mappings for Mozilla Fluent locale files:

```json theme={null}
{
  "from": "locales/en-US/messages.ftl",
  "to": "locales/[locale]/messages.ftl"
}
```

Hyperlocalise supports Fluent messages, attributes, multiline values, and select/plural values as full translation units. Attributes use dotted keys such as `brand.title`. Fluent terms are not supported and fail during parsing.

### Subtitle file mapping patterns

Use `.srt` or `.vtt` mappings for SubRip and WebVTT caption files:

```yaml theme={null}
buckets:
  captions:
    files:
      - from: captions/{{source}}.srt
        to: captions/{{target}}.srt
      - from: captions/{{source}}.vtt
        to: captions/{{target}}.vtt
```

Hyperlocalise translates cue payload text and preserves cue numbers, timestamps, WebVTT headers, and `NOTE` / `STYLE` / `REGION` blocks. Cues use sequential keys such as `srt.0001`.

### JS/TS locale module patterns

Use JavaScript or TypeScript locale module mappings when your app imports locale objects directly:

```yaml theme={null}
buckets:
  web:
    files:
      - from: apps/web/messages/{{source}}.ts
        to: apps/web/messages/{{target}}.ts
```

Supported modules must export one static object, for example:

```ts theme={null}
export default {
  home: {
    title: "Welcome",
    cta: "Start now",
  },
} as const;
```

Hyperlocalise preserves comments, imports, export syntax, and non-message module text. It rejects dynamic values, computed keys, spread properties, multiple exported locale objects, and interpolated template literals.

### Apple string catalog mapping patterns

Use `.xcstrings` mappings for Xcode string catalogs:

```json theme={null}
{
  "from": "ios/en.lproj/Localizable.xcstrings",
  "to": "ios/[locale].lproj/Localizable.xcstrings"
}
```

Hyperlocalise writes target values into `localizations[targetLocale]` and preserves catalog metadata. `status` and `check` read the requested target locale from the catalog. Variant and substitution source entries must include a source-language localization so Hyperlocalise can extract the source forms safely.

### Android XML string resource mappings

Android XML support is intentionally scoped to string resource files named `strings.xml` under `res/values*` directories. Use Android locale qualifier names in your target paths:

```yaml theme={null}
buckets:
  android:
    files:
      - from: app/src/main/res/values/strings.xml
        to: app/src/main/res/values-{{target}}/strings.xml
```

Supported resource entries are `<string name="...">` and `<plurals name="..."><item quantity="...">`. Resources marked `translatable="false"` are preserved and skipped. Unsupported translatable resource shapes such as `<string-array>` fail closed so they are not silently dropped.

### Java properties file mapping patterns

Use `.properties` mappings for Java resource bundles with one file per locale:

```yaml theme={null}
buckets:
  java:
    files:
      - from: src/main/resources/messages_{{source}}.properties
        to: src/main/resources/messages_{{target}}.properties
```

Supported entries are flat Java properties keys with string values. Hyperlocalise preserves comments, separators, and key order on write; translated values are written as escaped single-line `.properties` values.

## Groups

`groups.<name>` defines what to process together.

* `targets`: subset of `locales.targets`
* `buckets`: list of bucket names

`groups` is optional for beginner configs. Add it when you want to split execution by locale or file set.

## LLM profiles

`llm.profiles.<name>` fields:

* `provider`: `openai`, `azure_openai`, `anthropic`, `gemini`, `bedrock`, `lmstudio`, `groq`, `mistral`, `ollama`, `openrouter`, or `ai_gateway`
* `model`: provider model id
* `system_prompt` (optional): explicit system-message template
* `user_prompt` (optional): explicit user-message template
* `prompt` (deprecated, optional): legacy prompt template used as system fallback

Prompt variables:

* `{{source}}`
* `{{target}}`
* `{{input}}`

## Rules

`llm.rules` choose profile per group.

* `priority`: higher wins
* `group`: group name
* `profile`: profile name

`llm.rules` is optional. When no rule matches a group, Hyperlocalise falls back to `llm.profiles.default`.

## Hyperlocalise

`hyperlocalise` configures the public Hyperlocalise web API for `sync push` and `sync pull`.

* `project_id` (required unless `project_id_env` is set): Hyperlocalise project ID.
* `project_id_env` (optional): environment variable that contains the project ID.
* `api_base_url` (optional): API base URL. Defaults to `https://hyperlocalise.com/api`.
* `api_key_env` (optional): environment variable that contains the API key. Defaults to `HYPERLOCALISE_API_KEY`.
* `timeout_seconds` (optional): HTTP timeout for sync API calls. Defaults to `1200`.

`sync push` uploads source files. `sync pull` downloads translated files reconstructed by the API. Translation jobs are created by Hyperlocalise automation or in the web app, not by the CLI.

For API keys, sample config, and CI, see [Connect the CLI](/platform/cli).

## Cache

`cache` configures the remote caching client.

* `enabled` (optional): enable remote caching for `run`.
* `endpoint` (optional unless `enabled=true`): remote cache service endpoint.
* `project_key_env` (optional unless `enabled=true`): environment variable that contains the project cache key.
* `timeout_seconds` (optional): remote cache request timeout in seconds.

## Advanced example

```yaml theme={null}
locales:
  source: en-US
  targets:
    - fr-FR
    - es-ES
  fallbacks:
    fr-FR:
      - es-ES
      - en-US

buckets:
  ui:
    files:
      - from: packages/ui/lang/{{source}}.json
        to: apps/web/lang/{{target}}.json
  docs:
    files:
      - from: docs/{{source}}/**/*.mdx
        to: docs/{{target}}/**/*.mdx

groups:
  app:
    targets:
      - fr-FR
      - es-ES
    buckets:
      - ui
  docs:
    targets:
      - fr-FR
    buckets:
      - docs

llm:
  profiles:
    default:
      provider: openai
      model: gpt-5.2
    docs_review:
      provider: openai
      model: gpt-5.2
      system_prompt: You are a senior technical translator.
      user_prompt: |-
        Translate from {{source}} to {{target}}.

        Keep Markdown and MDX syntax intact.

        {{input}}
  context_memory:
    provider: openai
    model: gpt-5.2
  rules:
    - priority: 100
      group: docs
      profile: docs_review

hyperlocalise:
  project_id: project_123
  api_base_url: https://hyperlocalise.com/api
  api_key_env: HYPERLOCALISE_API_KEY
  timeout_seconds: 1200

cache:
  enabled: true
  endpoint: dns:///cache.internal:443
  project_key_env: HYPERLOCALISE_CACHE_PROJECT_KEY
  timeout_seconds: 5
```

## Generate a starter

```bash theme={null}
hyperlocalise init
```

Then edit the generated `i18n.yml` for your project.

## Validation tips

* If you omit `groups`, every bucket runs for every target locale.
* Keep group targets inside `locales.targets`.
* Keep group buckets aligned with `buckets` keys.
* Keep profile names consistent between `profiles` and `rules`.
* Use `hyperlocalise` for `sync push` and `sync pull`.
* Keep `storage` for provider-specific TMS adapter configuration.
