Localization of Rails core

ActionView and ActiveRecord have hardcoded English strings which make
using Rails in a different language a bit harder.

ActiveRecord has hardcoded error messages, and ActionView has many
helpers rendering English strings, or localized content in English for
the US.

Here are some examples:

Date helper:
distance_of_time_in_words
number_to_currency
date_select

FormOptionsHelper:
country_options_for_select

Time and Date object

While many plugins monkey patch rails to offer core localization, I
feel that we should find a simple localization solution for the core
methods with English localization only.

I'm not talking about UI localization or Model localization but simply
offering an option to use Rails builtin methods in another context
than North America. I'm not trying to fight for a i18n/l10n solution
for Rails developers since I know we all have different needs and
that's why many people came up with different plugins.

I do understand that this question raises at least 4 issues:
- how to deal with pluralization?
- how to deal with different grammar and dynamic variables?
- how to setup a locale, and what format to adopt?
- how to create/maintain core localization?

Here is what I think about the above issues:

Pluralization:
At the moment, the core team doesn't use pluralization in their hard
coded English strings, and I believe most people would prefer to see a
pluralization error instead of an error message in English.

Grammar:
The syntax changes from one language to another and you can structure
sentences in the same order. I believe it can be easily done by
passing one or many variables to the translation.

for instance (inspired by Globalite http://svn.aimonetti.net/public/plugins/globalite/trunk/
):
  :localization_key.translate({:who => 'Matt', :when => 'Time.now'})

The translator could use :when and :when in its translation in
whichever order and wherever he wants. (obviously the 'macro' would be
replaced by the passed variable)

Locale:
Locale is a more touchy subject since if the core lets you define a
locale for an user or for the framework, it also mean that most i18n/
l10n plugins will use that same value. However, looking at the actual
Rails plugins, none seem to agree on a standard. In Globalite I
decided to use the following format (used on a lot of other projects):
US English locale would be en-US. Locales are specified by RFC 3066
and consist of two parts. The first is an ISO 639 language code and
uses lowercase letters. The second is an ISO 3166 country code in
uppercase letters.
In the case of Globalite I let the user set only the language and the
locale becomes en-* for generic English. This is a personal choice and
I'm not sure I would recommend to do the same in the core. I had a
discussion with Jeremy Voorhis http://www.jvoorhis.com/ from Globalize
during the last RailsConf and agreeing on a standard for a locale
might be the only real issue with localizing the core.

Create/maintain core localization:
I personally think that localization should be included in the core
and maintained by the core team. Obviously they wouldn't be able to
translate the core themselves.

My 2 cents worth,

  m>a

+1

I don't want to get into details yet, but I agree that the main issue
is agreeing on a standard for view translation that all plugins will
have to support. In Globalize, this would be: 'Validation Error'.t,
instead of simply 'Validation Error'. The idea would be for Rails core
to overload String#t with a method that simply returns the original
string, i.e. a no-op. The end user could then choose to use any i18n
plugin he wants, and everything would be available for translation
with no monkey-patching needed. This in itself would be a huge step,
and I don't see a lot of downside. Localizing dates and countries
could also be done much the same way.

If we agree that this is a good idea, we can start discussing
standardization details.

Josh Harvey
Globalize Dev

Most sentences can't be localized with just a word by word translation. I don't think this will solve the problem. I localize by overriding the relevant methods.

Manfred

The end user could then choose to use any i18n
plugin he wants, and everything would be available for translation
with no monkey-patching needed. This in itself would be a huge step,
and I don't see a lot of downside. Localizing dates and countries
could also be done much the same way.

I don't quite follow how adding a String#t no-op helps the
localization plugins? Could you explain that a bit more please?

I personally think that localization should be included in the core
and maintained by the core team. Obviously they wouldn't be able to
translate the core themselves.

This has come up repeatedly, and it is unlikely that rails' core will
be localised. We only want something there which fits most cases,
most of the time. The fact that there are multiple competing
implementations and approaches for localising rails applications
indicates that there isn't a clear best-practise here yet.

I personally think that localization should be included in the core
and maintained by the core team. Obviously they wouldn't be able to
translate the core themselves.

This has come up repeatedly, and it is unlikely that rails' core will
be localised. We only want something there which fits most cases,
most of the time. The fact that there are multiple competing
implementations and approaches for localising rails applications
indicates that there isn't a clear best-practise here yet.

I'm sorry I wasn't clear enough, I don't want to find a way of
localizing rails applications but only localizing the core 'messages'.
I fully agree with you Koz, there isn't a clear best-practice and each
application will have different needs and can use one of the many
available plugin. However, I do believe that one shouldn't have to
overwrite the core methods to translate the output of a standard
helper.

During the RailsConf, I had the opportunity to discuss this issue with
David Heinemeier Hansson and maybe he could explain better the issue
and potential solutions?

Matt

Well, each i18n plugin would override String#t to actually translate
the validation message. Anybody who doesn't want i18n just uses Rails
as usual. But anyone who does want to translate, just adds their
localization plugin of choice, which now can automatically translate
all of the Rails validation messages without having to alter any core
Rails code.

Btw, when I say String#t, I don't mean that it has to be String#t --
it could be any agreed upon stand-in. Also, it could be a bit more
sophisticated, to handle pluralization and string interpolation as
Globalize currently does.

Hope that helps,
Josh

That made sense to me right from the start. It’s crude, but would lift (some of) the pain of plugin authors. There will never be one-size-fits-all anyway.

