Android strings.xml translator that runs in your browser
Drop an Android strings.xml file in below, pick a target language, download the translated file. The strings.xml file stays on your device.
How it works
Drop a res/values/strings.xml 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 translatable entry inside <resources>: every <string>, every quantity slot of every <plurals>, and every <item> of every <string-array>. Pick a target language and translation starts immediately. The translated file mirrors the original layout: namespace declarations, XML comments, translatable="false" entries, resource references, and the order of every entry round trip unchanged.
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 strings.xml 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 strings.xml 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
Android resource files saved under res/values/ and locale variants like res/values-de/, res/values-fr/. The parser is hand-written for the strings.xml subset Android Studio and gradle’s resource tooling produce, so it is tolerant of common real-world variations: BOM-prefixed files, Windows line endings, leading blank lines, namespace declarations, and the tools:locale attribute Android Studio adds.
Singular strings. A <string name="X">value</string> is one translatable entry. The name attribute is the stable identity used by the application code; we never rewrite it. The value text is sent for translation and the result is written back to the same slot.
Plurals with CLDR quantity slots. Every <plurals name="X"> becomes one entry with one slot per <item quantity="zero|one|two|few|many|other"> child. The quantity attribute on each item round-trips untouched. The Android runtime picks the right slot for the target locale at lookup time, so DropFormat translates the slots the file already declared without scaling to the target language’s CLDR plural rules. If the target locale needs additional quantity classes, add the new <item> elements by hand after download.
String-arrays preserve item order. A <string-array name="X"> becomes one entry with one slot per <item> child. Translation is done in source order; the index that the application code looks up by stays valid. Each item is translated as an independent string so a planet-name array does not get a single shared phrase reused across slots.
translatable=”false” entries round trip untouched. The translatable="false" attribute is Android’s signal that an entry holds an internal identifier (an API URL, a country code, a build constant). DropFormat reads the attribute, skips the entry from the translation queue, and round-trips the original value unchanged. The load banner shows how many entries this affected.
Resource references round trip untouched. Values whose content is wholly a resource reference (@string/foo, @android:string/cancel, @plurals/items, @string-array/colors, @null) point at another resource and must not be rewritten; doing so would break the reference graph at runtime. DropFormat detects them and skips them. The load banner shows the count.
Inline markup is preserved by skipping. Strings that contain inline XML elements (<xliff:g> placeholder wrappers, <b> / <i> / <u> formatting) carry markup Google Translate is likely to mangle. v1 round-trips those entries untouched and reports the count in the load banner so a translator can hand-edit them. Hand-translation of those entries is on the roadmap; for now, the safe default is to keep the original markup intact.
XML comments and namespace declarations survive. XML comments between entries, the xmlns:tools / xmlns:xliff declarations on <resources>, and Android Studio’s tools:locale attribute round-trip exactly.
Not yet: <xliff:g> placeholder preservation across translation (the v1 parser skips entries that contain inline markup so the markup never breaks; future work will protect placeholders during translation), Android escape decoding for review-pane display (\', \", \n, \@, \u####, "..."-quoted leading whitespace; the underlying text round-trips verbatim in both directions today), and <integer-array> translation (its items are integers, not user-facing strings; it round-trips untouched).
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
- Leading blank lines before the XML declaration
- Multiple <resources> elements (we use the first)
- Indented or whitespace-heavy XML formatting
- XML comments anywhere in the document
Refused with an explanation:
- Empty or whitespace-only file. Add at least one <string name="…"> entry under <resources> and re-upload.
- XML syntax error or unclosed element (e.g. <string> never closed). Fix the XML so it parses, then re-upload.
- No translatable <string> entries (all marked translatable="false" or empty). Confirm at least one <string> entry is non-empty and not marked translatable="false".
- Looks like a different translation format (JSON, PO, .resx, XLIFF, YAML). Use the /translate/ hub to pick the right translator.
Common questions
Which file should I drop here? The source-language file (res/values/strings.xml) if you want to seed a new locale, or an existing localized file (res/values-de/strings.xml, res/values-fr/strings.xml) if you want to re-translate it from one language into another. Android strings.xml files are per-locale; one file targets one locale.
What is res/values/? Android’s resource system stores per-configuration string resources under res/values*/. The default-locale file lives at res/values/strings.xml; a locale-specific variant lives at res/values-LANG/strings.xml (e.g. res/values-de/strings.xml). The application code looks strings up by name (getString(R.string.cancel)) and Android resolves the right locale at runtime.
What about CLDR plurals? Android’s <plurals> element wraps one <item quantity="..."> per CLDR plural case the developer chose to declare. At runtime, the application calls getQuantityString(R.plurals.items_in_cart, count) and Android picks the matching quantity slot for the target locale. DropFormat translates each slot in place; the runtime continues to do the selection.
What about placeholders like %1$s or %d? They pass through to the translator as part of the source text. Google Translate usually leaves them intact, but always spot-check the output before shipping. Placeholders wrapped in <xliff:g> currently land in the “kept original” bucket; remove the wrapper temporarily if you want machine translation to take a pass.
Does it cache anything? No. Each run starts fresh.
What about PO, XLIFF, TMX, Qt .ts, ARB, .xcstrings, .properties, JSON, .strings, Fluent, .resx, YAML? 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/, /translate/resx/, and /translate/yaml/. Drop your file at the page that matches it.
Why this exists
Most Android projects ship one source-language locale file and copy it manually into a translation tool when seeding 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 res/values-LANG/ and clean up” workflow.