R18n is an tool to internationalize and localize your Rails, Sinatra or desktop Ruby application.
Why R18n?
Ruby-style Syntax
R18n uses hierarchical, not English-centric, 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 the 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 the translation key is the name of an Object method you can access it via hash index:
t[:methods] #=> "Methods"
Filters
You can add custom filters for YAML types or any translated string. Filters are cascading 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 them. For example, you can use the ‘named variables filter’ from the r18n-rails-api gem:
greeting: "Hi, %{name}"
R18n::Filters.on(:named_variables)
t.greeting(name: 'John') #=> "Hi, John"
Flexible Locales
Locales extend the Locale class. For example, English locale extends the time formatters:
l Date.now, :full #=> "30th of November, 2009"
Russian has built-in 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 anywhere, 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(user_locales, DBLoader.new)
You can also set a list of different translation locations or set extension locations which will be only used with application translation (useful for plugins).
Object Translation
You can translate any class, including ORM models (ActiveRecord, DataMapper, MongoMapper, Mongoid or others):
require 'r18n-core/translated' class Product < ActiveRecord::Base include R18n::Translated # Model has two normal properties: title_en and title_ru translations :title end # For English users product.title #=> "Anthrax" # For Russian users 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
If a particular locale is requested but missing, R18n will automatically take the next available language (according to the browser’s list of locales) and for cultures with two official languages (e.g., exUSSR) it takes the second language (e.g., if a translation isn’t available in Kazakh R18n will look for 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 an agnostic core package and plugins with out-of-box support for Sinatra, Merb and desktop applications.