Internationalization (i18n)¶
CMDx talks to users through messages: coercion errors, validation errors, missing outputs, missing required inputs, and the default fault reason. All of that goes through CMDx::I18nProxy.
If the i18n gem is loaded, CMDx uses I18n.translate, so messages follow whatever I18n.locale is set to—just like the rest of your app.
If i18n isn’t there, CMDx loads YAML for config.default_locale and does simple %{key} interpolation itself.
Out of the box, CMDx ships English only (en). Want dozens more languages? Add cmdx-i18n, or drop in your own YAML (see Custom locale paths).
Usage¶
Flip the locale and built-in messages follow:
class ProcessQuote < CMDx::Task
required :price, coerce: :float
def work
# ...
end
end
I18n.with_locale(:fr) do
result = ProcessQuote.execute(price: "invalid")
result.failed? #=> true
result.errors[:price] #=> ["impossible de contraindre en float"]
result.reason #=> "price impossible de contraindre en float"
end
Note
Failures pile up on task.errors (CMDx::Errors). result.reason is basically the friendly string built from those errors (Errors#full_messages, joined with ". ").
Translation Keys¶
Everything lives under cmdx.*. Override a key in your locale file to change wording app-wide:
| Key | Used by |
|---|---|
cmdx.attributes.required |
Missing required input |
cmdx.coercions.into_a / into_an |
Single-type coercion failure (%{type}) |
cmdx.coercions.into_any |
Multi-type coercion failure (%{types}) |
cmdx.outputs.missing |
Declared output not set on context |
cmdx.reasons.unspecified |
Fallback fault reason |
cmdx.types.<name> |
Human-readable coercion type names (array, big_decimal, boolean, complex, date, date_time, float, hash, integer, rational, string, symbol, time) |
cmdx.validators.absence / presence / format |
Standalone validator messages |
cmdx.validators.inclusion.{of,within} |
Inclusion validator messages |
cmdx.validators.exclusion.{of,within} |
Exclusion validator messages |
cmdx.validators.length.{is,is_not,min,max,gt,lt,within,not_within,nil_value} |
Length validator messages |
cmdx.validators.numeric.{is,is_not,min,max,gt,lt,within,not_within,nil_value} |
Numeric validator messages |
Tip
Tweaking one field? Use :message or :<rule>_message on the input (see Validations). Overriding cmdx.* changes the text everywhere that key is used.
Configuration¶
Rails¶
The CMDx railtie adds its locale files to I18n.load_path on boot—but only for locales you list in config.i18n.available_locales. So you don’t load YAML for languages you never ship.
Default locale (plain Ruby)¶
No i18n gem? (Scripts, CLIs, tiny workers.) Set default_locale and CMDx reads that locale’s YAML directly.
In this mode there’s one active locale—no I18n.with_locale equivalent. If a key is missing, you’ll see "Translation missing: <key>". If the locale itself can’t be resolved to a YAML file on the load path, CMDx raises CMDx::UnknownLocaleError (a CMDx::Error) the first time it tries to translate. More detail: Configuration – default locale.
Custom locale paths¶
Point CMDx at extra folders of <locale>.yml files with I18nProxy.register. Later registrations win on merge, so you can override a few keys without copying entire files.
# lib/locales/en.yml
en:
cmdx:
attributes:
required: "is mandatory"
CMDx::I18nProxy.register(File.expand_path("lib/locales", __dir__))
Note
register only affects the no-i18n-gem path. When i18n is loaded, CMDx delegates to I18n.translate—add your paths to I18n.load_path instead.
Available locales¶
The cmdx-i18n gem bundles community translations for 85+ locales (Arabic, Chinese, French, German, Japanese, Portuguese, Spanish, and more). Add it to your Gemfile and those locales show up wherever CMDx calls I18n.translate. The gem’s README lists the exact set.