FastGettext / Rails integration.
Translate via FastGettext, use any other I18n backend as extension/fallback.
Rails does: I18n.t('syntax.with.lots.of.dots')
with nested yml files
We do: _('Just translate my damn text!')
with simple, flat mo/po/yml files or directly from db
To use I18n calls add a syntax.with.lots.of.dots
translation.
See it working in the example application.
rails plugin install git://github.com/grosser/gettext_i18n_rails.git
# Gemfile
gem 'fast_gettext', '>=0.4.8'
# Gemfile
gem 'gettext_i18n_rails'
Add gettext
if you want to find translations or build .mo files
Add ruby_parser
if you want to find translations inside haml/slim files
# Gemfile
gem 'gettext', '>=1.9.3', :require => false, :group => :development
gem 'ruby_parser', :require => false, :group => :development
script/plugin install git://github.com/grosser/gettext_i18n_rails.git
sudo gem install fast_gettext
# config/environment.rb
config.gem "fast_gettext", :version => '>=0.4.8'
gem install gettext_i18n_rails
# config/environment.rb
config.gem 'gettext_i18n_rails'
#Rakefile
begin
require "gettext_i18n_rails/tasks"
rescue LoadError
puts "gettext_i18n_rails is not installed, you probably should run 'rake gems:install' or 'bundle install'."
end
If you want to find translations or build .mo files # config/environments/development.rb config.gem "gettext", :version => '>=1.9.3', :lib => false
Copy default locales with dates/sentence-connectors/AR-errors you want from e.g. rails i18n into 'config/locales'
To initialize:
# config/initializers/fast_gettext.rb
FastGettext.add_text_domain 'app', :path => 'locale', :type => :po
FastGettext.default_available_locales = ['en','de'] #all you want to allow
FastGettext.default_text_domain = 'app'
And in your application:
# app/controllers/application_controller.rb
class ApplicationController < ...
before_filter :set_gettext_locale
Performance is almost the same for all backends since translations are cached after first use.
FastGettext.add_text_domain 'app', :path => 'locale', :type => :po
- use some _('translations')
- run
rake gettext:find
, to let GetText find all translations used - (optional) run
rake gettext:store_model_attributes
, to parse the database for columns that can be translated - if this is your first translation:
cp locale/app.pot locale/de/app.po
for every locale you want to use - translate messages in 'locale/de/app.po' (leave msgstr blank and msgstr == msgid)
New translations will be marked "fuzzy", search for this and remove it, so that they will be used. Obsolete translations are marked with ~#, they usually can be removed since they are no longer needed
Dynamic translations like _("x"+"u")
cannot be fond. You have 4 options:
- add
N_('xu')
somewhere else in the code, so the parser sees it - add
N_('xu')
in a totally separate file likelocale/unfound_translations.rb
, so the parser sees it - use the gettext_test_log rails plugin to find all translations that where used while testing
- add a Logger to a translation Chain, so every unfound translations is logged (example)
FastGettext.add_text_domain 'app', :path => 'locale'
- follow Option A
- run
rake gettext:pack
to write binary GetText .mo files
Most scalable method, all translators can work simultaneously and online.
Easiest to use with the translation database Rails engine.
Translations can be edited under /translation_keys
FastGettext::TranslationRepository::Db.require_models
FastGettext.add_text_domain 'app', :type => :db, :model => TranslationKey
I18n.locale <==> FastGettext.locale.to_sym
I18n.locale = :de <==> FastGettext.locale = 'de'
Any call to I18n that matches a gettext key will be translated through FastGettext.
Car|Model means Model in namespace Car. You do not have to translate this into english "Model", if you use the namespace-aware translation s_('Car|Model') == 'Model' #when no translation was found
If you trust your translators and all your usages of % on translations:
# config/environment.rb
GettextI18nRails.translations_are_html_safe = true
String % vs html_safe is buggy (can be used for XSS on 1.8 and is always non-safe in 1.9)
My recommended fix is: require 'gettext_i18n_rails/string_interpolate_fix'
- safe stays safe (escape added strings)
- unsafe stays unsafe (do not escape added strings)
ActiveRecord error messages are translated through Rails::I18n, but
model names and model attributes are translated through FastGettext.
Therefore a validation error on a BigCar's wheels_size needs _('big car')
and _('BigCar|Wheels size')
to display localized.
The model/attribute translations can be found through rake gettext:store_model_attributes
,
(which ignores some commonly untranslated columns like id,type,xxx_count,...).
Error messages can be translated through FastGettext, if the ':message' is a translation-id or the matching Rails I18n key is translated.
####Option A: Define a translation for "I need my rating!" and use it as message. validates_inclusion_of :rating, :in=>1..5, :message=>N_('I need my rating!')
####Option B:
validates_inclusion_of :rating, :in=>1..5
Make a translation for the I18n key: activerecord.errors.models.rating.attributes.rating.inclusion
####Option C: Add a translation to each config/locales/*.yml files en: activerecord: errors: models: rating: attributes: rating: inclusion: " -- please choose!" The rails I18n guide can help with Option B and C.
FastGettext supports pluralization n_('Apple','Apples',3) == 'Apples'
Abnormal plurals like e.g. Polish that has 4 different can also be addressed, see FastGettext Readme
When you run
rake gettext:find
by default the following files are going to be scanned for translations: {app,lib,config,locale}/**/*.{rb,erb,haml,slim}. If you want to specify a different list, you can redefine files_to_translate in the gettext namespace in a file like lib/tasks/gettext.rake:
namespace :gettext do
def files_to_translate
Dir.glob("{app,lib,config,locale}/**/*.{rb,erb,haml,slim,rhtml}")
end
end
If want to use your .PO files on client side javascript you should have a look at the GettextI18nRailsJs extension.
- ruby gettext extractor from retoo
- Paul McMahon
- Duncan Mac-Vicar P
- Ramihajamalala Hery
- J. Pablo Fernández
- Anh Hai Trinh
- ed0h
- Nikos Dimitrakopoulos
- Ben Tucker
- Kamil Śliwak
- Paul McMahon
- Rainux Luo
- Lucas Hills
- Ladislav Slezák
- Greg Weber
- Sean Kirby
- Julien Letessier
- Seb Bacon
- Ramón Cahenzli
- rustygeldmacher
- Jeroen Knoops
- Ivan Necas
- Andrey Chernih
- Imre Farkas
- Trong Tran
- Dmitri Dolguikh
Michael Grosser
grosser.michael@gmail.com
License: MIT