merb basic internationalization hooks
Reported by Matt Aimonetti (mattetti) | May 25th, 2008 @ 09:21 AM | in 1.1
see properly formatted ticket there: http://pastie.textmate.org/priva...
internationalization
=====================
Now:
when 2..44 then "#{distance_in_minutes} minutes"
when 45..89 then 'about 1 hour'
when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
when 1440..2879 then '1 day'
when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
when 43200..86399 then 'about 1 month'
when 86400..525599 then "#{(distance_in_minutes / 43200).round} months"
when 525600..1051199 then 'about 1 year'
else "over #{(distance_in_minutes / 525600).round} years"
The problem is that it can't be translated properly and only English is supported. To internationalize this piece of code, a plugin would need to overwrite the method which obviously will break if the original code is changed.
My goal is not to provide an official i18n solution but a easily solution for 3rd party developers to internationalize merb's components.
I18n solutions are usually based on a key, value solution. The i18n method usually lookups the translation in a dictionary/data store using the localization key and returns it.
For instance:
- localization data store
- English dictionary
:greetings => 'welcome'
- Spanish dictionary
:greetings => 'hola'
- internationalization
def greet_the_world
translate(:greetings, :language => 'es')
end
------------
Merb shouldn't include an i18n/l10n solution by default. However having a no op method would make things really easier for developers.
Something like that could work out:
@@merb_default_translations = {
:greetings => 'hello',
:about_1_hour => 'about 1 hour'
}
- ==== Parameters
- key:: translation key used to look up the string to return
#
- ==== Options
- optional, used by localization/internationalization plugins
#
- ==== Returns
- String:: translation
def translate(key, *options)
@@merb_default_translations[key]
end
The above solution works great until you actually need to use interpolation and pluralization. I'll skip pluralization for now but interpolation is a major problem. For instance how would you internationalize:
"about #{(distance_in_minutes.to_f / 60.0).round} hours ago"
Because we need to look up the translation we have to use a key, but keys are not dynamic and the amount of hours is. The usual solution is to pass the arguments to use in the translation as params.
translate(:about_x_hours_ago, {:hours => (distance_in_minutes.to_f / 60.0).round})
In your data store, the translation will be stored as:
:about_x_hours => "about {{hours}} hours ago"
An interpolation needs to happen so {{hours}} can be replaced by the correct/dynamic amount.
Note that we could have also passed only the needed param, but that would cause issues when you have multiple params. Here is an example:
:user_notice_email_received => "Hi {{first_name}} {{last_name}}, you have {{email_count}} emails"
If you were using an Asian translation, you would more than likely switch first_name and last_name, without using specific identifiers, the translator couldn't switch interpolations.
Potential solution:
@@merb_default_translations = {
:greetings => 'hello',
:about_x_hours => "about {{hours}} hours ago",
:user_notice_email_received => "Hi {{first_name}} {{last_name}}, you have {{email_count}} emails"
}
- ==== Parameters
- key:: translation key used to look up the string to return
#
- ==== Options
- values a hash defining values used for interpolation
- optional, used by localization/internationalization plugins
#
- ==== Returns
- String:: translation
def translate(key, *options)
translation = merb_default_translations[key]
if options[:values]
interpolate_string(translation.dup, options[:values].dup)
else
translation
end
end
def interpolate_string(string, args={})
if args.length > 0
args.each do |arg|
string = string.gsub("{{#{arg[0].to_s}}}", arg[1].to_s)
end
end
string
end
Comments and changes to this ticket
-
Michael Klishin (antares) May 27th, 2008 @ 12:02 AM
- → State changed from new to open
Matt,
Good point, I think it should be done as part of 0.9.5.
-

Prabode Weebadde May 31st, 2008 @ 08:09 PM
Let me know what you think of my i18nrb plugin
URL http://i18nrb.rubyforge.org/rdoc/
Summery
The plugin uses a yaml property file with the naming format "application_resources.yml" for each language. For example
Spanish application resources file => application_resources_es.yml German application resources file => application_resources_de.yml The default application resources file is the English file => application_resources.yml
The messages are grouped based on the application component and each group contains a key: value pair for each message that we expect our application to present, in the locale appropriate for the requesting browser.
Example of a message
1. English - application_resources.yml
shared:
welcome: 'Welcome to {0}'
cart:
cart_items: 'You have {0} {1} in your cart.'
1. Spanish - application_resources_es.yml
shared:
welcome: 'Bienvenido a {0}!'
cart:
items_count: 'Usted tiene {0} {1} en su carrito de compras.'
As you can see, we can pass the dynamic values to the message using {0}, {1} format. The dynamic values should be an array and {n} should be the index of the respective value.
Locale Detection
The locale can be passed to the plugin or plugin will obtain the locale from the request header. We can choose the appropriate method based on the application i18n strategy. Set a default locale for the application using I18NRB_DEFAULT_LOCALE environment variable in the environment.rb. The plugin will load the default locale for the unsupported locales.
-
Matt Aimonetti (mattetti) May 31st, 2008 @ 10:18 PM
@prabode I'm part of the team who started working on i18n and l10n gems. Thanks for your suggestion.
The problem is that there is a lot of thing going on in the background to figure out what backend to use and what syntax is being used. I'm quite concerned by the performance impact. Adding i18n support to merb-core/more in theory shouldn't affect merb-core performance.
We are discussing this issue with the i18n team but most of us are really busy in RL or working on other projects.
Also, I need to check but I don't think the gems are handling locales in a thread safe way yet.
-Matt
-

Prabode Weebadde June 1st, 2008 @ 12:15 AM
Matt,
Sounds good, I like to contribute anyway I can even if i18nrb is not the right solution for merb-core.
Cheers,
Prabode
-
Michael Klishin (antares) August 2nd, 2008 @ 06:46 PM
- → Tag changed from to i18n merb-core
- → Milestone changed from to 1.0 Final
-
Matt Aimonetti (mattetti) September 9th, 2008 @ 04:50 PM
- → Assigned user changed from to Matt Aimonetti (mattetti)
-
Matt Aimonetti (mattetti) October 25th, 2008 @ 12:31 AM
- → Milestone changed from 1.0 Final to 1.1
- → State changed from open to unconfirmed
-
Michael Klishin (antares) October 30th, 2008 @ 11:02 AM
- → State changed from unconfirmed to confirmed
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
