Formats

strings.xml

Android resource files, one per values folder. Escaping, placeholders and plurals round-trip without hand edits.

What you get

Everything the editor does, through the files you already ship.

  • Every plural form a language has

    Each locale gets exactly the CLDR categories it uses, Arabic six and Japanese one, written in the format's own plural shape.

  • Placeholders round-trip

    %@, %1$s and {count} come back as they went in, and a translation that drops or alters one is flagged before it is verified.

  • AI drafts, a person verifies

    Every language is drafted against your glossary and each key's length limit. A draft never ships until someone has verified it.

  • Runs in CI

    Push the source language on merge and pull every language before the release build, on any CI that can run a shell.

    CI pipelines

Set it up

From nothing to every language.

  1. Step 1: Reference resources the way the module already does

    Nothing changes in code. Key names are written to the file as they are, so name them the way Android wants them: cart_items, not cart.items. Singulars are read with getString, plurals with getQuantityString.

    CartFragment.kt
    titleView.text = getString(R.string.paywall_subscribe_cta)
    countView.text = resources.getQuantityString(
        R.plurals.cart_items, cart.size, cart.size
    )
  2. Step 2: Install the CLI and log in

    Homebrew or the one-line installer, then a token issued per project under Settings, Integrations. The read scope pulls; push writes source files and values; manage creates and deletes keys.

    shell
    brew install anylocale/tap/anylocale
    anylocale login --project my-app
  3. Step 3: Push the source file

    The push is additive: keys missing from the file stay in place, so a truncated file cannot empty a project. Descriptions in the file become translator notes.

    shell
    curl -fsS -X POST "https://anylocale.com/api/loc/push?project=my-app&format=android-xml" \
        -H "Authorization: Bearer $ANYLOCALE_TOKEN" \
        --data-binary @app/src/main/res/values/strings.xml
  4. Step 4: Pull each locale into its values folder

    One file per locale. Placeholders come back positional, plurals as a <plurals> block, and a key's description as the comment above it.

    shell
    anylocale pull --project my-app --locale de --format android-xml \
        --out app/src/main/res/values-de/strings.xml
    app/src/main/res/values-de/strings.xml
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <!-- Items in the cart -->
        <plurals name="cart_items">
            <item quantity="one">1 Artikel</item>
            <item quantity="other">%1$d Artikel</item>
        </plurals>
        <!-- Explains why the app needs the location -->
        <string name="onboarding_location_permission">Standort &amp; Wetter für %1$s erlauben</string>
        <string name="paywall_subscribe_cta">Jetzt abonnieren</string>
    </resources>
  5. Step 5: Script it over the project's locales

    The same command per locale, from a Gradle exec task or the CI job that runs before the build.

    shell
    for locale in de fr ja; do
      anylocale pull --project my-app --locale $locale --format android-xml \
        --out app/src/main/res/values-$locale/strings.xml
    done

Good to know

  • Key names are written verbatim, so an Android project names its keys with underscores; a dot in a resource name fails the build.
  • A string-array is ignored on push and missing from a pulled file. Keep arrays in a resource file the pull does not overwrite.
  • formatted="false" does not survive a pull, so use positional placeholders (%1$s, %2$d) in any string that has more than one.
  • A string marked translatable="false" in the source file stays that way and is never put in front of a translator.
  • Every pull carries the current text of every key, verified or not. Only over-the-air delivery is limited to verified strings.

Questions

Are string arrays and escaping handled?
Escaping yes: apostrophes, quotes and the other characters Android needs escaped are written the way the resource compiler expects. String arrays no: a string-array is ignored on push and absent from a pulled file, so keep arrays in a resource file anylocale does not overwrite.
Which folder does each locale go to?
The source locale to values/, every other one to its own values-<locale>/ folder. Pull one locale per folder, or script it over the project's locale list.
Do %d and %1$s survive the round trip?
Yes. Placeholders are kept as written, positional forms included, and a translation that drops or alters one is flagged before it is verified.

Start with the file your app already ships.

After checkout, import one strings file and read the first drafts within minutes.

Nothing to connect and nothing to install. The CLI is optional.