R18n is a tool to internationalize and localize your Rails, Sinatra or desktop Ruby application.
Why R18n?
Ruby-style Syntax
R18n uses hierarchical not English-centrist YAML format for translations by default:
user:
edit: Edit user
name: User name is %1
count: !!pl
1: There is 1 user
n: There are %1 users
To access translation you can call methods with same names:
t.user.edit #=> "Edit user" t.user.name('John') #=> "User name is John" t.user.count(5) #=> "There are 5 users" t.not.exists | 'default' #=> "default" t.not.exists.translated? #=> false
If translation key has name of Object method you can use another way:
t[:methods] #=> "Methods"
Filters
You can add custom filters for some YAML type or any translated strings. Filters are cascade and can communicate with each other.
R18n already has filters for HTML escaping, lambdas, Textile and Markdown:
hi: !!markdown **Hi**, people! greater: !!escape 1 < 2 is true t.hi #=> "<p><strong>Hi</strong>, people!</p>" t.greater #=> "1 < 2 is true"
Flexibility
Translation variables and pluralization (“1 comment”, “5 comments”) are filters too. So you can extend or replace it. For example, you can use named variables filter from r18n-rails-api gem:
greeting: "Hi, {{name}}"
R18n::Filters.on(:named_variables)
t.greeting(name: 'John') #=> "Hi, John"
Flexible Locales
Locale can extend Locale class, so locales are very flexible. For example, English locale extend time formatters:
l Date.now, :full #=> "30th of November, 2009"
Or Russian has built-in different pluralization without any lambdas in YAML:
t.user.count(1) #=> "1 пользователь" t.user.count(2) #=> "2 пользователя" t.user.count(5) #=> "5 пользователей"
Loaders
R18n can load translations from any places, not just from YAML files. You just need to create loader object with 2 methods: available and load:
class DBLoader
def available
Translation.find(:all).map(&:locale)
end
def load(locale)
Translation.find(locale).to_hash
end
end
R18n.set R18n::I18n.new(user_locales, DBLoader.new)
You can also set a list of different translation places or set extension places, which will be used only with application translation (useful for plugins).
Object Translation
You can translate any class, including ORM models:
require 'r18n-core/translated' class Product < ActiveRecord::Base include R18n::Translated # Model has two usual property: title_en and title_ru translations :title end # For English user product.title #=> "Anthrax" # For Russian user product.title #=> "Сибирская язва"
Localization
R18n can localize numbers and time:
l -5000 #=> "−5,000" l Time.now #=> "30/11/2009 14:36" l Time.now, :full #=> "30th of November, 2009 14:37" l Time.now - 60, :human #=> "1 minute ago"
Several User Languages
Lack of translation in user language isn’t exception for R18n (because translation to not primary language done by enthusiasts, it can be out of date). R18n just automatically take next user language (browser send a list of locales) and for cultures with two officially languages (e.g., exUSSR) it take second language (e.g., if translation isn’t available in Kazakh R18n will see in Russian):
i18n = R18n::I18n.new(['kk', 'de'], 'dir/with/translations') i18n.locales #=> [Locale kk (Қазақша), Locale de (Deutsch), # Locale ru (Русский), Locale en (English)] i18n.kazakh #=> "Қазақша", main user language i18n.deutsch #=> "Deutsch", not in Kazakh, use next user locale i18n.russian #=> "Русский", not in kk and de, use Kazakh sublocale i18n.english #=> "English", not in any user locales, use default
Agnostic
R18n has a agnostic core package and plugins with out-of-box support for Sinatra, Merb and desktop applications.