rigor-rails-i18n
Validates t('key.path') / I18n.t(...) / I18n.translate(...)
calls against config/locales/*.yml: missing keys (with
did-you-mean suggestions), per-locale coverage gaps, and
interpolation-variable mismatches. No Rails runtime dependency —
locale files are read through Prism and YAML.safe_load only.
It ships bundled in rigortype. Activate it under plugins::
plugins: - rigor-rails-i18nWhat it checks
Section titled “What it checks”Against a locale catalogue, every statically-resolvable call site is validated:
demo.rb:14:1: info: `t('users.welcome')` resolves in en, jaerrors_demo.rb:12:1: error: missing translation key `users.welcom` in any locale (did you mean `users.welcome`?)errors_demo.rb:16:1: error: `t('users.welcome')` expects interpolation `name`, got (none)errors_demo.rb:20:1: warning: `t('users.welcome')` does not use interpolation `extra` (known placeholders: `name`)errors_demo.rb:25:1: warning: `t('errors.messages.blank')` is missing from locale(s) ja- Key existence — a key absent from every locale is flagged,
with
DidYouMeannear-matches. - Per-locale coverage — a key present in some
configured_localesbut not others emits amissing-localewarning (suppressed when the call passesdefault:). - Interpolation variables — the leaf string’s
%{var}placeholders must match the call’s keyword arguments. Missing required placeholders are errors; extras are warnings. Reserved I18n option keys (default:/scope:/locale:/count:/raise:/ …) are excluded.
Recognised call shapes
Section titled “Recognised call shapes”t(...) (implicit self), I18n.t(...), and I18n.translate(...)
with a literal first argument. Lazy keys — t('.title') in a
controller — are expanded to <controller_scope>.<action>.<key>
from the file path and the innermost enclosing def, matching
Rails’ convention; lazy keys in non-controller files are skipped
(the scope can’t be determined statically). Calls with a
non-literal key (t(some_variable)) pass through unchecked.
Keys under the prefixes Rails and the rails-i18n gem ship
themselves (date. / time. / datetime. / number. /
errors.messages. / errors.format / support.array. /
helpers.{select,submit,label}. / i18n.transliterate. /
activerecord.errors.{messages,models}.) are not flagged as
unknown, since the framework provides them.
Configuration
Section titled “Configuration”plugins: - gem: rigor-rails-i18n config: locale_search_paths: ["config/locales"] # default configured_locales: ["en"] # defaultconfigured_locales is the set of locales the project ships;
setting it to ["en", "ja"] turns on missing-locale warnings
whenever a key resolves in one but not the other.
Limitations
Section titled “Limitations”- Literal-string keys only — a variable key passes through.
- Lazy keys outside controllers are skipped — the
controller/action scope
t('.x')depends on isn’t derivable in a model / helper / mailer. - Pluralization is recognised but not validated —
count:is treated as a reserved option; whether the locale defines:zero/:one/:otheris not checked. - Per-locale interpolation differences are merged into one
placeholder set (if
enuses%{name}andjauses%{user_name}, both are treated as required). safe_loadonly — YAML aliases / merges are accepted; custom Ruby classes in the YAML are not.
Plugin internals
Section titled “Plugin internals”The locale loader / index, the cached :locale_index producer,
the demo, and the contract surfaces this plugin exercises are in
the plugin’s README.
To write a plugin, see examples/
and the rigor-plugin-author skill.
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.