YAML
YAML locale files, from Rails on
YAML has carried Rails translations since version 2.2:
config/locales/en.yml, a locale root key, and a
readable tree underneath. Symfony and static site generators read it too. It is the
most human friendly of the translation formats and the most sensitive to
whitespace, and that tension shapes most of its rules.
This page covers the syntax, the quoting rules that keep ICU plurals parseable, and the conventions each framework expects.
fr:
menu:
home: Accueil
projects: Projets
checkout:
title: Récapitulatif de commande
items: "{count, plural, one {# article} other {# articles}}" Cheatsheet
YAML locale syntax in five rows
fr: as the root key The Rails locale root convention. The tree under it becomes your keys. "{count, plural, …}" ICU messages need quotes, since a bare { starts a YAML map. Quoted, the whole plural imports intact. &defaults, *alias, <<: Anchors, aliases and merge keys resolve on import; every alias becomes an independent copy, so editing one does not edit the other. : or a leading % Need quoting to parse. When in doubt, quote; a conservative exporter quotes anything not obviously safe. # comments Legal YAML, but no translation model carries them. Keep translator context in notes on the key; formats built for comments can hold them. Nested or flat, side by side
The tree Rails expects, or flat dotted keys under the locale root.
de:
menu:
home: Startseite
projects: Projekte de:
menu.home: Startseite
menu.projects: Projekte Untranslated keys, three spellings
A file can represent a key German has not translated yet three ways: exported empty, left out entirely, or filled with the source language value.
checkout:
title: Bestellübersicht
confirm: "" checkout:
title: Bestellübersicht checkout:
title: Bestellübersicht
confirm: Confirm purchase Conventions
Where YAML translation files live
config/locales/fr.yml, root key = locale translations/messages.fr.yaml i18n/fr.yaml Typical flow: GitHub or GitLab watches the repo, new keys import on push, and finished translations return as a merge request that only touches changed strings.
How the frameworks write plurals in YAML
Rails puts CLDR categories in subkeys; Symfony reads ICU messages in intl-icu domain files.
de:
cart:
items:
one: "%{count} Artikel"
other: "%{count} Artikel" cart.items: "{count, plural,
one {# item}
other {# items}}" Rails resolves the category at runtime from the subkeys. On import, category subkeys like these are recognized as one plural with separate forms, not as unrelated keys.
Plurals
Plurals in YAML
Like JSON, the format has no plural syntax, so files encode plurals in the tree they already have. Pick an encoding and see how the same plural grows from English to Polish. Every encoding has a dedicated guide.
items: "{count, plural, one {# item} other {# items}}" items: "{count, plural,
one {# artykuł} few {# artykuły}
many {# artykułów} other {# artykułu}}" items: "{count, plural,
zero {لا عناصر} one {عنصر واحد}
two {عنصران} few {# عناصر}
many {# عنصرًا} other {# عنصر}}" One quoted string carries every branch.
items:
one: "# item"
other: "# items" items:
one: "# artykuł"
few: "# artykuły"
many: "# artykułów"
other: "# artykułu" items:
zero: "لا عناصر"
one: "عنصر واحد"
two: "عنصران"
few: "# عناصر"
many: "# عنصرًا"
other: "# عنصر" CLDR categories as subkeys. This is the Rails idiom, and category subkeys are recognized as one plural on import.
items:
- "# item"
- "# items" items:
- "# artykuł"
- "# artykuły"
- "# artykułów"
- "# artykułu" A sequence in CLDR order; only position says which form is which.
item: "{{count}} item"
item_plural: "{{count}} items" Legacy i18next: base key plus _plural, one and other only. Polish and Arabic cannot be expressed in it.
item_one: "{{count}} item"
item_other: "{{count}} items" item_one: "{{count}} artykuł"
item_few: "{{count}} artykuły"
item_many: "{{count}} artykułów"
item_other: "{{count}} artykułu" Modern i18next: one suffixed key per CLDR category.
items: "# item|# items" items: "# artykuł|# artykuły|# artykułów|# artykułu" Every form in one pipe separated string, the Symfony translation convention.
The categories per language come from CLDR: Polish needs four forms, Arabic six, Japanese only one.
In locamorph
How locamorph handles YAML
Trees in, trees out
Nested locale trees import as dotted keys and export back as trees. Flat files stay flat. The shape of your file is a setting, not an accident.
Plurals as ICU messages
All CLDR forms travel inside one ICU message, so a plural never collapses to a single form between import and export.
Indentation you can trust
Exports follow the project’s indentation settings every time. No mixed tabs, no drifting levels, no Monday morning YAML parse error.
Convert
Convert YAML to and from other formats
Conversion is import plus export; the key model is shared, so a Rails tree can leave as anything locamorph writes.
YAML to JSON
A Rails backend growing a JavaScript front end.
- Import
config/locales/en.yml; the locale root is understood. - The tree structure carries over unchanged.
- Export as JSON, nested or flat, for your JS i18n library.
JSON to YAML
The reverse trip, re-rooted for Rails.
- Import the JSON file.
- Nothing to adjust; keys and plurals map one to one.
- Export as YAML with stable indentation and conservative quoting.
YAML to XLIFF
Handing a Rails app to a translation agency.
- Import the YAML locales.
- Source and target languages pair up per key.
- Export XLIFF 1.2 for any CAT tool.
Related
Keep going
JSON
The same trees for JavaScript apps, with the same plural guarantees.
XLIFF
The interchange format when an agency or CAT tool enters the picture.
GitLab integration
Locale files synced by merge request, formatted the same way every time.
Further reading
- YAML 1.2 specification
- Rails Internationalization guide, the format’s home turf
- ICU MessageFormat, the plural syntax carried in values
Bring your config/locales
Import a YAML locale file on the free plan and get it back with the same structure, the same indentation and only the translations changed.