StringLane

Skip to content
ARBFlutter ARBmacOS, Windows, Linux

An ARB editor that shows every locale at once

StringLane opens all of your app_*.arb files together, flags what is missing or broken while you type, and writes back to the same files your flutter gen-l10n already reads.

$49 once · No email · Full app for 14 days

StringLane showing a Flutter ARB project with six locales side by side and Missing badges on untranslated cells

The format

What StringLane opens

ARB (Application Resource Bundle) is JSON with a convention. Each translatable key sits beside an optional @key object holding its description, placeholder types and constraints, and Flutter reads the set of files to generate AppLocalizations. StringLane detects the format from the file extension, so there is nothing to configure.

File layout
One JSON file per locale, typically lib/l10n/app_en.arb
Placeholders
{param}, compared between locales by name
Plurals
ICU MessageFormat inline, {count, plural, other{...}}
Metadata
@key objects: @description, x-max-length, x-guarded
Detected by
Any .arb file in the project folder
Project chip
ARB

Verification

What gets flagged, and why it matters in ARB

Validation runs when the project loads and again after every edit. These are the checks that apply to ARB specifically.

Missing key

The key exists in your template locale but is absent or empty in another. Your build still succeeds and the string ships in English, so this is the failure mode that reaches users.

Placeholder mismatch

Placeholders are compared by name, parsed from the ICU syntax tree rather than matched with a regex. That distinction matters: in {count, plural, other{days} one{day}} a regex reads days and day as placeholders, so translating those two words would look like a mismatch. StringLane compares only the real argument, count.

Invalid ICU

Unmatched braces, a plural missing its other category, or a malformed select clause. gen_l10n parses ICU too and will fail the build on malformed syntax. StringLane shows it while you are still in the file.

Standalone #

Flutter has no pound token, so a bare # inside a plural branch renders literally in the UI instead of being replaced by the number. StringLane flags it and the AI fill converts it to a named variable.

Length over the limit

Set x-max-length in a key's @key metadata and any translation longer than that is flagged. German button labels are the usual reason this exists.

Same as base, and guarded words

A value identical to the template locale usually means it was copied and never translated. Terms you mark as guarded, such as a product name, are flagged the other way round when a locale changes them.

What it will not do. StringLane is a file editor, not a translation reviewer. It cannot tell you that a grammatically valid German sentence says the wrong thing. It can tell you the key is missing, the placeholder was dropped, the ICU is malformed and the plural is short a category, which is the part you can check without speaking the language.

Your files

Your files come back the way you left them

StringLane writes to your source files directly. There is no export step and no project database.

  • @key metadata objects are read and written back untouched, including @description, x-max-length and x-guarded.
  • Key order is preserved exactly as it appears in the source file.
  • ICU strings are stored as you wrote them, not normalised into a house style.
  • Open the file in your editor before and after: the diff shows only the values you actually changed.

Your toolchain

Where it sits in a Flutter project

StringLane is a file editor, not a code generator and not a build tool. It edits the .arb files that gen_l10n and the FlutterIntl extension already consume. Your l10n.yaml, your flutter gen-l10n step and your CI all keep running unchanged.

That matters because the build is not the safety net people assume. gen_l10n reports a count of untranslated messages in the build log and does not fail the build, so a missing German string compiles clean and ships as English. A count also says nothing about a translation that exists but dropped its {placeholder}, and nothing at all about your other formats.

FAQ

Flutter ARB questions

Does StringLane replace gen_l10n or FlutterIntl?
No. It sits one layer below both, at the file level. StringLane edits .arb files; gen_l10n reads them and generates AppLocalizations exactly as before. Nothing in your l10n.yaml or your build changes.
Will it reorder my keys or strip my @description annotations?
No. Key order is preserved as found, and the @key metadata objects are written back untouched, in every locale file rather than only the template. If you have lost annotations to an editor before, that is the behaviour worth testing first: open a translated locale, save it, and read the diff.
Does it handle ICU plurals and select forms?
Yes, with a visual editor and a raw tab for the ICU string itself. Invalid syntax is flagged as an error, and a plural missing its other category is caught before gen_l10n refuses to generate.
What about a bare # inside a plural branch?
It is flagged. Flutter's generated code has no pound substitution, so # renders literally in the UI. StringLane detects the standalone case and leaves deliberate literal usage such as rank #1 alone.
Do I need an account or an internet connection?
No account, and no connection unless you choose to use AI fill. StringLane has no server. The 14-day trial does not ask for an email address.

Price

One purchase, no subscription

$49once

Early-adopter price. Full price after launch is $79.

Start the 14-day trial
  • All five formats, not just this one
  • Live validation while you edit
  • AI fill with your own API key, or a local model
  • macOS, Windows and Linux
  • Updates within the major version

The comparison worth making is against a cloud TMS seat rather than against another editor. Lokalise lists $144 a month at entry and $999 a month on its Advanced plan, checked July 2026. That bill arrives every month. This one does not.