Start here
For your first project, copy the tested configuration from Translate your first file. You need only source and target locales, a source-to-target file mapping, and an AI provider profile.
The sections below are the complete field reference. Add advanced settings only when your workflow needs them.
File overview
i18n.yml controls locales, file mapping, model profiles, and optional advanced routing. i18n.jsonc is still supported for compatibility.
CLI version pin
Pin the Hyperlocalise CLI version at the top ofi18n.yml, similar to packageManager in package.json:
run, check, status, pack, sync, and others) fail if the running CLI version does not match the pinned value. The hl alias is also accepted (hl@1.13.3).
In GitHub Actions, set hyperlocalise-version: config to install the version declared in your i18n config file.
Starter config
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. - optional
locales.copies: map a target locale to another locale whose catalog should be copied instead of translated. Use this when one locale should ship as a duplicate of another, for exampleen-AUcopyingen-GB.
run still writes a catalog for the copy locale. It does not call an LLM or MT provider for that locale. After the origin locale is translated (or when its files already exist), Hyperlocalise copies those values into the copy locale’s output paths. The copy replaces the destination catalog: keys that exist only on the destination are removed. Image copies convert the origin bytes into the destination file format when the extensions differ, for example banner.png to banner-en-AU.webp.
The copy key must be in locales.targets. The origin must be locales.source or another target that is not itself a copy. A locale cannot be both a copy and a locales.fallbacks key. Copy locales need their own output files, so the bucket to path must include {{target}}, {{localeDir}}, or [locale].
Include copy locales in groups.*.targets (or omit groups so the implicit default group includes every target). hl run --locale en-AU copies from existing origin files and does not translate the origin. Translate the origin first, or run both locales together.
Buckets
buckets map source files to target output templates.
Each file mapping uses:
from: source path templateto: target path template- optional
srx: built-in sentence-break template (default,html,markdown) or a project-relative SRX 2.0 file. When set,runsplits string values into sentence spans before translation and joins them back to the original keys on write. JSON and YAML stay unsplit unlesssrxis set. Already-segmented formats (XLIFF, PO, SRT, VTT, xcstrings, stringsdict) and FormatJS/ARB parser modes ignoresrx. ICU, printf, and Fluent{ $var }values stay one unit.hl run --srxoverrides this field for the whole invocation.
{{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.<?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.
See File formats for the complete list of supported extensions, source examples, and writeback limitations.
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.
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.
Windows Runtime .resw files use the same parser. Map one file per locale, typically under Strings/<locale>/:
.ts catalogs use a dedicated parser. Map one file per locale. The CLI detects Qt from a <TS> root so TypeScript locale modules that also use .ts stay on the JavaScript parser:
CSV file mapping patterns
Use bucket file mappings to model CSV workflows. Per-locale files:run can update consistently.
Fluent file mapping patterns
Use.ftl mappings for Mozilla Fluent locale files:
brand.title. Fluent terms are not supported and fail during parsing.
Subtitle file mapping patterns
Use.srt, .vtt, or .sbv mappings for SubRip, WebVTT, and YouTube SBV caption files:
NOTE / STYLE / REGION blocks. Cues use sequential keys such as srt.0001 and sbv.0001. SBV files use comma-separated H:MM:SS.mmm timestamps and have no cue numbers.
JS/TS locale module patterns
Use JavaScript or TypeScript locale module mappings when your app imports locale objects directly:Apple string catalog mapping patterns
Use.xcstrings mappings for Xcode string catalogs:
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 namedstrings.xml under res/values* directories. Use Android locale qualifier names in your target paths:
<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.
INI file mapping patterns
Use.ini mappings for Windows-style localization files with one file per locale:
[section] stay unprefixed. Keys inside a section flatten as section.key. Hyperlocalise preserves sections, comments, separators, and key order on write.
Java properties file mapping patterns
Use.properties mappings for Java resource bundles with one file per locale:
.properties values.
Groups
groups.<name> defines what to process together.
targets: subset oflocales.targetsbuckets: 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, orai_gatewaymodel: provider model idsystem_prompt(optional): explicit system-message templateuser_prompt(optional): explicit user-message templateprompt(deprecated, optional): legacy prompt template used as system fallback
{{source}}{{target}}{{input}}
Rules
llm.rules choose profile per group.
priority: higher winsgroup: group nameprofile: profile name
llm.rules is optional. When no rule matches a group, Hyperlocalise falls back to llm.profiles.default.
Translation routing
translation chooses, per group, whether tasks route to an LLM profile or a machine translation (MT) profile. It configures routing only; llm.profiles still defines provider/model/prompt behavior for every type: llm selection, and mt.profiles defines MT engines (see below).
translation.default(required): fallback selection used when no rule matches a group.type:llmormtprofile: profile name, resolved againstllm.profileswhentype: llm, ormt.profileswhentype: mt
translation.rules(optional): ordered list of per-group overrides.priority: higher priority wins. Priorities must be unique within the same group.group: group name (must exist ingroups, or be the implicitdefaultgroup whengroupsis omitted)type:llmormtprofile: profile name, resolved the same way astranslation.default.profile
translation.rules entry whose group matches. If no rule matches, it falls back to translation.default.
When translation is omitted entirely, Hyperlocalise uses the legacy llm.rules/llm.profiles.default routing described above, unchanged.
Migrating from llm.rules
translation.rules and llm.rules cannot both be set. Setting both fails config validation with:
llm.rules entry into translation.rules and add type: llm. llm.profiles itself does not change:
Machine translation (MT) profiles
mt.profiles.<name> defines an MT engine that translation.default/translation.rules can select with type: mt.
provider:googleordeepl. These are the only supported providers today.api_key_env(required): name of the environment variable that holds the API key. You choose this name yourself — unlike LLM providers, which read a fixed variable per provider (for exampleOPENAI_API_KEY), Hyperlocalise reads whatever variable name you put here. See Provider credentials for exported examples.base_url:- Optional for
google. Defaults to the real Google Cloud Translation endpoint when omitted. - Required for
deepl, and must be exactly one of DeepL’s two API hosts:https://api.deepl.com(Pro accounts) orhttps://api-free.deepl.com(Free accounts). Any other value is rejected when the profile is selected.
- Optional for
mt.profiles is only checked and connected to when a translation rule or default actually selects it. Defining extra MT profiles you aren’t using yet does not require their environment variables to be set.
Mixed MT/LLM example
ui group has no matching rule and falls back to translation.default, so it routes to MT. The marketing group matches a rule and routes to the LLM profile instead — useful when some content (like marketing copy) needs LLM-quality nuance while the bulk of UI strings are translated more cheaply via MT.
MT execution has no automatic fallback to an LLM profile on failure, batches requests, retries transient failures a bounded number of times, and reports character usage separately from LLM token usage. See run for the full execution behavior.
Hyperlocalise
hyperlocalise configures the public Hyperlocalise web API for sync push and sync pull when that block is present.
project_id(required unlessproject_id_envis set): Hyperlocalise project ID.project_id_env(optional): environment variable that contains the project ID.api_base_url(optional): API base URL. Defaults tohttps://hyperlocalise.com/api.api_key_env(optional): environment variable that contains the API key. Defaults toHYPERLOCALISE_API_KEY.timeout_seconds(optional): HTTP timeout for sync API calls. Defaults to1200.
hyperlocalise is set, sync push uploads source files and 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. A hyperlocalise block wins over storage.adapter when both are set.
When hyperlocalise is absent, set storage.adapter so sync push and sync pull use TMS entry sync. That path uses the first bucket files[].to mapping and currently requires one concrete flat JSON locale file. Keep storage for provider-specific file commands as well.
For API keys, sample config, and CI, see Connect the CLI.
Cache
cache configures the remote caching client.
enabled(optional): enable remote caching forrun.endpoint(optional unlessenabled=true): remote cache service endpoint.project_key_env(optional unlessenabled=true): environment variable that contains the project cache key.timeout_seconds(optional): remote cache request timeout in seconds.
Advanced example
QA policy
qa.policy_file points at a local snapshot of the project’s Cloud QA policy. check reads that path, and --qa-policy overrides it. validate takes the same file with --policy-file.
1 and list all 12 checks. See validate for the file shape, severities, glossary terms, and accepted spelling words.
Generate a starter
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
bucketskeys. - Keep profile names consistent between
profilesandrules. - Keep MT profile names consistent between
mt.profilesandtranslation.rules/translation.default. - Do not set both
llm.rulesandtranslation— migratellm.rulesentries totranslation.rulesinstead. - Use
hyperlocalisewhensync pushandsync pullshould talk to the Hyperlocalise API. That block wins ifstorage.adapteris also set. - Use
storage.adapterwithouthyperlocalisewhensync pushandsync pullshould run TMS entry sync. Keepstoragefor provider-specific file commands as well.

