Install any skill in seconds. Free to start, no credit card required.
Get Started Free →ledgerhq/i18n-keys
Write wording keys the i18n key check can verify. Read when adding or changing t() / Trans i18nKey calls, key tables (titleKey, labelKey, ...) or English catalog entries in features/, domain/ or shared/, or when `lint:i18n-keys` fails.
Passed 23 of 23 test cases with the skill, and 10 of 23 without it.
and 20 more in the full report
13 fixed10 passed either way0 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 13 test cases the skill fixed. Same model, same prompt, with and without the skill.
After refactoring dynamic string lookups into literal calls in Ledger Live, CI failed with a notice that the unverifiable baseline count decreased. Which command must be executed locally to update the baseline configuration to the new lower count?
| Checked | Without skill | With skill |
|---|---|---|
| Specifies the command node tools/nx-plugins/enforce-i18n-keys/validate.js --update-baseline. | Missed | Passed |
The instructions your model reads when the skill loads.
pnpm lint:i18n-keys (tools/nx-plugins/enforce-i18n-keys) checks that every key used in
features/, domain/ and shared/ exists in the English catalog of each app consuming the
package: Desktop static/i18n/en/app.json, Mobile src/locales/en/common.json.
.web.* files are checked against Desktop only, .native.* against Mobile only.
Other locales are not checked: only edit English.
A feature resolves its own wording with useTranslation(). Apps must not inject keys or labels
into features: pass a domain id or variant (stage, status) and let the feature map it to wording.
A key prop coming from apps/* is a smell; key props between components of the same package are fine.
A key is verified when its type is a finite set of literals. A key typed string is
unverifiable: it is counted and the count may never go up (unverifiable-baseline.json).
Prefer, in this order:
t("payTab.login.title"). Greppable, needs no types.type Stage = "intro" | "login";
declare const stage: Stage;
t(`payTab.login.${stage}.title`); // every Stage member is expanded and checked
type Props = { titleKey: "x.intro.title" | "x.login.title" };
What widens a key to string and hides it:
const COPY: Record<Id, { titleKey: string }> = { ... }; // annotation widens: use as const satisfies
const rows = [{ key: "a" }, { key: "b" }]; // add as const
function labelKey(kind: Kind): string { ... } // annotate the literal union
test cases passed, vs 10 / 23 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.