Works with the AI Agents you already use

    Claude CodeClaude CodeCursorCursorCodex CLICodex CLIMuseMuseDotsDots+22 more

    Translation Key Drift Auditor

    2

    Compares a project's locale catalogues against the code that looks keys up in them and returns a ranked drift report

    $5

    /mo

    Subscription · cancel anytime

    Secure checkout via Stripe

    • Always the latest version
    • Delivered live to your agent via MCP
    • Cancel anytime, access ends at period end
    Security scanned
    Translation Key Drift Auditor

    Translation Key Drift Auditor

    Example session with this skill installed

    The Arabic build is showing odd plurals and I think our English file has fallen behind. Audit the l10n files against the app.

    • Read your context and instructions
    • Compiled the translation key drift

    Translation drift - lib/l10n

    Base fr, 8 keys - checked: en, ar
    1 breaking, 1 missing, 3 never extracted, 1 plural gap, 1 unused, 1 not provable

    Base locale is

    fr, not en: l10n.yaml:2 sets template-arb-file: app_fr.arb, and README.md:3 says the same. French is the file everything else is measured against, so "the English file has fallen behind" is the right instinct - English is a translation here, and it is the one with a hole in it.

    Lookup pattern in use: Flutter gen-l10n. Every call site binds final l10n = AppLocalizations.of(context); and then reads a generated member - l10n.appTitle, l10n.welcomeUser(crewName). Seven such lookups across three screens, all static member access. No template literals, no concatenation, no map indexing: there are

    no dynamic key prefixes in this repo, so the unused list below is settled by search rather than guessed at.

    Breaking - placeholder mismatch

    1. welcomeUser - base expects {name} - lib/l10n/app_fr.arb:4 (declared @welcomeUser.placeholders.name, lib/l10n/app_fr.arb:5-11)
      en: no placeholder at all - lib/l10n/app_en.arb:4 "Welcome back"
      ar: has {name} - lib/l10n/app_ar.arb:4 (correct)
      Called with an argument at lib/screens/home_screen.dart:17 - Text(l10n.welcomeUser(crewName))
      Effect: the generated AppLocalizationsEn.welcomeUser(String name) still takes the crew name and never renders it. English readers get a bare "Welcome back" while French and Arabic readers get the name. It does not throw - it silently drops information, which is why nobody has reported it.
      Fix: "welcomeUser": "Welcome back, {name}"

    Missing in a shipping locale

    • settingsTitle - en - used at lib/screens/settings_screen.dart:13, base at lib/l10n/app_fr.arb:12

    Shows

    "Paramètres" - the French base string, not the raw key. gen-l10n backfills any message absent from a locale ARB with the template locale's message (it warns at build time and carries on), and l10n.yaml:4 nullable-getter: false means the call site never guards for it. So the English settings screen has a French title in the app bar.
    Present in ar at lib/l10n/app_ar.arb:5, so this is an English-only hole.
    Fix: "settingsTitle": "TODO(en) Paramètres" - the marker keeps the build green without shipping an invented string; an English writer replaces it with "Settings".

    Never extracted

    • "Save changes" - lib/screens/home_screen.dart:19 - suggested key saveChanges
      Rendered as a bare const Text inside the home column, between two translated widgets. French and Arabic readers see English.
    • "Clear offline cache" - lib/screens/settings_screen.dart:17 - suggested key clearOfflineCache
      ListTile title, directly beneath a translated batteryWarning tile.
    • "Close settings" - lib/screens/settings_screen.dart:19 - suggested key closeSettings
      A Semantics(label:) - it never appears on screen, but it is what TalkBack and VoiceOver read aloud. An Arabic screen-reader user hears an English phrase. Easy to miss precisely because it is invisible.

    All three follow the camelCase convention already used across the catalogue. Each needs the key added to app_fr.arb (with the French source string), then TODO(en) / TODO(ar) stubs, and the call site changed to Text(l10n.saveChanges) and so on. The const on lines 19 and 17 has to go - a localized lookup is not a compile-time constant.

    Plural gaps

    • syncPending - ar needs zero, one, two, few, many, other - has only one, other - lib/l10n/app_ar.arb:6
      This is the odd Arabic plurals you are seeing, and it is invisible to a missing-key check: the key is present in every locale, so nothing flags it. Arabic is a six-category language under CLDR. With only one and other defined, ICU falls through to other for every count that is not 1 - so 0, 2, and 3-10 reports all render the other form. The other form here is {count} تقارير (the paucal/plural noun), which is wrong for 0 and for exactly 2, and grammatically the wrong number class for 11 and above. The count itself will also render in whichever digit set the locale resolves to, unrelated to this gap.
      Fix: the categories are mechanical, the strings are not. The skeleton is
      {count, plural, zero{TODO(ar)} one{...} two{TODO(ar)} few{TODO(ar)} many{TODO(ar)} other{...}}
      keeping the existing one and other arms. The five new arms need an Arabic speaker - this audit does not write them.
    • en: one / other at lib/l10n/app_en.arb:5 - correct and complete for English.

    Note, not counted as a finding: fr formally carries a many category in CLDR, but it fires only for compact notation (1M, 2M). syncPending is called with a plain int from lib/screens/home_screen.dart:18, so that category is unreachable here. Adding it would be noise.

    Unused

    • deprecatedTooltip - lib/l10n/app_fr.arb:38, and translated in both locales (lib/l10n/app_en.arb:9, lib/l10n/app_ar.arb:10)
      Zero references in lib/. No dynamic lookups exist in this repo, so nothing can be reaching it by a constructed key. The name suggests it was already known to be dead. Cleanup only, no urgency - and it is worth one grep across any code not in this repo before deleting three translated strings.

    Not provable

    • Which locales actually ship - no MaterialApp / supportedLocales declaration exists anywhere in this repo (the three files under lib/screens/ are the whole of the Dart source). "en, ar, fr ship" is taken from the ARB files present in lib/l10n/ plus README.md:4. If a locale is registered but has no ARB, this audit cannot see it.

    Verdict

    Not safe to ship in English or Arabic today: English silently drops the crew name from the welcome line and shows a French settings title, Arabic gets the wrong plural form for every count except one, and three user-facing strings - including a screen-reader label - were never extracted at all.

    is taken from the ARB files present in plus README.md
    $5/mo

    Subscription · always the latest version

    • Secure checkout via Stripe
    • Cancel anytime
    • Delivered live via MCP (optional)

    About this skill

    Locale files drift away from the code that reads them, and nobody notices until a customer sees a raw key on screen. This skill checks your catalogues against the lookups in the code and returns a ranked report: placeholder mismatches that break at runtime first, then keys missing from a shipping locale, strings nobody ever extracted, plural categories that pl, ru and ar require but the catalogue never got, and dead keys last. Every finding cites the catalogue line and the code line.

    What it does

    Compares a project's locale catalogues against the code that looks keys up in them and returns a ranked drift report - placeholder mismatches first because those break at runtime, then keys missing from a shipping locale, user-facing strings that were never extracted, plural categories a language requires but the catalogue lacks, and dead keys last. Every finding carries the catalogue line and the code line that settle it.

    Try it first

    Open a repo that has a locales folder and say "check the translations against the code before we ship". You should get back a Translation drift report: the base locale it picked and why, six counts, then the ranked sections - breaking placeholder mismatches with the corrected string, keys missing per locale with what the reader sees instead, literals still sitting in the components, plural gaps named by CLDR category, unused keys, anything it could not settle, and a one-sentence verdict on whether the catalogue is safe to ship.

    What it needs

    An agent that can read and search the repo - Read, Grep, Glob and Bash. No API keys, no MCP servers, no network access. Framework-agnostic: it learns your lookup patterns from your own call sites instead of assuming i18next, react-intl, Vue I18n, gettext or ARB.

    How to use

    Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.

    Reviews

    No reviews yet

    Be one of the first to try it. Every listed skill passes our trust checks below.

    Security scanned

    Passed our 8-point scan before listing

    Fresh listing

    Recently published to Agensi

    Free forever

    No account required to browse

    Trust & safety

    Security scanned

    Verified clean 6 days ago

    Listed6 days ago

    What's inside

    Frequently Asked Questions