Formats

CSV

One locale as a spreadsheet: hand it to a translator who works in Excel or Numbers and import the result.

What you get

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

  • 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.

  • Five checks on every save

    Placeholders, length, terminology, consistency and missing translations are flagged on the row they concern, not in production.

  • Everything is an HTTP call

    Project tokens carry read, push and manage scopes, so a CI token that pushes files cannot delete keys.

    The HTTP API
  • Scriptable from the CLI

    Push, pull and sync from a terminal, a build phase or a coding agent's shell, with a token in the environment.

    The CLI

Set it up

From nothing to every language.

  1. Step 1: The columns

    One row per key, or one per plural category. The comment column carries the key's description so the translator sees the same context the editor shows. Only the value column is theirs to edit.

    de.csv
    key,variable,plural,value,comment
    cart.items,,one,1 Artikel,Items in the cart
    cart.items,,other,%d Artikel,Items in the cart
    onboarding.location_permission,,,"Standort, Wetter & Regen für %s erlauben",Explains why the app needs the location
    paywall.subscribe_cta,,,Jetzt abonnieren,
  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: Export one locale

    The file opens in Excel, Numbers and Sheets as it is. Ask for it back as CSV with UTF-8 encoding, header row intact.

    shell
    anylocale pull --project my-app --locale de --format csv --out de.csv
  4. Step 4: Import the edited file

    The locale is named on the request. Rows are matched by key and plural category; a key the project does not have is reported, never created.

    shell
    curl -fsS -X POST "https://anylocale.com/api/loc/push?project=my-app&locale=de&format=csv" \
        -H "Authorization: Bearer $ANYLOCALE_TOKEN" \
        --data-binary @de.csv

Good to know

  • A cell starting with =, +, -, @, a tab or a carriage return would open as a formula, so it is prefixed with an apostrophe on export and unprefixed on import. Translators should leave that apostrophe alone.
  • Values written through a push are marked translated, not verified; verification stays a human step in the app.

Questions

Does an import mark the strings verified?
No. Values written through a push are marked translated, and verification stays a human step in the app, where the five checks have run on each row.
Can one spreadsheet hold every locale?
No, one file per locale. That is what keeps a translator's file to the one language they work in, and an import from reaching a locale it was not meant for.
Which columns does the export have?
key, variable, plural, value and comment. The plural column carries the CLDR category on a plural's rows and is empty otherwise; the variable column is used only by keys with several counted variables.
Which other formats can the same project be pulled in?
.xcstrings, .strings with .stringsdict, strings.xml, JSON, next-intl messages and CSV. A project is not tied to the format it was pushed in, which is how an iOS app and an Android app share one catalog..xcstrings.stringsstrings.xmlJSONnext-intlCSV

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.