Well, each i18n plugin would override String#t to actually translate
the validation message. Anybody who doesn't want i18n just uses Rails
as usual. But anyone who does want to translate, just adds their
localization plugin of choice, which now can automatically translate
all of the Rails validation messages without having to alter any core
Rails code.

But String#t, or anything else, would be entirely redundant without
localisation code in rails right? Adding a bunch of method
invocations for no new functionality doesn't seem like a good trade :slight_smile:

  It seems the best bet is to leave the concern entirely outside rails
itself, until the current disparate efforts can be folded into a
single 'best practise'. Failing that, perhaps it's something where
there isn't a solution which suits 'most of the people most of the
time'.

Is this the opinion of the whole team? That copy/pasting whole code for Rails core methods is the preferred way of changing hardcoded strings?

No wonder i18n plugins always fell behind on new releases of the framework. It’s hard to keep up that way.

  It seems the best bet is to leave the concern entirely outside rails
itself, until the current disparate efforts can be folded into a
single 'best practise'. Failing that, perhaps it's something where
there isn't a solution which suits 'most of the people most of the
time'.

There will never be a best practice because there is more than one problem to solve. But does this mean
that Rails Core feels that it's OK for a growing number of plugins to override large chunks of Rails code?
For this problem 'most people' means 'most il8n plugin developers' and 'people who need localization' of which
there are many of both now.

One could look at the 'prepend_view_path' option as a feature that was added specifically to ease the development
of plugins. Why would a similar solution for changing error messages and other hard-coded strings in Rails be different,
  except for the valid point of having extra (though hardly complex or detrimental) method invocations?

It's understandable to shy away from il8n because of its 'can of worms' nature. But what we're really talking about here
  is providing a simple mechanism by which plugins can access and change Rails
error messages and hard-coded strings. Lumping that in with the rest of the il8n/il0n problems is a red herring.

Perhaps it's time to lift the stigma associated with il8n and look at a specific proposal for how to solve this. Many other
frameworks provide simple solutions to this without adding complexity beyond variable interpolation.

Joshua Sierles

Michael Koziarski wrote:

Well, each i18n plugin would override String#t to actually translate
the validation message. Anybody who doesn't want i18n just uses Rails
as usual. But anyone who does want to translate, just adds their
localization plugin of choice, which now can automatically translate
all of the Rails validation messages without having to alter any core
Rails code.

But String#t, or anything else, would be entirely redundant without
localisation code in rails right? Adding a bunch of method
invocations for no new functionality doesn't seem like a good trade :slight_smile:

It would make the life of all non-english developers a lot easier as swapping the hard coded strings becomes very easy and does not include copy&pasting functionality or fiddling rails' internals.

In case of the average english developer nothing has changed.

Jonathan

Agreed 100%. The fact that localization plugins have to override many
hard coded strings in core Rails points to a problem with core Rails,
and not an issue with localization complexity. This is just a 'better
practices' thing - externalize constants so they can be easily
changed, whether for language or just preference.

International apps shouldn't be penalized just because the core team
writes English-only apps. There should be a easier solution to allow
overriding the default messages, while maintaining the English
messages for the 80% who are fine with that.

Are there any patches in trac that address this problem directly?

- Rob

Is it possible to auto-extract strings like Heckle?
Doing so it would be very easy to lookup for translatable strings and
no change to core would be needed.

Marcello

Is it possible to auto-extract strings like Heckle?
Doing so it would be very easy to lookup for translatable strings and
no change to core would be needed.

Marcello

Is it possible to auto-extract strings like Heckle?
Doing so it would be very easy to lookup for translatable strings and
no change to core would be needed.

Marcello

Is it possible to auto-extract strings like Heckle?
Doing so it would be very easy to lookup for translatable strings and
no change to core would be needed.

Marcello

I understand that many people won't get use out of 't', but I think
the extra work involved (we're talking about an extra charcter, and
letting the people who care submit patches to clean up what's already
there) is trivial in comparison to what is gained here. It means that
i18n efforts can hook into rails core easily, without monkey patching
large bits of code (which is inhearently error prone).

I think this fits into something that has minimal effect on the
codebase at large, but has a very large gain for the plugin writing
community. I think this effort, which isn't deciding on a specific way
to do i18n, but only on a common helper method for it, is something
core can do without picking sides. I also think this means that the
arguments about localization of rails core are going to go away
because people can solve their own problems easily.

Wouldn't that be nice? No more threads about localization in rails
core? Wouldn't it? :wink:

Kev

Alright, that's exactly what I wanted to avoid... a long thread about
how the core should deal with localization :frowning:

I don't think the core team should adopt a .t method or another way of
dealing with translation. That's really up to the plugin developers to
decide.
What I would like to see is simply a way of declaring your locale and
when you call one of the usual method, instead of returning an English
string you get something in your own language/culture.

Nothing fancy, nothing specially designed to help l10n/i18n plugins
but just to avoid patching the core methods. (extending is fine)

-Matt

Nothing fancy, nothing specially designed to help l10n/i18n plugins
but just to avoid patching the core methods. (extending is fine)

Provided there are no adverse performance or understandability
impacts, I think we could apply a patch which refactored the core code
a little. If a little bit of refactoring would let plugin authors
override in a slightly-more-surgical manner, then I figure that'll add
much more to l10n plugin authors than a no-op, uncalled, method on
String. :slight_smile: