File formats
Every file format transglot reads and writes, the identifier you use for it in configuration and the API, and how keys, plurals and placeholders map.
transglot reads and writes twenty file formats. Each has an identifier, the string you put in the format field of a CLI rule, in API requests, and in Delivery format for the runtime SDKs.
Formats
| Format | Identifier | Extensions | Plurals | Nested keys | Descriptions |
|---|---|---|---|---|---|
| JSON (flat) | json_flat | .json | No | No | No |
| JSON (nested) | json_nested | .json | No | Yes, split on . | No |
| Laravel JSON | laravel_json | .json | No | No | No |
| Laravel PHP | laravel_php | .php | No | No | No |
| YAML | yaml | .yml, .yaml | No | Yes, split on . | No |
| Flutter ARB | flutter_arb | .arb | Yes, ICU plural messages | No | Yes |
| Android XML | android_xml | .xml | Yes, <plurals> | No | No |
| Apple Strings | ios_strings | .strings | No | No | No |
| Apple Stringsdict | ios_stringsdict | .stringsdict | Plural keys only | No | No |
| Apple String Catalog | ios_xcstrings | .xcstrings | Yes | No | Yes |
| XLIFF 1.2 | xliff_12 | .xlf, .xliff | No | No | Yes |
| XLIFF 2.0 | xliff_20 | .xlf, .xliff | No | No | No |
| gettext PO | gettext_po | .po, .pot | Yes, msgid_plural | No | Yes |
| Unreal PO | unreal_po | .po | No | No | Yes |
| Java properties | java_properties | .properties | No | No | No |
| .NET resx | resx | .resx | No | No | No |
| CSV | csv | .csv | Yes, one row per form | No | Yes |
| Excel | xlsx | .xlsx | Yes, one row per form | No | Yes |
| Unity CSV | unity_csv | .csv | No | No | Yes |
| Markdown / MDX | markdown | .md, .mdx | No | Not key-based | No |
Descriptions means the file has a place for a note to translators, which becomes the key's description when you import and is written back when you export. In the other formats, keep descriptions in the console.
How a format is chosen
- CLI and API. Every CLI rule names its format, and the API takes it as a parameter.
transglot initproposes one from your files. - Browser upload. transglot guesses from the file name and contents, and shows the guess with a control to change it before anything is imported. When it cannot tell, it asks rather than guessing.
The guess uses the extension first, then the contents for extensions several formats share:
.json:@@localemeans Flutter ARB;sourceLanguagewithstringsmeans an Apple String Catalog; any nested object means JSON (nested); a key containing a space means Laravel JSON; otherwise JSON (flat)..xml:<resources>means Android,<root>with<data>means .NET resx,<plist>means Stringsdict..xlfand.xliff: theversionon<xliff>, or the namespace, picks 1.2 or 2.0.
Unity CSV and Unreal PO are never guessed, because their files look like CSV and gettext PO. Choose them explicitly.
One file, one locale
Every format is read and written one locale at a time. A file that holds several languages (an Apple String Catalog, a Unity string table) is read for the locale you are importing, and an export contains that one locale.
Keys
Each format derives key names in its own way, described on its page. Two rules apply everywhere:
- A key name appears once per file. A duplicate is an error, not a silent overwrite.
- Nested formats (JSON (nested) and YAML) join nested object keys with
.when you import ({"home": {"title": ...}}becomeshome.title) and split on.when you export. A project that holds bothhomeandhome.titlecannot be exported to them, becausehomewould have to be both a string and an object. The export fails and names the colliding keys; publishing in such a format fails with the problem typenested-key-collision. Flat formats keep dots as part of the key.
Plurals
transglot stores a plural key as one form per CLDR plural category of each locale: one and other for English, one, few, many and other for Polish, and so on. See Plural forms.
- Formats with a plural construct (the ones marked in the table) read and write those forms. A category the file leaves out is stored empty. In most of them, a category the locale does not use, such as
fewin an English file, is an import error; each format's page says how it handles one. - Formats without one cannot carry a plural key. Exporting to them leaves plural keys out and counts them (the
X-Skipped-Keysresponse header on an API pull). - In any format, a string can hold an ICU message such as
{count, plural, one {# item} other {# items}}. It is stored as an ordinary string and written back unchanged.
Placeholders
Placeholders are read and written exactly as they appear in the file; no format rewrites them. transglot recognizes these syntaxes, and its quality checks flag a translation that loses or alters one:
| Syntax | Examples |
|---|---|
| Double braces | {{name}} |
Single braces (ICU, .NET, Python, Rails %{name}) | {name}, {0}, { user.name } |
| printf | %s, %d, %1$s, %.2f, %% |
| HTML tags | <b>, </b>, <a href="..."> |
| Laravel parameters | :name, :count |
What an export leaves out
An export, a CLI pull, or an API pull contains only translated keys the format can carry. The API's pull response reports each kind of omission in its own header:
| Header | Counts |
|---|---|
X-Omitted-Empty-Keys | Keys with no translation yet in that locale. |
X-Skipped-Keys | Keys the format cannot carry, such as plural keys in JSON, or simple keys in Stringsdict. |
X-Omitted-Invalid-Icu-Keys | On a project whose message syntax is ICU, translations left out because they are not valid ICU. |
The export screen in the console warns before you choose a format that would leave keys out, and blocks one that cannot produce a usable file for the project.
Encoding
Files are read as UTF-8. A leading byte order mark is ignored in the JSON, ARB, String Catalog, Apple Strings, YAML, Java properties, CSV and Unreal PO formats and in the XML-based formats. Other encodings are not supported: convert UTF-16 files (common for older Apple .strings) to UTF-8 first.
Related
Language server
Install the transglot language server to see translations beside your keys, flag missing ones, and extract hardcoded strings in Neovim, JetBrains IDEs, Helix, Sublime Text or any other editor with an LSP client.
JSON
JSON (flat) and JSON (nested): string maps with dotted or nested keys, for i18next, react-intl, next-intl, Vue I18n and most JavaScript stacks.