hermes

Write 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.

context

English has two plural forms, so English-speaking developers write count === 1 ? "item" : "items" and ship it. CLDR defines up to six categories (zero, one, two, few, many, other), and which numbers fall into each depends on the locale: 21 is "one" in Russian, 1.5 is "one" in French but "other" in English, and Japanese has only "other". ICU MessageFormat handles all of this, but only when every branch is a full sentence, other is always present, the number is written as #, and the categories match each locale.

task

Convert these messages to ICU MessageFormat for the locales :

  1. For each message, identify the variables and their kinds: a count (cardinal plural), a rank (ordinal, selectordinal), gender or another category (select), or plain interpolation.
  2. Write the source-language message first:
  • Use # for the formatted count inside plural branches.
  • Use =0 (or any exact =N) only for wording that is genuinely special ("No messages"), never as a stand-in for a plural category.
  • Use offset:1 for patterns like "You and # others".
  • Put select outside and plural inside when both apply, and make every branch a complete sentence. Never assemble fragments around a plural.
  • Every plural, select and selectordinal has an other branch.
  • Escape a literal apostrophe as '' and literal braces with apostrophe quoting.
  1. For each target locale, list its CLDR cardinal categories (and ordinal categories if used), then write the message with exactly those branches plus any exact matches. Translations: . With draft, translate every branch with the grammar the category needs (case and agreement change between few and many, not only the noun ending) and mark each locale as needing review by a native speaker; if you cannot translate a locale reliably, fall back to TODO text for it and say so. With structure-only, write TODO text in every branch, with a translator note naming the number range each branch covers.
  2. Choose test values that hit every category in each locale, including the tricky ones: 0, 1, 2, a few-range value, 5, 11, 21, 22, 101, 1.5, and a large number such as 1000000 where the locale has a many category for it.
  3. If a runtime is available, verify categories with Intl.PluralRules (or the ICU library) and say you did. Otherwise state that the categories come from CLDR rules.
constraints
  • Never translate ICU keywords, argument names or category names.
  • Do not reduce a locale's categories to make messages shorter; missing categories fall back to other and read wrongly.
  • If a message cannot work as ICU without a copy change (for example, a count embedded in a fragment shared across messages), say so and propose the reworded source.
  • Separate what you verified from what you inferred. Mark inferences as such.
  • When you do not know, say "I don't know" once and state what would settle it.
output format

Messages

For each key: the source message, then one code block per locale, headed by the locale and its category list.

Test values

| Key | Locale | Value | Category | Expected output |

Notes

Copy changes needed, translations to review, and any category you could not confirm.

examples
example

Key inbox.unread, variable count, locales en and ru.

en (one, other):

{count, plural, =0 {You have no unread messages} one {You have # unread message} other {You have # unread messages}}

ru (one, few, many, other):

{count, plural, =0 {У вас нет непрочитанных сообщений} one {У вас # непрочитанное сообщение} few {У вас # непрочитанных сообщения} many {У вас # непрочитанных сообщений} other {У вас # непрочитанного сообщения}}

Test values for ru: 1 and 21 are one; 2 and 22 are few; 5, 11 and 100 are many; 1.5 is other.

2 required values still a placeholder; the assistant will ask for them.

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
Software engineer, Frontend engineer, Mobile engineer
risk
read-only
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, ChatGPT, claude.ai

Edit on GitHubReport a problem

use in

Hodios CLI
npx @hermes-hq/hodios install write-icu-plural-messages --target claude-code
Agent Skills
npx skills add hermes-hq/hodios-dist --skill write-icu-plural-messages -a claude-code
Add the Hodios marketplace (once)
claude plugin marketplace add hermes-hq/hodios-dist
Install the software-engineering plugin
claude plugin install hodios-software-engineering@hodios

The plugin brings every entry in this domain at once.

PromptLocalization (software)

Translate 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
PromptLocalization (software)

QA 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-strings
PromptLocalization (software)

Build 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-glossary
PromptLocalization (software)

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.

extract-ui-strings
PromptLocalization (software)

Plan 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-support
PromptLocalization (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-readiness