rails-i18n: Locale Data for Ruby on Rails Without Hand-Written YAML
Repository for collecting Locale data for Ruby on Rails I18n as well as other interesting, Rails related I18n stuff
At a glance
- What is it?
- The rails-i18n gem ships locale files, pluralization rules, transliteration and ordinals for roughly 130 locales, so a Rails app does not start with an empty config/locales directory. Here is how it loads, how to install it, and where it stops helping.
- Who is it for?
- Adopt rails-i18n if your Rails app needs more than English and you would rather not hand-maintain date, number and ActiveRecord error translations. Skip it if you only support one locale, or if you need translations of your own domain strings, which it does not provide.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 36 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What rails-i18n Actually Contains
Rails ships an I18n API but almost no translation data. A new application gets a config/locales directory with an en.yml stub, and every date format, plural rule, currency symbol and ActiveRecord validation message for any other language is left to the developer. Multiply that by the number of languages you support and the work becomes a translation project of its own.
rails-i18n fills that gap. The repository holds locale files under rails/locale, plus pluralization, transliteration and ordinal rules, packaged as a gem. The README lists the available locales, and the list is long: af, ar, az, be, bg, bn, bs, ca, cs, cy, csb, da, de and its regional variants, dsb, dz, el, en and its many regional variants, eo, es and its Latin American variants, et, eu, fa, fi, fr and its Canadian and Swiss variants, and on through ja, ko, pt-BR, ru, zh-CN, zh-HK, zh-TW and zh-YUE.
The intended audience is a Rails developer adding a second or third language who wants standard scaffolding rather than a blank file. It is not a translation service and it does not translate your application's own strings. The README is explicit that most locales are incomplete, typically missing activerecord.errors.messages.record_invalid and the restrict_dependent_destroy keys. A smaller set is marked complete: en, en-US, es, es-419, es-AR, es-CL, es-CO, es-CR, es-EC, es-ES, es-MX, es-NI, es-PA, es-PE, es-US, es-VE, fr, fr-CA, fr-CH, fr-FR, gd, ja, pt, pt-BR, ru and sc. That distinction is the first thing to check before picking a locale.
The gem also covers framework internals that developers rarely get right by hand. Date and time formats, number and currency formatting, and the plural rules that decide between one and other forms all live in the locale data rather than in your code. If you have ever written a German date format from memory, you know why shipping a maintained set matters. The flip side is that the data reflects the maintainers' judgement about conventions, not your product's style guide, which is why the override pattern exists.
How the Gem Loads Locale Data and Rules
The gem is split into four modules: :locale, :ordinals, :pluralization and :transliteration. By default all four load. The README says that on load the gem brings in every available locale file along with the pluralization and transliteration rules, which means a Rails boot with rails-i18n in the Gemfile pulls in far more data than most applications use.
Two configuration levers exist. config.rails_i18n.enabled_modules restricts which feature types load, and I18n.available_locales restricts which locales load. The README gives config.i18n.available_locales = ['es-CO', :de] and config.i18n.available_locales = :nl as examples, placed in config/environments/*. Combining both is the sensible default for a production app: enable only :locale and :pluralization if you do not need transliteration, and list the locales you actually ship. An application that never sets available_locales carries data for languages it will never serve, in every process.
The pluralization module matters more than it looks. Rails' pluralization is driven by rules, not by a translation string, and the README notes a set of locales with missing pluralization rules: af, csb, dsb, dz, fur, gsw-CH, lb, rm, scr, sq, sv-FI, te, tt, ug and uz. It also lists removed pluralizations for ak, am, bh, bm, bo, br, by, cy, dz, ff, ga, gd, guw, gv, ig, ii, iu, jv, kab, kde, kea, ksh, kw, lag, ln, mo, mt, my, naq, nso, root, sah, se, ses, sg, sh, shi, sma, smi, smj, smn, sms, ti, to, tzm, wa, yo and zh, with the stated reason that those rules had no corresponding locale files. If your language is in the missing-rules list, plural forms fall back to whatever Rails does by default, and you will need to supply the rule yourself.
Transliteration and ordinals are the quieter modules. Transliteration converts non-Latin scripts for URL slugs and search, and ordinals produce forms like 1st or 2nd for a given language. Both are the kind of detail that looks trivial until you ship a Japanese or Polish interface and discover that the naive implementation is wrong. Restricting enabled_modules is therefore a size decision, not a correctness one: the modules you leave on are the ones you want the gem to answer for.
Installing rails-i18n and Setting a First Locale
Installation is a Gemfile line. The gem version tracks the Rails version, so pick the constraint that matches your application. The README lists gem 'rails-i18n', '~> 8.1.0' for Rails >= 8.1.0, '~> 8.0.0' for Rails >= 8.0.0, '~> 7.0.0' for Rails >= 7.0.0, '~> 6.0' for 6.x, '~> 5.1' for 5.0.x, 5.1.x and 5.2.x, '~> 4.0' for 4.0.x and '~> 3.0' for 3.x. Rails 3.0 or higher is required for the gem; Rails 2.x needs the manual route.
gem 'rails-i18n', '~> 8.1.0' # For Rails >= 8.1.0If you would rather not touch the Gemfile, the README gives the equivalent command line. The version constraints are the same, so a Rails 7 application installs the 7.0.0 line.
gem install rails-i18n -v '~> 7.0.0' # For Rails >= 7.0.0After bundle install, set the locales you want loaded. The README places this in config/environments/*, and restricting the list keeps boot time and memory down because the gem otherwise loads every locale file it ships.
config.i18n.available_locales = ['es-CO', :de]If you want only some feature types, the README shows the module switch. Setting enabled_modules restricts the gem's loaded features to the specific types you name.
config.rails_i18n.enabled_modules = [:pluralization, :ordinals]With that in place, I18n.t and the view helper t resolve against the bundled data. A date format, for example, comes from the locale file rather than from your application, so t(:'date.formats.long', locale: :de) returns the German format defined in the gem. If a translation does not suit your application, the README's guidance is to edit it or add your own locale file, and the currency section shows the pattern: create config/locales/tr.yml and override the key you want.
tr:
number:
currency:
format:
unit: TLThat override example comes straight from the README, which explains that the Turkish Lira sign was added in Unicode 6.2 and that font support was still uneven, so the gem keeps the code CHF or TL style value in some locales and the symbol in others. Application-level overrides are the supported escape hatch for that kind of disagreement.
The Manual Installation Path, and Why You Might Prefer It
The gem is not the only option. The README documents manual installation: download the locale files you need from the rails/locale directory and move them into your application's config/locales. From that point they are ordinary YAML files in your repository, editable like any other locale file, and the README suggests editing or adding to them when a translation does not fit.
The trade-off is maintenance. A copied file does not receive upstream corrections, and the README notes that most locales are incomplete, which means upstream corrections are likely over time. The gem route gets those fixes on a version bump. The manual route gives you full control over every string and no dependency, which suits an application that has already forked the translations or that pins to a locale the gem marks as incomplete and intends to finish itself. Rails 2.3 users have no gem option at all: the README points to a separate rails-2-3 branch with Rails 2.3-compatible locale data.
There is also a middle path the README does not spell out but the repository layout supports: depend on the gem for pluralization and ordinals, and override individual keys in your own config/locales files. Rails merges locale files, so a key you define locally takes precedence over the gem's value. That keeps you on the upgrade path for the parts you do not want to own while letting you take responsibility for the strings your product depends on.
Where rails-i18n Stops Being the Right Tool
The gem provides framework-level translations. It does not provide your product's copy, and no amount of locale data will produce a German sentence for a button label you invented. Teams sometimes install it expecting a localization solution and discover they still need a translation workflow for everything the user actually reads.
Coverage is uneven, and the README says so. The available locales list is much longer than the complete locales list, and locales with missing pluralization rules are called out separately. The README also names keys that should not be included, errors.messages.model_invalid and errors.messages.required, which matters if you copy a third-party locale file and merge it in.
Loading behaviour is the other trap. Because all modules and all locale files load by default, an application that never configures available_locales carries data for languages it will never serve. That is not a correctness problem, but it is avoidable weight in every process. The Dockerfile in the repository shows the maintainers' own test path, ruby:3.2.2 with bundle install and bundle exec rake spec, which is a development concern rather than a deployment recommendation.
Finally, version coupling. The gem version must match the Rails major version, and the README's Gemfile examples run from Rails 3.x to 8.1.0. An application on an older Rails line has to pick the matching constraint or the older branch, and the README lists github: 'svenfuchs/rails-i18n' with branch rails-5-x, rails-4-x and rails-3-x for those cases. A team that upgrades Rails infrequently will feel this as a recurring chore rather than a one-time setup.
rails-i18n Compared with the i18n Gem and Front-End Libraries
The name invites confusion with the i18n gem, and the two do different jobs. The i18n gem is the backend that implements the translation API in Ruby: lookup, interpolation, pluralization hooks, fallbacks. rails-i18n is data plus Rails integration on top of it. Installing rails-i18n does not replace i18n, and removing i18n would break rails-i18n. If your question is how I18n.t resolves a key, that is the i18n gem's behaviour; if your question is what date.formats.long contains for Japanese, that is rails-i18n's data.
Front-end libraries such as Vue i18n sit in a different layer entirely. They manage translations in JavaScript, often with their own message compiler and their own plural rules. A Rails app serving JSON to a Vue front end can end up with two independent locale stores, one from rails-i18n for server-rendered views and ActiveRecord messages, one from the JavaScript library for the client. Nothing in rails-i18n synchronizes them, and the README does not describe a JSON export. Teams in that situation either duplicate the strings or generate the client bundle from the same YAML files themselves.
The practical difference from hand-rolled YAML is coverage of framework internals. ActiveRecord validation messages, date and time formats, number and currency formatting and plural rules are all things Rails expects to find in the I18n backend. rails-i18n supplies them for the locales it lists; a hand-written file usually covers the strings the developer remembered. That is the whole argument for the gem, and it is also its boundary: it answers for the framework, not for your application.
Contributing, Licence and Version Cost
The repository is MIT licensed, which in practice means you can use, modify and redistribute the locale data with the licence text. The repository carries MIT-LICENSE.txt at the top level. That is a permissive arrangement and removes the licensing question from the adoption decision for most teams; it does not remove attribution requirements, so keep the licence file if you vendor the data.
Contributing is documented in two tracks. The quick track asks for a Gist with the locale data and an issue referencing it. The full track asks for a fork, a clone, a new or edited file based on rails/locale/en.yml, saved as UTF-8, then verification before pushing. The README gives two commands for that verification.
bundle exec rake spec
bundle exec rake i18n-spec:completeness rails/locale/en.yml rails/locale/YOUR_NEW_LOCALE.ymlThe second command checks a new locale file against the English base for missing translations, which is how the completeness lists in the README are maintained. The README also mentions running the tests with Docker; the Dockerfile at the repository root builds on ruby:3.2.2, copies the repository into /gem, runs bundle install and defaults to bundle exec rake spec.
Upgrade cost is a Gemfile constraint change. The last push to the repository was on 2026-08-25, and the README documents constraints through Rails 8.1.0. Because the gem version follows the Rails version, a Rails upgrade normally means a rails-i18n constraint bump in the same commit, and any local overrides in config/locales continue to take precedence over the bundled values. The licence imposes no version-tracking obligation, so the cost is purely the constraint bump and whatever review your team gives the locale data that changed.
Working with Incomplete Locales
Most locales in the repository are incomplete, and the README names the usual gaps: activerecord.errors.messages.record_invalid and the two restrict_dependent_destroy keys, has_one and has_many. If your application relies on ActiveRecord validation error messages for a locale in that group, those specific messages will fall back or go missing until you fill them in yourself.
The completeness rake task is the tool for this. Running it against your locale file and rails/locale/en.yml reports what is absent, and the README's contribution instructions treat that check as a precondition for submitting a locale. You can run the same check against a locale you intend to use, before you commit to it, and decide whether the missing keys matter for your application.
The override pattern from the currency section applies here too. Any key you define in your own config/locales file wins over the gem's value, so filling a gap does not require forking the repository. What it does require is knowing which keys are missing, which is what the completeness task tells you. For a locale with missing pluralization rules the situation is different: that is a rule, not a string, and the README does not describe a configuration option for supplying one through the gem, so you would be working with the i18n gem's pluralization hooks directly.
Editorial conclusion
Adopt rails-i18n if your Rails app needs more than English and you would rather not hand-maintain date, number and ActiveRecord error translations. Skip it if you only support one locale, or if you need translations of your own domain strings, which it does not provide. Before committing, check whether your locale appears in the complete locales list or only the available one, and run bundle exec rake i18n-spec:completeness against the locale file you plan to use.
Frequently asked questions
What is the purpose of i18n in a Rails application?
It lets the application serve more than one language by looking translations up by locale key instead of hard-coding strings. Rails provides the API, and rails-i18n supplies the locale data, pluralization rules and formats that the API resolves against.
How do I install rails-i18n in a Rails project?
Add a version constraint to your Gemfile that matches your Rails version, such as gem 'rails-i18n', '~> 8.1.0' for Rails 8.1.0 and above, then run bundle install. Alternatively install it directly with gem install rails-i18n and the same version constraint.
How do I limit which locales rails-i18n loads?
Set config.i18n.available_locales in config/environments/*, for example config.i18n.available_locales = ['es-CO', :de]. The README notes that the gem otherwise loads all available locale files along with the pluralization and transliteration rules.
Can I turn off pluralization or transliteration in rails-i18n?
Yes. Set config.rails_i18n.enabled_modules to the modules you want, such as [:pluralization] or [:pluralization, :ordinals]. The recognized module names are :locale, :ordinals, :pluralization and :transliteration.
How do I override a translation that comes from rails-i18n?
Create your own locale file under config/locales and define the key there. The README shows this with config/locales/tr.yml overriding number.currency.format.unit, and notes you can edit or add locale files when a translation does not suit your application.
How do I check whether a locale file is complete?
Run bundle exec rake i18n-spec:completeness rails/locale/en.yml rails/locale/YOUR_NEW_LOCALE.yml, which the README gives as the check before committing a locale file. The README also lists which locales are complete and which have missing pluralization rules.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/svenfuchs-rails-i18n)