Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when preparing a source file for translation by pulling user-visible text literals out of the code and routing them through a translation function plus a message catalog — JSX/HTML element text, and the alt, title, aria-label, and placeholder attributes, plus error and toast copy shown to a person. Leaves every non-user-facing literal untouched: log and console output, test IDs, object and map keys, enum and discriminant values, URLs, paths, class names, and HTML attribute values like type or role. Do NOT use to translate the extracted strings, to author brand-new copy, or to design the catalog key scheme for an existing framework.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 409% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 405% | 0% |
| case-01 | ✗→✗ | = Same ✗ | 394% | 0% |
| case-02 | ✗→✗ | = Same ✗ | 402% | 0% |
| case-03 | ✗→✗ | = Same ✗ | 408% | 0% |
You are handed a source file. Find every literal that an end user reads on screen, replace it with a call to the translation function t("key"), and add a key → original text line to a message catalog. Leave every other literal exactly as it is. The whole task is one binary decision made over and over: does a human read this string in the running UI? If yes, extract it. If no, it stays a plain literal.
Getting the boundary right matters more than getting many strings. Wrapping a log line, a test id, or an enum value in t() is a bug — it changes program behavior or ships noise to translators. Missing an aria-label leaves a blind user with untranslated text. Precision on the boundary is the whole job.
<h1>Account settings</h1>,<button>Save changes</button>, <p>Your trial ends soon.</p>.
alt, title, aria-label (and aria-description), and placeholder.
snackbar, confirmation dialog, or empty-state message that is rendered to the user.
tab, or column header (the label the person sees, never its underlying value).
console.log/warn/error, logger.*, adebug() call, or a comment. It never reaches the UI.
data-testid, data-cy, data-test, and any id usedfor selection.
Map/Record keys, the first argument tot() itself, dispatch/action type strings, GraphQL field names, event names.
(status === "pending", case "archived":, variant="primary"). It is an identifier, not prose, even though it reads like a word.
type, role, name, href, src, htmlFor,className, class, rel, target, method, autoComplete, inputMode, and the like.
"/api/v1/users", "https://…","config.yaml".
t(...) / <Trans> / i18n.*call is done; do not double-wrap it.
"pending" instatus === "pending" is compared by the code, so it is frozen; "Pending" shown in <span>{label}</span> is read by a user, so it is extracted. Ask what the string is used for, not what it looks like.
alt, title, aria-label,aria-description, and placeholder carry user-facing text. Every other attribute value — even one that happens to be English words — stays a literal. When unsure, an attribute is skipped unless it is on the allowlist.
t("key"). Inside JSX element text, wrap it: <h1>{t("settings.title")}</h1>.settings.title,login.error.badPassword) — never derived from the English words, so the key survives a wording change.
concatenation: t("cart.count", { n }) for a catalog entry "You have {n} items", not "You have " + n + " items".
key: "original text" line to the message catalog. Do not translate the text —the catalog holds the source-language original.
jsx// before <button data-testid="save-btn" aria-label="Save account settings" onClick={save}> Save </button> // after — element text and aria-label extracted; data-testid frozen <button data-testid="save-btn" aria-label={t("account.save.aria")} onClick={save}> {t("account.save.label")} </button> // catalog: account.save.aria: "Save account settings" account.save.label: "Save"
js// before if (status === "error") { console.error("payment failed for order"); toast("We couldn't process your payment."); } // after — only the toast is user-facing if (status === "error") { // "error" is a compared value → frozen console.error("payment failed for order"); // log → frozen toast(t("checkout.paymentFailed")); // shown to the user → extracted } // catalog: checkout.paymentFailed: "We couldn't process your payment."
Other measured skills in the registry, with their headline benchmark lift.