Drop Locale

YAML i18n translator that runs in your browser

Drop a YAML i18n file in below, pick a target language, download the translated file. The YAML file stays on your device.

Loading translator...

How it works

Drop a Rails I18n or Hugo YAML file on the page, click to choose one, or paste the contents straight in. The parser reads the file in your browser and lists every leaf string under the locale root. Pick a target language and translation starts immediately. The translated file is produced by splicing the new strings into the original bytes, so anchors, aliases, comments, block scalars, indentation, and trailing whitespace round trip untouched.

Quality Warning

Please don’t rely on the quality of these translations to ship a finalized product. This is just a starting point. It’s machine translation and there are no guarantees about its quality.

What we do not do

The file itself never leaves your device. We do not see what you are translating, we do not store any of the strings, and there is nothing about your file in our logs. The privacy wedge in DropFormat is structural: the YAML parser, the Google Translate caller, and the file writer all run inside your browser tab.

What does leave your device: the individual strings go to translate.googleapis.com the same way they would if you pasted them into translate.google.com yourself. We are not in the middle. If your YAML file contains internal product strings you do not want a third party to see, do not translate it here; use an offline tool.

What it supports

Rails I18n (config/locales/en.yml) and Hugo i18n (i18n/en.yaml). The parser is hand-written for the YAML subset these files use, so it is tolerant of common real-world variations: BOM-prefixed files, Windows line endings, leading and trailing blank lines, mixed quote styles, embedded comments, and block scalars Visual Studio’s or Phrase’s export tooling produces.

Nested namespaces. A Rails locale file’s root key is the locale code (en, de, fr). Below it, nested mappings group related strings into namespaces (en.shared.actions.save, en.dashboard.welcome.title). Every leaf string at any depth becomes one translatable entry, keyed by its full path. Insertion order is preserved on round trip.

Hugo sequence layout. Hugo’s classic i18n layout is a top-level sequence of {id, translation} mappings. The parser detects the layout automatically and walks each list item as if it were a mapping. The id value names the entry in the review pane; the translation value is the translatable string. When translation is itself a mapping with CLDR plural keys, each case becomes its own entry.

CLDR pluralization keys are honored. Rails I18n and Hugo both use the CLDR plural-case names (zero, one, two, few, many, other) as nested keys under a parent. The parser treats each case as an independent translatable entry and groups them in the review pane so you can see they belong together. Interpolation placeholders like Rails’s %{count} or Hugo’s {{ .Count }} pass through to the translator as part of the source text and round trip untouched.

Anchors and aliases are preserved. YAML anchors (&name) and aliases (*name) let you reuse a string from one node in another. The anchor target is translatable; aliases referencing it round trip untouched so the file’s reference graph survives. The load banner shows how many alias references the file contained.

Comments are kept. Full-line comments (# Greeting copy), trailing comments (greeting: "Hi" # used on the dashboard), and blank-line spacing all survive the round trip exactly because the compiler splices translations into the original byte stream rather than reserializing.

Quote styles round trip. Plain, single-quoted, and double-quoted scalars in the source are translated and re-emitted using the same style when possible (the compiler escalates to double-quoted form when the translated text requires escapes the original style cannot represent).

Block scalars are translated in place. Multi-line block scalars (|, >, with - or + chomping) are decoded on parse, translated as one string, and re-emitted as a block scalar using the same indicator and indentation.

Not yet: full YAML 1.2 grammar (compact-flow mappings embedded inside scalar values, multi-document streams, tag handles, directive headers), Crowdin or Phrase’s custom comment-as-context conventions, and automatic resolution of alias references (aliases round trip as references; the target’s translation is the single source of truth).

What we tolerate, and what we reject

Some malformed files we repair on the way in. Others we refuse to load so we do not make things worse. This list is the parser’s actual behaviour, generated from the format module itself, not aspirational copy.

Repaired automatically:

  • UTF-8 byte order mark (BOM) at the start of the file
  • Windows (CRLF) or mixed line endings
  • Tabs used for indentation (we treat each tab as one column)
  • File truncated mid-document at the tail (we keep complete entries)

Refused with an explanation:

  • Empty or whitespace-only file. Add at least one locale key with nested string values and re-upload.
  • No translatable string values found. Confirm at least one leaf value is a non-empty string.
  • Looks like a different translation format (JSON, PO, .resx, XLIFF). Use the /translate/ hub to pick the right translator.

Common questions

Which file should I drop here? The source-language file (en.yml) if you want to seed a new locale, or an existing localized file (de.yml, fr.yml, …) if you want to re-translate it from one language into another. YAML i18n files are per-locale; one file targets one locale.

What is Rails I18n? Rails I18n is the Ruby on Rails translation framework. Translations live in config/locales/, one YAML file per locale. The application reads a string by symbol path (t('shared.actions.save')) and Rails picks the locale at request time. Pluralization uses CLDR plural-case names. DropFormat parses the same files Rails reads.

What is Hugo i18n? Hugo is the Go static-site generator. Translations live in i18n/, one YAML / TOML / JSON file per locale. The template calls {{ i18n "greeting" }} and Hugo resolves it for the current locale. The legacy YAML layout is a sequence of {id, translation} mappings; the modern go-i18n v2 layout is a flat mapping. DropFormat parses both.

What about ICU MessageFormat placeholders? They pass through to the translator as part of the source text. Google Translate usually leaves {name} / %{count} / {{ .Count }} intact, but always spot-check the output before shipping.

What if I am translating something Google’s endpoint will not accept? The free endpoint occasionally returns the source unchanged for content it would rather not translate. Those entries show “kept original” in the review pane so you can hand-translate just those.

Does it cache anything? No. Each run starts fresh.

What about PO, XLIFF, TMX, Qt .ts, ARB, .xcstrings, .properties, JSON, .strings, Fluent, .resx? Each has its own translator at /translate/po/, /translate/xliff/, /translate/xliff2/, /translate/tmx/, /translate/ts/, /translate/arb/, /translate/xcstrings/, /translate/properties/, /translate/json/, /translate/strings/, /translate/fluent/, and /translate/resx/. Drop your file at the page that matches it.

Why this exists

Most Rails and Hugo projects ship a single source-language locale file and copy it manually into a translation tool when they need to seed a new language. The tools that exist either require a paid subscription, an API key, or pasting strings into a website that holds onto them forever. DropFormat sits in between: free, browser-based, no upload, designed for the “I just added a feature; give me a first-pass target draft I can paste back into the project and clean up” workflow.