File formats
Built-in formats, how plurals and placeholders round-trip, and how unknown formats are learned.
A format turns file bytes into entries (key, value, comment, plural forms) and entries back into a file. Built-in formats are code; learned formats are declarative templates the AI writes. Both run through the same interface, so everything else (dedupe, translation, review, pull) works the same for every file.
Built-in formats
| Format | Id | Extensions | Locales per file |
|---|---|---|---|
| Xcode String Catalog | xcstrings | .xcstrings | all |
| Flutter ARB | arb | .arb | one |
| JSON (key/value, i18next) | json | .json | one |
| YAML (Rails i18n) | yaml | .yml .yaml | one |
| Apple .strings | ios-strings | .strings | one |
| Apple .stringsdict | ios-stringsdict | .stringsdict | one |
| Android strings.xml | android-xml | .xml | one |
| Gettext PO/POT | gettext-po | .po .pot | one |
| XLIFF 1.2 / 2.0 | xliff | .xlf .xliff | all |
| Java .properties | properties | .properties | one |
| .NET RESX | resx | .resx | one |
| CSV / TSV (multi-locale) | csv | .csv .tsv | all |
Detection and locales
push_file scores every format against the file name and content and picks the most confident. Pass format to force one, or call detect_format to see the candidates without storing anything. The locale of a single-locale file comes from its path (locales/es.json, es.lproj, values-pt-rBR, messages_de.properties) or from locale. Paths are stored as patterns such as locales/{locale}.json, so one file record covers every locale.
What survives a round trip
- Plurals are read into CLDR categories (zero, one, two, few, many, other) and written back in the format's own structure.
- Comments become the string's context, which the translator sees, and are written back where the format has them.
- Placeholders (printf, braces, ICU arguments, template literals, HTML tags) are checked on every translation. A translation that changes them is rejected with
placeholder_mismatchor held for review. - Layout: serializers start from the file as last imported, so ordering, headers and format-specific attributes are kept where the format allows.
Formats it has never seen
When no format is confident about a file, it is not rejected. Instead:
- The file is stored with status
needs_formatand alearn_formatjob starts. You can also start one yourself with a hint about the structure. - The AI reads a sample and writes a declarative template: where keys, values, comments and plurals are. The template is validated against your file; one that reads nothing is rejected.
- A
learn_formattask asks a reviewer tokeep,retireorretry_with_hint. - Kept templates are stored in your workspace and read every similar file from then on, with no model call.
npx @meterapp/glossa detect_format --json '{"filename":"strings.ts","content":"…"}'npx @meterapp/glossa learn_format --json '{"project":"web","path":"i18n/strings.ts","content":"…","hint":"TS object; keys are property names"}'npx @meterapp/glossa list_formats