Writing i18n
Skill chrisrackstallion/pitchd-rails-cursor-plugin/skills/writing-i18n
Organize Rails I18n — YAML structure, lazy lookup in views, absolute keys in helpers and controllers, interpolation and pluralization, datetime/number formats, and Active Record error messages. DHH/37signals style: boring keys, framework-first, no string concatenation in templates. Use when adding or changing locales, extracting user-facing copy from ERB, flash messages, or validation messages; not for translation vendor tooling or SPA i18n-js. Triggers: locales, config/locales YAML, t(), I18n.t, missing translations, flash copy, human_attribute_name.From its SKILL.md
npx -y skills add chrisrackstallion/pitchd-rails-cursor-plugin --skill writing-i18nAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.6 KB, as published. Nobody here has run it
Writing I18n
<objective> Treat locale files as part of the application: namespaced keys, static copy in YAML, dynamic values via interpolation. Locale files always mirror the application's structure so key resolution (lazy lookup, `default_i18n_subject`, `human_attribute_name`) works by convention. Views use lazy lookup where it reads naturally; helpers and shared partials use explicit keys. All user-facing error messages live in I18n and read as human language — rename schema-shaped attributes (join-table foreign keys) to their real-world names. All user-visible dates and times are formatted via I18n (`l()` with declared formats). Rails handles pluralization and time formats — do not hand-roll them in templates. Keep I18n boring and omakase — no parallel translation architecture. </objective>Process
1. Determine What You're Building
| Task | Action |
|---|---|
| New feature copy | Read references/patterns.md § Key structure; add keys under a feature namespace |
| Strings in a view | Prefer t(".key") lazy lookup; read § Lazy vs absolute |
| Strings in a helper / shared partial | Absolute key — t("feature.button.save") |
| Flash / controller messages | Absolute keys; keep messages out of fat controllers where possible |
| Validation / attribute labels | activerecord tree — § Active Record |
| Mailer subject / body phrases | mailers.* + § Mailers in patterns; mailer skill § subjects |
| Pluralization / dates / numbers | § Pluralization and datetime; use l(), number_to_* |
2. Add or Update YAML
Place files under config/locales/ — e.g. en.yml, articles.en.yml. Keep default locale complete for keys you introduce; add secondary locales when the app actually ships them.
3. Replace String Soup
Swap "Save", "Cancel", concatenated greetings, etc., for t() calls and keys. Use %{name} — never string math for grammar.
4. Verify
In development, config.i18n.raise_on_missing_translations = true (if enabled) catches missing keys. Run the screen or mailer preview that uses the new copy.
Verification
- User-facing static strings in views/helpers/controllers use
t()/I18n.t, not raw literals (domain data excepted) - Lazy keys match the template path; shared partials use absolute keys
- Interpolation uses YAML placeholders, not Ruby concatenation
- Pluralization uses
count:and properone/other(and locale-specific keys when required) - No unbounded dynamic key paths from user input
-
activerecordattributes/errors follow Rails structure for forms - Locale file nesting mirrors the app structure (view paths, mailer paths) so keys resolve by convention
- All user-facing error messages come from I18n and read as human language — join-table / FK attributes renamed to real-world names via
activerecord.attributes - All user-visible dates and times go through
l()with formats declared in locale YAML — nostrftimein views or helpers