Rails I18n revs up: Globalize2 preview released!
posted: September 19th, 2008 · by: Sven
When it comes to selecting a fullfledged Internationalization solutions for a Ruby on Rails application Globalize has always been amongst the first choices. Shipping with “batteries included”, solid support for Model translations and everything stored to the database it was an obvious pick in many project environments.
On the other hand Globalize had some problems like the fact that it actually limited the set of ActiveRecord features one could use for translated models, its original choice to use default strings as keys and the mere size of its shipped data – something that sparked the development of several other Rails I18n solutions announcing themselves as way more lightweight and down to the basics.
Now with the introduction of the new I18n API to Ruby on Rails (which will be released with Rails 2.2 pretty soon) this landscape has changed. Future solutions will comply with and build on this API and therefor can be made much more modular, exchangeable and lightweight.
We’re happy to announce Globalize2 as the first fullfledged I18n solution for Ruby on Rails compatible with the new I18n API.
Please note: the following explanations assume that you’re familiar with the new I18n API in Rails and might leave some unanswered questions otherwise :-). Also note that this is a preview release targeted at Rails I18n developers. We’ll do at least one more release and provide more complete documentation about how Globalize2 can be used by end users then.
Globalize2 preview
The first preview release of Globalize2 includes the following features and tools. Most of them can be used independent of each other so you can pick whatever tools you need and combine them with other libraries or plugins.
- Model translations – transparently translate ActiveRecord data
- Static backend – swap the Simple backend for this more powerful backend, enabling custom pluralization logic, locale fallbacks and translation value objects
- Locale LoadPath – easily load translation data from standard locations enforcing conventions that suite your needs
- Locale Fallbacks – make sure your translation lookups fall back transparently through a path of alternative locales that make sense for any given locale in your application
- Translation value objects – access useful meta data information on the translations returned from your backend and/or translated models
Also, we’ve put together a small and simple demo application for demonstrating Globalize2’s feature set. You can find globalize2-demo on GitHub. Instructions for installation are included in the readme at the bottom of that page.
The implementation of Globalize2 has been sponsored by the company BESTGroup consulting and software, Berlin.
Installation
To install Globalize2 with its default setup just use:
script/plugin install -r 'tag 0.1.0_PR1' git://github.com/joshmh/globalize2.git
This will:
- activate model translations
- set I18n.load_path to an instance of Globalize::LoadPath
- set I18n.backend to an instance of Globalize::Backend::Static
Configuration
You might want to add additional configuration to an initializer, e.g. config/initializers/globalize.rb
Model translations
Model translations (or content translations) allow you to translate your models’ attribute values. E.g.
class Post < ActiveRecord::Base
translates :title, :text
end
Allows you to translate values for the attributes :title and :text per locale:
I18n.locale = :en
post.title # Globalize2 rocks!
I18n.locale = :he
post.title # ?????????2 ????!
In order to make this work you currently need to take care of creating the appropriate database migrations manually. Globalize2 will provide a handy helper method for doing this in future.
The migration for the above Post model could look like this:
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.timestamps
end
create_table :post_translations do |t|
t.string :locale
t.references :post
t.string :title
t.text :text
t.timestamps
end
end
def self.down
drop_table :posts
drop_table :post_translations
end
end
Globalize::Backend::Static
Globalize2 ships with a Static backend that builds on the Simple backend from the I18n library (which is shipped with Rails) and adds the following features:
- It uses locale fallbacks when looking up translation data.
- It returns an instance of Globalize::Translation::Static instead of a plain Ruby String as a translation.
- It allows to hook in custom pluralization logic as lambdas.
Custom pluralization logic
The Simple backend has its pluralization algorithm baked in hardcoded. This algorithm is only suitable for English and other languages that have the same pluralization rules. It is not suitable for, e.g., Czech though.
To add custom pluralization logic to Globalize’ Static backend you can do something like this:
@backend.add_pluralizer :cz, lambda{|c|
c == 1 ? :one : (2..4).include?(c) ? :few : :other
}
Locale Fallbacks
Globalize2 ships with a Locale fallback tool which extends the I18n module to hold a fallbacks instance which is set to an instance of Globalize::Locale::Fallbacks by default but can be swapped with a different implementation.
Globalize2 fallbacks will compute a number of other locales for a given locale. For example:
I18n.fallbacks[:"es-MX"] # => [:"es-MX", :es, :"en-US", :en]
Globalize2 fallbacks always fall back to
- all parents of a given locale (e.g. :es for :”es-MX”),
- then to the fallbacks’ default locales and all of their parents and
- finally to the :root locale.
The default locales are set to [:”en-US”] by default but can be set to something else. The root locale is a concept borrowed from CLDR and makes sense for storing common locale data which works as a last default fallback (e.g. “ltr” for bidi directions).
One can additionally add any number of additional fallback locales manually. These will be added before the default locales to the fallback chain. For example:
fb = I18n.fallbacks
fb.map :ca => :"es-ES"
fb[:ca] # => [:ca, :"es-ES", :es, :"en-US", :en]
fb.map :"ar-PS" => :"he-IL"
fb[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en]
fb[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en]
fb.map :sms => [:"se-FI", :"fi-FI"]
fb[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en]
Globalize::LoadPath
Globalize2 replaces the plain Ruby array that is set to I18n.load_path by default through an instance of Globalize::LoadPath.
This object can be populated with both paths to files and directories. If a path to a directory is added to it it will look up all locale data files present in that directory enforcing the following convention:
I18n.load_path << "#{RAILS_ROOT}/lib/locales"
# will load all the following files if present:
lib/locales/all.yml
lib/locales/fr.yml
lib/locales/fr/*.yaml
lib/locales/ru.yml
lib/locales/ru/*.yaml
...
One can also specify which locales are used. By default this is set to “*” meaning that files for all locales are added. To define that only files for the locale :es are added one can specify:
I18n.load_path.locales = [:es]
One can also specify which file extensions are used. By default this is set to [“rb”, “yml”] so plain Ruby and YAML files are added if found. To define that only *.sql files are added one can specify:
I18n.load_path.extensions = ['sql']
Note that Globalize::LoadPath “expands” a directory to its contained file paths immediately when you add it to the load_path. Thus, if you change the locales or extensions settings in the middle of your application the change won’t be applied to already added file paths.
Globalize::Translation classes
Globalize2’s Static backend as well as Globalize2 model translations return instances of Globalize::Translation classes (instead of plain Ruby Strings). These are simple and lightweight value objects that carry some additional meta data about the translation and how it was looked up.
Model translations return instances of Globalize::Translation::Attribute, the Static backend returns instances of Globalize::Translation::Static.
For example:
I18n.locale = :de
# Translation::Attribute
title = Post.first.title # assuming that no translation can be found:
title.locale # => :en
title.requested_locale # => :de
title.fallback? # => true
# Translation::Static
rails = I18n.t :rails # assuming that no translation can be found:
rails.locale # => :en
rails.requested_locale # => :de
rails.fallback? # => true
rails.options # returns the options passed to #t
rails.plural_key # returns the plural_key (e.g. :one, :other)
rails.original # returns the original translation with no values
# interpolated to it (e.g. "Hi {{name}}!")
Other notes
Please note that the Globalize2 Static backend (just like the Simple backend) does not support reloading translation data.
shuoling said September 19th, 2008 at 05:31 PM ¶
Look forward it, hope …… .
Pierre said September 19th, 2008 at 07:15 PM ¶
Looks great ! Thanks
Saimon Moore said September 22nd, 2008 at 09:35 AM ¶
Way to go guys….
Looking forward to getting stuck in when I can.
Nick said September 23rd, 2008 at 10:36 AM ¶
Nice work!
Does Globalize2 take away the need to use the Localized Dates plugin?
Damu said October 2nd, 2008 at 05:26 AM ¶
Great plugin!
I’m trying to use it. I have:
class Property < ActiveRecord::Base translates :title, :description end
When I save a new record, the title and description are saved ok in the translation table but when I do @property.title or @property.description in the record saved, I get a empty string. What am I doing wrong? Thanks!
Tex said October 5th, 2008 at 02:03 AM ¶
Hi, great presentation.
I’ve just downloaded git demo and installed, it works !!!
But, a moment: I cannot handle named_scope in globalize2.
Example:
namedscope :postswithout_text, :conditions => “body is null”
Clearly the above statement cannot works because body is not into posts table but it’s into posttranslations table and I cannot put :include => :posttranslations because I’ve not the model class.
Is there any simple solution for named_scope support into globalize 2 ?
Dmitri Zhuchkov said October 11th, 2008 at 03:16 PM ¶
Globalize2 expects that all translations are strings:
http://github.com/joshmh/globalize2/tree/master/lib/globalize/translation.rb#L5
However ActionView DateHelpers use arrays for translating months, day names, etc.
http://github.com/clemens/i18ndemoapp/tree/master/config/locales/en-US.yml
When Globalize2 hooks the translation backend and gets the Array from YAML then it raise the TypeError “can’t convert Array into String”.
Ned Schwartz said October 24th, 2008 at 06:45 PM ¶
Hi, is there a way to easily get another language while in a particular language context?
I would like to show multiple languages side by side.
Thanks!
Swami Atma said November 29th, 2008 at 05:50 PM ¶
Hi Sven,
Thanks for all your work on rails, i18n, and globalize2.
What if I want to use this type of url (http://localhost:3000/de/posts/new) instead of this one (http://localhost:3000/posts/new?locale=de)?
Is is possible? How do I go about it?
erwin said January 7th, 2009 at 03:59 PM ¶
@damu
got the same problem, after creating a project record, the locale description is to stored, but cannot get it back reading project.description
I believe it”s a I18n locale setup problem… locale stored and fetch are not the same ..
INSERT INTO
project_translations(created_at,project_id,updated_at,locale,description) VALUES(‘2009-01-07 14:43:51’, 4, ‘2009-01-07 14:43:51’, ‘— :fr\n’, ‘Globalize mortel!’)stored : — :fr\n
SELECT * FROM
project_translationsWHERE (project_translations.project_id = 4 AND (project_translations.localeIN (‘fr’,’root’)))fetched : IN ( ‘fr’,’root’ )
Tomash said January 12th, 2009 at 02:57 PM ¶
This is a message I sent joshmh on github, didn’t get a reply - maybe I’ll be more lucky here :)
Hi! Thanks for globalize2 – I hope that it’ll surpass first globalize with a clean code and usage of rails i18n framework. :) Unfortunately, as for now I’m stuck with rails 2.1.2 and globalize1 (some recent version/hack for working with rails 2.x), because globalize2 doesn’t do “it” for me, yet. I’d love to use it, though, so my questions are: 1) Does globalize support full view files translations, i.e. .html.erb AND .[locale].html.erb? All of my views are translated this way and I’d really like to stick with it instead of slicing and putting into yaml files. 2) I’d like to migrate my currently-globalized data from db onto globalize2-compatible structure. As for now I have (for example): Article translates :title, :content table articles: id, title, content, createdat, updatedat table globalize_translations: default from globalize1 to keep fields transations And with default locale of course (set to pl-PL in my application) I want to have: table articles: id, createdat, updatedat table articletranslations: id, locale, articleid, title, content The thing is, articletranslations doesn’t have a corresponding model (and I wouldn’t like to create it if it’s not necessary), so to access it I have to include globalize2 in my application. But if I do that, I can’t access original articles.title and articles.content (because globalize2 looks them up in an empty articletransations table that I want to populate with migrating script). How can I do it gracefully? Can’t think of better solution (as for now) than hand-crafting ArticleTranslation model and deleting it after migrating the data. Could you please clear it up for me? Any help will be greatly appreciated. Also if you need some help with coding features in globalize2, tell me where to start and I could send you patches (been working on some plugins – check out github.com/aenima, there are some plugins by company I work for). Do you have a board/group for globalize2 questions and issues? Regards, Tomasz Stachewicz
Tomash said January 12th, 2009 at 02:59 PM ¶
Hi!
Thanks for globalize2 – I hope that it’ll surpass first globalize with a clean code and usage of rails i18n framework. :)
Unfortunately, as for now I’m stuck with rails 2.1.2 and globalize1 (some recent version/hack for working with rails 2.x), because globalize2 doesn’t do “it” for me, yet.
I’d love to use it, though, so my questions are:
1) Does globalize support full view files translations, i.e. .html.erb AND .[locale].html.erb? All of my views are translated this way and I’d really like to stick with it instead of slicing and putting into yaml files.
2) I’d like to migrate my currently-globalized data from db onto globalize2-compatible structure. As for now I have (for example):
And with default locale of course (set to pl-PL in my application)
I want to have: table articles: id, createdat, updatedat table articletranslations: id, locale, articleid, title, content
The thing is, articletranslations doesn’t have a corresponding model (and I wouldn’t like to create it if it’s not necessary), so to access it I have to include globalize2 in my application. But if I do that, I can’t access original articles.title and articles.content (because globalize2 looks them up in an empty articletransations table that I want to populate with migrating script). How can I do it gracefully? Can’t think of better solution (as for now) than hand-crafting ArticleTranslation model and deleting it after migrating the data.
Could you please clear it up for me? Any help will be greatly appreciated.
Also if you need some help with coding features in globalize2, tell me where to start and I could send you patches (been working on some plugins – check out github.com/aenima, there are some plugins by company I work for).
Do you have a board/group for globalize2 questions and issues? Regards,
joost said February 2nd, 2009 at 04:50 PM ¶
I keep getting a:
A copy of Globalize::Model::ActiveRecord::Translated::ActMethods has been removed from the module tree but is still active!
On the second reload of a page in development mode (globalize2).. anybody got some tips?
MySchizoBuddy said February 16th, 2009 at 03:33 PM ¶
will it support Rails 2.3?
Prakash Teli said April 22nd, 2009 at 10:12 PM ¶
I am currently using acts_as_versioned to keep track of the model changes. How could I keep the versioning feature and localize the model attribute?.
The problem is that both acts_as_versioned and Globlalize2 maintains the attributes in its own tables. Is there any plan of adding versioning capability to Globalize?
Thanks.
Prakash Teli
Sven said April 23rd, 2009 at 09:25 AM ¶
Prakash, there’s globalize_versioned for this. Can find it on Github. HTH :)
jack said January 23rd, 2011 at 10:22 AM ¶
This is a really good read for me, Must admit that you are one of the best blogger I ever saw.Thanks for posting this informative article. windows vps
GenriFridt said February 10th, 2011 at 01:10 AM ¶
I have a problem with translation data (. bad hands
Allen said February 11th, 2011 at 11:19 AM ¶
website design cumbria - We offer Search Marketing solutions to UK businesses looking to promote their websites on the internet and through the search engines.
spy equipment - Whatever your reason for visiting our site, we want you to know that we are dedicated to providing you with the very latest in cutting-edge solutions to assist in resolving your issues.
Aalupalak said February 18th, 2011 at 11:39 AM ¶
Web Development Canada - We offer Web Creation, Web Development Services, Mobile App Development and SEO Traffic Solutions.
Stenbroweg said March 1st, 2011 at 11:09 PM ¶
Custom pluralizations format? Yeah, I know, it is still a bit of a hack but it would be nice if backend authors can elaborate on lambda pluralizers “API” so that it would be easy to use custom backends that support Globalize conventions. buy levitra pharmacy
Allenwood said March 7th, 2011 at 11:35 AM ¶
Website design cumbria - Finding someone to design a website for you is tricky business, as there are so many web design companies out there.
ddsgd said March 21st, 2011 at 06:29 AM ¶
How to Convert AVCHD films to AVI
URL?http://www.wondershare.com/avchd/convert-avchd-to-avi.html Troubles we may possibly have encountered to take satisfaction in and reveal AVCHD films with friends:
That’s true, the AVCHD structure is not accepted by lots of players, and also this kind of structure cannot be uploaded to internet which prevents film sharing. I’ve searched near to some great offer and uncover an simplest alternative finally. The simplest way can be to convert avchd to avi or other standard formats.
The alternative we are able to consider to solve them: An AVCHD to AVI Converter is needed. Please click to obtain avchd to avi converter, set up and run it. Step one Get AVCHD films from AVCHD Camcorder to PC
Connect the AVCHD Camcorder for the PC using a USB cable. when attached and powered on, the camcorder should seek out the desktop like a brand brand new disk. It is desirable which you duplicate the films for the PC’s hard-drive earlier to converting avchd to avi or editing it. Step 2. fill AVCHD camcorder videos
Click “Add Video” or just drag & squirrel away your AVCHD camcorder films using the document checklist directly, you can very easily include AVCHD camcorder videos.
Load AVCHD camcorder videos Step 3. find AVI as output format
Select AVI as output structure away from your categorized output formats checklist in “Profile” drop-down checklist and specify the output list to preserve your converted records in “Output” drop-down list.
Select Convert AVCHD films to AVI output format Step 4. start to convert avchd to avi
After every little thing is done, strike “Start” key to convert avchd to avi. And all the things can be achieved at quickly demand and higher quality. The conversion demand often is dependent for the genuine film sizing as well as your PC configuration. as well as the output best quality is great.
After converting avchd to avi, now you can upload these AVI films to internet or view them with house windows advertising Player/Movie Maker to reveal them jointly with your friends. The complete method is easy, and you also can possess a try of the AVCHD to AVI Converter to how to convert avchd to avi and reveal your delighted instant easily.
Tips: Why we choose AVI format? As we realize that AVI structure is among the probably the most standard formats, that is broadly accepted by the majority of players. as well as the best quality of AVI film is great. using the sake of reputation and compatibility, AVI is regarded as probably the most advantageous choice. Therefore, you only should convert AVCHD to AVI, after which you can very easily reveal your AVCHD camcorder videos.
Okey oyunu said May 12th, 2011 at 03:34 PM ¶
Tüm dünya artik okey oyunu oynuyor. Yillardir bir çok oyun programi olmasina ragmen, içlerinden en güzeli olarak nitelendirebilecegimiz tek bir site göze çarpmaktadir. Diger tüm okey oyunu programlarinin aksine ücretsiz olmasi ve 3 boyutlu olarak hizmet vermesi mükemmel bir gelismedir. Sizlerde www. okey-oyunu.com adresinden bu essiz okey oyununu indirebilirsiniz. Kullanimi çok basit ve Türkçe dil seçenegi ile kolaylikla oyuna baslayabilirsiniz. Ister kendi ülkenizden, isterseniz dünyanin tüm farkli bölgelerinden dilediginiz oyun odalarini seçerek, oyuna hemen baslayabilirsiniz. Okey oyunu oynamak için artik arkadas bile aramaniza gerek kalmadan, bilgisayarinizdan 100 binlerce üye ile online olarak okey oyununu oynamanin zevkine varabilirsiniz.
Joanna said May 13th, 2011 at 02:04 PM ¶
Thanks for this great plugin. I went to globalize2-demo to test it out. Thank you. Joanna from absorbent pads
p said May 21st, 2011 at 05:05 PM ¶
porno said May 23rd, 2011 at 10:40 AM ¶
good comment. thanks you friends.
I’ve surfed the net more than three hours today, however, I haven’t found such useful information. Thanks a lot, it is really useful to me
porno said May 23rd, 2011 at 10:40 AM ¶
good comment. thanks you friends.
I’ve surfed the net more than three hours today, however, I haven’t found such useful information. Thanks a lot, it is really useful to me