Hi folks,
today I've stumbled across an issue that I already raised (and
partially fixed with a plugin) last summer, namely the lack of lambda
support in i18n.
See this topic for more in-depth information:
http://groups.google.com/group/rails-i18n/browse_thread/thread/7b042fffe6b40e3d
As I said, I've partially fixed the issues with my localized dates
plugin (see
http://github.com/clemens/localized_dates) where I've
added support for lambdas at least for localizing dates. Apart from
the fact that I still feel that this belongs into i18n itself
including a proper Rails patch (also see the still pending patch I
proposed at Lighthouse:
https://rails.lighthouseapp.com/projects/8994/tickets/748-date-and-time-classes-i18n-l10n-implementation),
today I saw that this would also be of use for translations (not only
localizations).
Here's a use case: Assume you're creating an application with some CRM-
like functionalities such as emails, letters etc. to customers which,
of course, needs proper i18n so you can address your customers
accordingly. The primary issue here is the salutation (assume we have
Dr Gregory Brown, his wife Sandra and their (unmarried) daughter
Catherine):
- (Formal) English: Dear Dr Brown, Dear Mrs Brown, Dear Ms Brown
- (Informal) English: Dear Gregory, Dear Sandra, Dear Catherine
- German: Sehr geehrter Herr Dr. Brown, Sehr geehrte Frau Brown, Sehr
geehrte Frau Brown
- (Older Austrian) German: Sehr geehrte Frau Dr. Brown (we used to
address women with their spouse's academic title)
The problem here is two-fold:
- Some languages (e.g. English, French) distinguish between married
and unmarried women and address them differently (Mrs/Ms).
- Some languages include prefixes in the salutation, some don't. Even
if they include prefixes, there are differences: In German, we still
use "Herr/Frau" (Mr/Mrs/Ms) together with the actual prefix (e.g.
academic titles) whereas in other languages (e.g. English) you drop
the "gender prefix" and only use the actual prefix.
Now, of course you could handle all this logic in the model/view code:
if person.has_prefix?
I18n.t(:'salutation.with_prefix')
else
I18n.t(:'salutation.without_prefix')
end
However, if you have rules with increasing complexity, this can easily
get out of hand. Plus, at least in my opinion, translations are
separate entities and models/views/controllers shouldn't have to deal
with the additional logic.
Here's a short implementation of a translation with logic, using a
lambda:
http://gist.github.com/90757. As you can see, this gives us
the opportunity to extract all translation-related logic into the
translation itself instead of bothering the model with it. The
translation can call other translations internally which could also
save you from doing weird double translations like <%= t
(:signup_text, :signup_link => link_to(t(:signup_link_text),
signup_path)) %> because there might be potential to internalize it.
I'm not sure how attributes should be passed. For this example, I've
assumed that a hash is passed, so if you have t(:something, :x =>
x, :y => y, :z => z) you get attributes[:x] etc. in Ruby translations
and the usual interpolations (e.g. {{x}}) in YAML translations. This
might not be a suitable solution as it might clash with localize where
you'd have to pass the object to be localized to the lambda (e.g.
lambda { |date| ... }) - but of course, you could always pass both
(lambda { |date, attributes| ... }).
I'm curious as to what you guys think about this use case and whether
or not it justifies to (finally) implement lambda support in i18n.
- Clemens