Minimalistic i18n library for Ruby
MiniI18n
is a simple, flexible, and fast Ruby Internationalization library. It supports localization, interpolation, pluralization, fallbacks, nested keys and more, with a minimal footprint and straightforward API (inspired by the well-known I18n gem).
Translations should be stored in YAML
or JSON
files and they will be loaded in an in-memory Hash
.
en:
hello: 'Hello'
es:
hello: 'Hola'
>> T(:hello)
=> "Hello"
>> T(:hello, locale: :es)
=> "Hola"
Add this line to your application's Gemfile:
gem 'mini_i18n'
And then execute:
bundle install
Or install it yourself as:
gem install mini_i18n
Configure your environment using the configure
method:
MiniI18n.configure do |config|
# Path to your translation files.
config.load_translations(__dir__ + '/translations/*')
# Default locale.
config.default_locale = :pt
# Available locales in your application.
config.available_locales = [:en, :es, :fr, :pt]
# If given key is empty, defaults to the default_locale.
config.fallbacks = true
# Custom separator for nested keys.
config.separator = '/'
# Custom pluralization rules, by locale.
config.pluralization_rules = {
es: -> (n) { n == 0 ? 'zero' : 'other' },
fr: -> (n) { ... }
}
end
>> T(:hello)
=> "Hello"
>> T(:hello, locale: :fr)
=> "Bonjour"
>> MiniI18n.locale = :es
>> T(:hello)
=> "Hola"
>> T(:non_existent_key)
=> nil
>> T([:hello, :bye])
=> ["Hello", "Bye"]
>> T('validations.empty')
=> "Can't be empty!"
>> L(Date.new(2025, 8, 16), format: :short)
=> "16 Aug, 18"
>> L(1000.25)
=> "1,000.25"
- Use
T()
for translations. - Use
L()
for localization (dates, times, numbers). Read more details in this section.
You can also use the long form methods:
MiniI18n.t()
orMiniI18n.translate()
MiniI18n.l()
orMiniI18n.localize()
locale
>> T(:hello, locale: :es)
=> "Hola"
>> T(:hello, locale: [:en, :fr, :es])
=> ["Hello", "Bonjour", "Hola"]
scope
>> T('views.welcome')
=> "Welcome"
>> T('welcome', scope: 'views')
=> "Welcome"
default
>> T(:non_existent_key, default: 'this is a default value')
=> "this is a default value"
count
>> T('notifications', count: 0)
=> "no unread notifications"
Read more details in the Pluralization section.
Use custom separators (default is .
) to access nested keys.
en:
validations:
empty: "Can't be empty!"
T('validations.empty')
MiniI18n.separator = '/'
T('validations/empty')
en:
hello_with_name: "Hello %{name}!"
>> T(:hello_with_name, name: 'John Doe')
=> "Hello John Doe!"
Define plurals (default keys: zero
, one
, other
):
en:
notifications:
zero: 'good job! no new notifications'
one: '1 unread notification'
other: '%{count} unread notifications'
>> T('notifications', count: 0)
=> "good job! no new notifications"
>> T('notifications', count: 1)
=> "1 unread notification"
>> T('notifications', count: 5)
=> "5 unread notifications"
You are also able to customize how plurals are handled in each locale, by defining custom pluralization rules. Example:
MiniI18n.pluralization_rules = {
es: -> (n) {
if n == 0
'zero'
elsif (1..3).include?(n)
'few'
elsif (4..10).include?(n)
'many'
else
'other'
end
}
}
Then, define those keys in your translation files:
es:
notifications:
zero: 'no tienes nuevas notificaciones'
few: 'tienes algunas notificaciones pendientes ...'
many: 'tienes %{count} notificaciones!'
other: 'alerta!! %{count} notificaciones!'
>> T('notifications', count: 0)
=> "no tienes nuevas notificaciones"
>> T('notifications', count: 2)
=> "tienes algunas notificaciones pendientes ..."
>> T('notifications', count: 5)
=> "tienes 5 notificaciones!"
>> T('notifications', count: 20)
=> "alerta!! 20 notificaciones!"
Use L()
to localize dates, times, and numbers. Don't forget you can also use MiniI18n.l()
or MiniI18n.localize()
.
The gem provides built-in localization for some languages:
:en
- English:es
- Spanish:fr
- French:de
- German:pt
- Portuguese:it
- Italian:nl
- Dutch:zh
- Chinese:ja
- Japanese
These defaults include proper date/time formats, day and month names, and number formatting that follows each language's conventions. You can check out a full example of all supported keys in this folder.
It uses strftime
under the hood. You can customize the defaults using the following format:
en:
date:
formats:
default: "%A %d, %b %Y"
short: "%d %B, %y"
>> L(Date.new(2018, 8, 15))
=> "Wednesday 15, Aug 2018"
>> L(Date.new(2018, 8, 15), format: :short)
=> "15 August, 18"
To localize your numbers, you can provide the following keys:
en:
number:
format:
delimiter: ','
separator: '.'
as:
currency: '%{number} $'
>> L(1000.25)
=> "1,000.25"
>> L(1000, as: :currency)
=> "1,000 $"
>> L(1000, as: :currency, locale: :es)
=> "1.000 β¬"
TIP π‘ By using the :as
option you can build custom full sentences with formatted numbers, like:
en:
number:
as:
final_price: 'Final price: %{number} $'
percentage: '%{number}%'
>> L(1000, as: :final_price)
=> "Final price: 1,000 $"
>> L(70.5, as: :percentage)
=> "70.5%"
Feedback, bug reports, ideas, and enhancements are welcome!
To contribute, fork the repo, make your changes, and open a pull request. Please add specs for any behavior changes and run the test suite:
bundle exec rspec
Copyright (c) Marc Anguera. MiniI18n
is released under the MIT License.