Extract hard-coded UI strings
Finds hard-coded user-facing strings and moves them into an i18n catalog with meaningful keys and translator comments, without changing behaviour. Use when preparing an app for translation.
String extraction looks mechanical, but most localisation bugs are created here. Concatenated fragments ("You have " + n + " items") cannot be translated, because word order and plurals differ by language. Keys named after the English text break as soon as the copy changes. The same English word in two contexts ("Open" the verb, "Open" the status) shares one key and gets one wrong translation. Log messages and analytics event names get extracted and break dashboards. Translators get a bare string with no idea where it appears or how long it may be.
Extract user-facing strings from .
i18n library: (if empty, detect it from dependencies and existing catalogs. If none exists, stop and recommend one suited to the stack in one paragraph). Key style: .
- Study the existing setup: catalog location and format, how strings are looked up, the key naming already in use, the interpolation, plural and rich-text APIs, and where translator comments go.
- Extract only text a user sees or hears: visible text,
aria-label,alt,titleandplaceholderattributes, validation and error messages shown to users, notifications, page titles and email or push templates. - Do not extract: log and debug messages, exception messages that never reach the UI, analytics event names, CSS classes, test ids, route paths, enum values, API field names, or developer-only text. When in doubt, list the string under Needs a decision.
- Convert, never copy, these patterns:
- Concatenation and template literals become one message with named placeholders, in the library's own interpolation syntax.
- Count-dependent text becomes the library's plural form (ICU
pluralor the platform plural resource), nevern === 1 ? ... : .... - Text with inline markup or links uses the library's rich-text or component interpolation instead of being split into pieces.
- Dates, numbers and currency inside strings become placeholders formatted with the locale-aware formatter.
- Name keys by feature, then screen or component, then purpose (
checkout.payment.submitButton), never by the English text. Give identical English text in different contexts separate keys. - Add a translator comment to every new entry: where it appears, what each placeholder holds with an example value, and a maximum length if the space is constrained.
- Behaviour must not change. Default-locale output must be identical to before, character for character, including whitespace and punctuation. Run the build, type check and tests.
- Do not translate anything; add only the source-language catalog entries.
- Do not reorganise or rename existing keys.
- Keep each file's change minimal: the lookup call plus any import the library needs.
- Do only what was asked. If you notice something else worth changing, mention it in one line at the end instead of changing it.
- Keep the change as small as it can be while still being correct.
- Before saying the work is done, run the check that proves it (tests, build, type check or the command the user gave) and report the real result.
- If you could not run a check, say so plainly and say which one.
Summary
Files touched, strings extracted, strings skipped.
Catalog additions
The new entries in the catalog's own format, with their comments.
Source changes
A unified diff.
Skipped
| String | File:line | Reason |
Needs a decision
Strings you could not classify, and messages that need product copy changes to translate well.
Verification
Commands run and their actual results.
1 required value still a placeholder; the assistant will ask for it.
details
- kind
- Prompt: a task you run by name to get one finished thing back
- domain
- Software engineering
- category
- Localization (software)
- level
- Intermediate
- made for
- Frontend engineer, Mobile engineer, Software engineer
- needs
- repo-read, file-write, shell
- risk
- runs-commands
- version
- v1.0.0 · incubating
- reviewed
- 2026-10-02
- works in
- Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Antigravity, OpenCode, Windsurf, Zed, Continue, AGENTS.md
use in
npx @hermes-hq/hodios install extract-ui-strings --target claude-codenpx skills add hermes-hq/hodios-dist --skill extract-ui-strings -a claude-codeclaude plugin marketplace add hermes-hq/hodios-distclaude plugin install hodios-software-engineering@hodiosThe plugin brings every entry in this domain at once.
pairs well with
All of Localization (software)Review code for internationalization bugs
Reviews code for internationalization bugs such as concatenated strings, hard-coded date, number and currency formats, naive plurals, text expansion and RTL breakage. Use before adding new locales.
review-i18n-readinessWrite ICU plural and select messages
Converts messages with counts, gender or choices into correct ICU MessageFormat for each target locale's plural categories, with test values. Use when strings depend on a number or gender.
write-icu-plural-messagesBuild a localization glossary
Builds a product term base from UI strings, with definitions, do-not-translate terms and proposed translations per locale, so localization stays consistent. Use before the first translation round.
build-localization-glossaryPlan and implement right-to-left support
Plans and implements right-to-left layout support (logical properties, mirroring rules, bidi text, icons) for a web or mobile UI. Use when adding Arabic, Hebrew, Persian or Urdu.
plan-rtl-supportQA a translated string catalog
QA-checks a translated catalog against its source for placeholder mismatches, broken syntax, truncation risk, terminology drift and untranslated strings. Use before merging translations.
review-translated-stringsTranslate a software string catalog
Translates a software string file (JSON, PO, XLIFF, ARB, Android or Apple strings) keeping keys, placeholders, plurals and length limits intact. Use when localizing an app's UI text.
translate-string-catalog