yaml loader plugin

38 views
Skip to first unread message

iain

unread,
Jul 24, 2008, 2:02:56 PM7/24/08
to rails-i18n
Hi,

I made a small plugin to use yaml files to load translations. You can
find it here: http://github.com/iain/i18n_yaml

In short it supports these functions:
- Loads complete directories with yaml files per language
- Uses Rails' built-in caching methods
- Provides a before_filter for your controllers to set the locale from
params or session.
- Provide basic translations, so far only Dutch, if you made your own
rails.yml, please submit it ;)
- Provides some view helpers ht and th which is a combination of h()
and t().

Can you tell me what you think, have any suggestions about it, or that
I'm missing something?

BTW: my opinion about the i18n-work: fabulous! I love it!

Sven Fuchs

unread,
Jul 26, 2008, 7:12:16 AM7/26/08
to rails...@googlegroups.com
Hey Iain,

I've just looked at your plugin. This is awesome :)

What I particulary find interesting is that you're using Rails.cache
directly. I would immediately have put that into a custom backend
(like SimpleCachingBackend) but now that I'm reading your code I'm
wondering if that really would make more sense.

Also: #available_locales seems to look up a separate locales.yml file.
This is also interesting because it allows to "switch on/off" certain
locales no matter if they are actually available as translation data.
Maybe you could additionally fall back to looking at the /locales/
[locale] subdirectory names and use these if no locales.yml file has
been provided?

In your code comments you're using 'nl-NL' as an example for a locale
while on http://github.com/iain/i18n_yaml/wikis/getting-started there's

I18n.default_locale = 'english'

I think we all should standarize on using RFC4646 [1] compliant
locales both for providing locales data and documentation to make sure
our data is more exchangeable. We haven't build in any locale
constraints to the API to keep it as simple and slim as possible but I
start wondering if we probably should have added some kind of super-
simple locale validation.

In any case it might be a good idea to at least standarize on that in
an informal way.

Also, I've send out a couple of messages to the Japanese followers of
my I18n fork on GitHub and other guys. We've been told that YAML might
cause major headaches when used for Japanese (and similar) languages.
I still haven't been able to definitely confirm this though. Maybe
there's already somebody on the list who can point to some ressources
that explain those issues?


[1] http://rfc.net/rfc4646.html
--
sven fuchs sven...@artweb-design.de
artweb design http://www.artweb-design.de
grünberger 65 + 49 (0) 30 - 47 98 69 96 (phone)
d-10245 berlin + 49 (0) 171 - 35 20 38 4 (mobile)



iain

unread,
Jul 27, 2008, 5:07:06 AM7/27/08
to rails-i18n


On Jul 26, 1:12 pm, Sven Fuchs <svenfu...@artweb-design.de> wrote:
> Hey Iain,
>
> I've just looked at your plugin. This is awesome :)

Thanks :)

> What I particulary find interesting is that you're using Rails.cache  
> directly. I would immediately have put that into a custom backend  
> (like SimpleCachingBackend) but now that I'm reading your code I'm  
> wondering if that really would make more sense.

I've also been wondering that. The documentation encourages you to
make your own backend. But I'm not sure if I'd want to do that. It
wasn't my intention to change anything in the i18n impelementation,
just add a yaml-loader. Of course I got carried away.


> Also: #available_locales seems to look up a separate locales.yml file.  
> This is also interesting because it allows to "switch on/off" certain  
> locales no matter if they are actually available as translation data.  
> Maybe you could additionally fall back to looking at the /locales/
> [locale] subdirectory names and use these if no locales.yml file has  
> been provided?

The locales.yml has been added for multiple locales for one language.
Locales like en-GB and en-US are all english and although there is
difference between them, you mostly wouldn't implement that.

> In your code comments you're using 'nl-NL' as an example for a locale  
> while onhttp://github.com/iain/i18n_yaml/wikis/getting-startedthere's
>
> I18n.default_locale = 'english'
>
> I think we all should standarize on using RFC4646 [1] compliant  
> locales both for providing locales data and documentation to make sure  
> our data is more exchangeable.

I tried to group en-US and en-GB and stuff. I'm struggling a bit to
know how to properly interpret HTTP_ACCEPT_LANGUAGE and locales.
Should I just split('-') so I only look at the first part, or group it
with locales.yml? What's your advise on this?

> We haven't build in any locale  
> constraints to the API to keep it as simple and slim as possible but I  
> start wondering if we probably should have added some kind of super-
> simple locale validation.

> In any case it might be a good idea to at least standarize on that in  
> an informal way.

I'd like that.

> Also, I've send out a couple of messages to the Japanese followers of  
> my I18n fork on GitHub and other guys. We've been told that YAML might  
> cause major headaches when used for Japanese (and similar) languages.  
> I still haven't been able to definitely confirm this though. Maybe  
> there's already somebody on the list who can point to some ressources  
> that explain those issues?

Damn those pesky non-latin languages ;) Anyway, my plugin is still
Simple. I'm not trying to make a one-size-fits-all solution. When you
want to do japanese, arabic or stuff, it might be better to use
Globalize?

PS. Do you have a list of things that are translatable in the Rails
core? I've been looking for it, but somehow I think I'm missing a lot.

Sven Fuchs

unread,
Jul 28, 2008, 3:40:34 PM7/28/08
to rails...@googlegroups.com
Hey Iain,

On 27.07.2008, at 11:07, iain wrote:
> The locales.yml has been added for multiple locales for one language.
> Locales like en-GB and en-US are all english and although there is
> difference between them, you mostly wouldn't implement that.

Ah! Ok, so that touches the topics of

a) hierarchically organized locale data (en-US and en-GB can both
share most of en and only add a couple of differences) and
b) locale fallback (if the client requests en-GB, but there's only en
defined, en will be used)

These are both topics which we've discussed a lot initially but
finally abstained from doing anything about it. They are very
controversial topics to say the least ... and it's part of what I
meant in my blog post with "we initially tried to accomplish way too
much in Rails core" ;)

>> In your code comments you're using 'nl-NL' as an example for a locale
>> while onhttp://github.com/iain/i18n_yaml/wikis/getting-startedthere's
>>
>> I18n.default_locale = 'english'
>>
>> I think we all should standarize on using RFC4646 [1] compliant
>> locales both for providing locales data and documentation to make
>> sure
>> our data is more exchangeable.
>
> I tried to group en-US and en-GB and stuff. I'm struggling a bit to
> know how to properly interpret HTTP_ACCEPT_LANGUAGE and locales.
> Should I just split('-') so I only look at the first part, or group it
> with locales.yml? What's your advise on this?

As for parsing locales I think you should stick to what RFC4646
defines. E.g.:

http://trac.globalize-rails.org/trac/globalize/browser/branches/saimon/trunk_with_rfc4646_support/lib/globalize/localization/rfc_4646.rb
http://svn.artweb-design.de/stuff/globalize/cldr/lib/cldr/rfc4646.rb

The most important parts are the language and region tags. The 2-3-
letter lowercase, first part denotes the language tag. The 2-letter
uppercase second part (or third, if there's also a script tag given,
which would go to the second position then) denotes the region tag.
Thus en just means "English", while en-US means "English as spoken in
the *region* USA" (regions not necessarily are countries).

As far as I know HTTP_ACCEPT_LANGUAGE is a huge issue because
virtually nobody actually configures that header for their browser -
and browsers used to stick whatever crap into there. Maybe that
situation has improved, though.

I think we could all benefit from someone researching this matter and
then implementing a small plugin that does exactly that: do a
reasonable pick from HTTP_ACCEPT_LANGUAGE based on the available
RFC4646 locales in an app.

So ... if you'd want to jump at that, that would be awesome :)

> Damn those pesky non-latin languages ;) Anyway, my plugin is still
> Simple. I'm not trying to make a one-size-fits-all solution. When you
> want to do japanese, arabic or stuff, it might be better to use
> Globalize?

I've got some responses from the Japanese people that I've contacted
recently. (Really, really, really exciting! *jumps* :D I totally hope
to be allowed to forward some of the news.)

Basically the answer is:

There's no problem with reading Japanese translations from YAML (as
long as utf-8, of course) - so everybody can do that. There's still a
huge problem with writing Japanese to YAML, though, because YAML
serializes this sort of data to a binary format - which completely
defeats the purpose of YAML as a format that makes manual editing easy
of course.

So, the advice is: If you want to write translations (and want your
solution working for a larger audience), don't use YAML. If you only
want to read from YAML, everything's cool with that :)

> PS. Do you have a list of things that are translatable in the Rails
> core? I've been looking for it, but somehow I think I'm missing a lot.

Actually, no. Although that would be a good idea.

The only lists available are the en_US.rb files in the various Rails
libraries. But of course that does not include translateable dynamic
things that are also already there (like model attributes).

iain

unread,
Jul 30, 2008, 7:07:26 AM7/30/08
to rails-i18n
> a) hierarchically organized locale data (en-US and en-GB can both
> share most of en and only add a couple of differences) and
> b) locale fallback (if the client requests en-GB, but there's only en
> defined, en will be used)

How about this kind of structure then:

.
|-- en
| |-- gb
| | `-- colour.yml
| |-- us
| | `-- color.yml
| `-- rails.yml

When en-GB is requested, load anything in en and in GB, but not US.
And let overlapping keys from the region override the language
specific translation.

> These are both topics which we've discussed a lot initially but
> finally abstained from doing anything about it. They are very
> controversial topics to say the least ... and it's part of what I
> meant in my blog post with "we initially tried to accomplish way too
> much in Rails core" ;)



> As far as I know HTTP_ACCEPT_LANGUAGE is a huge issue because
> virtually nobody actually configures that header for their browser -
> and browsers used to stick whatever crap into there. Maybe that
> situation has improved, though.

In the case of firefox: if you install the dutch version, dutch (nl-
NL) is automatically added to your header. My guess is IE does this as
well. So if you don't adjust it manually you get the default language
of the browser.

> I think we could all benefit from someone researching this matter and
> then implementing a small plugin that does exactly that: do a
> reasonable pick from HTTP_ACCEPT_LANGUAGE based on the available
> RFC4646 locales in an app.
>
> So ... if you'd want to jump at that, that would be awesome :)

I can extract the HTTP_ACCEPT_LANGUAGE identification from my plugin
ofcourse. Make something nice and i18n independent.


> So, the advice is: If you want to write translations (and want your
> solution working for a larger audience), don't use YAML. If you only
> want to read from YAML, everything's cool with that :)

You mean, as in automatic writing? I mean, I'm guessing that people
who understand japanese can edit a .yml file themselves. If the
YAML.load_file() method works fine with utf8, than I see no problem.


> Actually, no. Although that would be a good idea.

Working on it...

habermann24

unread,
Jul 30, 2008, 8:26:43 AM7/30/08
to rails-i18n
I can't get this plugin to work with form error messages. It says
"can't convert array into string" (error_messages_for) ...

I'm trying to fix this but i have no idea why this is happening...

Other than that...my question would be, if it would be possible to
translate the default rails error messages aswell!?

Sven Fuchs

unread,
Jul 30, 2008, 9:06:40 AM7/30/08
to rails...@googlegroups.com
Hi Jan,

thanks for registering :)

On 30.07.2008, at 14:26, habermann24 wrote:
> I can't get this plugin to work with form error messages. It says
> "can't convert array into string" (error_messages_for) ...
>
> I'm trying to fix this but i have no idea why this is happening...

I'd have to try that myself to answer the question. If you can't fix
it maybe it's easiest if you'd provide a failing test case?

> Other than that...my question would be, if it would be possible to
> translate the default rails error messages aswell!?

The Simple Backend which Iain uses overwrites existing keys and
translations iirc. Thus, if you make sure to load your custom
translations after the Rails frameworks have been loaded that should
work fine.

Sven Fuchs

unread,
Jul 30, 2008, 9:43:12 AM7/30/08
to rails...@googlegroups.com
>> a) hierarchically organized locale data (en-US and en-GB can both
>> share most of en and only add a couple of differences) and
>> b) locale fallback (if the client requests en-GB, but there's only en
>> defined, en will be used)
>
> How about this kind of structure then:
>
> .
> |-- en
> | |-- gb
> | | `-- colour.yml
> | |-- us
> | | `-- color.yml
> | `-- rails.yml
>
> When en-GB is requested, load anything in en and in GB, but not US.
> And let overlapping keys from the region override the language
> specific translation.

Sounds like a plan.

Although, maybe the nested directory structure makes it hard to see
what's there in one glance? Also, in an editor like Textmate where you
only see the filename on the tab, maybe it's more convenient to have
the full locale on the filename? Just mulling ...

-- en
`-- en.yml
`-- en-US_rails.yml
`-- en-US_colors.yml

Not sure ...

Btw ... I guess right now this certainly will be overkill, but at some
point in the future we might want to try to wrap our head around
private-use subtags. These can be used to define such variants like
"formal english" vs. "informal english" etc. E.g. in German you'd
address the user with "Sie" in a formal way, but with "Du" in an
informal way, in English this is both just "You". Of course one can
often work around these things but in the end it might make sense to
provide different translation files for variants like these and let
the user choose either de-x-formal or de-x-informal (in this example).

>> As far as I know HTTP_ACCEPT_LANGUAGE is a huge issue because
>> virtually nobody actually configures that header for their browser -
>> and browsers used to stick whatever crap into there. Maybe that
>> situation has improved, though.
>
> In the case of firefox: if you install the dutch version, dutch (nl-
> NL) is automatically added to your header. My guess is IE does this as
> well. So if you don't adjust it manually you get the default language
> of the browser.

Yeah, maybe it's more usable today than it used to be.

>> I think we could all benefit from someone researching this matter and
>> then implementing a small plugin that does exactly that: do a
>> reasonable pick from HTTP_ACCEPT_LANGUAGE based on the available
>> RFC4646 locales in an app.
>>
>> So ... if you'd want to jump at that, that would be awesome :)
>
> I can extract the HTTP_ACCEPT_LANGUAGE identification from my plugin
> ofcourse. Make something nice and i18n independent.

Cool!

>> So, the advice is: If you want to write translations (and want your
>> solution working for a larger audience), don't use YAML. If you only
>> want to read from YAML, everything's cool with that :)
>
> You mean, as in automatic writing? I mean, I'm guessing that people
> who understand japanese can edit a .yml file themselves. If the
> YAML.load_file() method works fine with utf8, than I see no problem.

I meant like in Globalize where you can have an UI to store
translations to the backend and such.

So for a solution like your's that's all fine.

>> Actually, no. Although that would be a good idea.
>
> Working on it...

Great :)

habermann24

unread,
Jul 30, 2008, 2:36:16 PM7/30/08
to rails-i18n
I had an error using this plugin that kept annoying me. When you try
to submit a form that does not validate, the error messages can't tbe
displayed...rails throws a "can't convert Array to string" error.
After alot of time spent investigating what causes the problem, i
thought this was a bug in rails core...

And somehow, it is...because you don't even need the yml_loader
plugin. Just set I18n.locale to something other than "en-US" and try
to display form errors.

However, i know how to fix this. You have to provide all rails error
messages with your locale...then it works. I thought rails would fall
back to en-US if you don't provide error messages, but it seems that
this is not the case.

So what i did is add the following translations to my rails.yml files:

active_record:
error:
header_message:
- "1 error prohibited this {{object_name}} from being saved"
- "{{count}} errors prohibited this {{object_name}} from being
saved"
message: "There were problems with the following fields:"

error_messages:
inclusion: "is not included in the list"
exclusion: "is reserved"
invalid: "is invalid"
confirmation: "doesn't match confirmation"
accepted: "must be accepted"
empty: "can't be empty"
blank: "can't be blank"
too_long: "is too long (maximum is {{count}} characters)"
too_short: "is too short (minimum is {{count}} characters)"
wrong_length: "is the wrong length (should be {{count}}
characters)"
taken: "has already been taken"
not_a_number: "is not a number"
greater_than: "must be greater than {{count}}"
greater_than_or_equal_to: "must be greater than or equal to
{{count}}"
equal_to: "must be equal to {{count}}"
less_than: "must be less than {{count}}"
less_than_or_equal_to: "must be less than or equal to {{count}}"
odd: "must be odd"
even: "must be even"

iain

unread,
Jul 30, 2008, 5:06:33 PM7/30/08
to rails-i18n
I need to read the google-group before I reply to my mail ;)
Thank you for your testing this. I've looked at the current edge code
and found that the error messages don't do default values.

in the file: vendor/rails/activerecord/lib/active_record/
validations.rb on line 171, it reads a variable called "message" which
turns out to be an array.In my testcase it was this:
[:"custom.product.name.blank", :blank] for a Product model and a name-
field that couldn't be blank.

A couple of thoughts cross my mind

* Cool that you can define custom error messages per model in you lang-
files instead of in the controller \o/
* What is that "custom" scope doing there? Seems like an odd name.
* There's no "try-these-keys" function in i18n functionality. You
can't supply I18n.translate an array of keys, to try out and use the
first translation it finds. It just translates them both and
concatenates them. Maybe there should be? I'm not sure. Can you
guarantee this is the only case which produces an array?
* On lines 171 and 167 both reference the message. But at that time,
shouldn't the messages be already translated into the errors-object?
Shouldn't it be translated at the moment the error is raised, as
apposed to when it's displayed? That would solve this problem anyway,
because the display moment is not controlled by the user.
* i18n really _really_ needs a complete manual. I'm having a day off
tomorrow. I'll see what I can write in between chores. ;)

Sven Fuchs

unread,
Jul 30, 2008, 5:51:05 PM7/30/08
to rails...@googlegroups.com
Hi Iain

Thanks so much for taking the time for this. There's so much going on
right now that I barley find the time to answer the most important
mails :)

On 30.07.2008, at 23:06, iain wrote:
> in the file: vendor/rails/activerecord/lib/active_record/
> validations.rb on line 171, it reads a variable called "message" which
> turns out to be an array.In my testcase it was this:
> [:"custom.product.name.blank", :blank] for a Product model and a name-
> field that couldn't be blank.

I'd still have to look into that more closely, but it seems really odd
to me that this would be an array at this point.

> * Cool that you can define custom error messages per model in you
> lang-
> files instead of in the controller \o/
> * What is that "custom" scope doing there? Seems like an odd name.

We just wanted to pick a name for a namespace that definitely would
not conflict with any other namespaces. What would be a better name?

The purpose is, like you said, to be able to define custom error
message translations per model.

> * There's no "try-these-keys" function in i18n functionality. You
> can't supply I18n.translate an array of keys, to try out and use the
> first translation it finds. It just translates them both and
> concatenates them. Maybe there should be? I'm not sure. Can you
> guarantee this is the only case which produces an array?

I think there is this functionality, although it's not an explicit
method:

I18n.t :not_here, :default => [:also_not_here, :default]

This would try to lookup :not_here, and :also_not_here and (when they
don't yield a result) finally fall back to the translation of :default.

Is that what you mean?

You can also supply #translate an array of keys. This has a different
meaning, though, it's defined as "bulk-lookup" and returns an array of
translations:

I18n.t [:foo, :bar]
# => ['Foo translation', 'Bar translation']

> * On lines 171 and 167 both reference the message. But at that time,
> shouldn't the messages be already translated into the errors-object?
> Shouldn't it be translated at the moment the error is raised, as
> apposed to when it's displayed? That would solve this problem anyway,
> because the display moment is not controlled by the user.

IIRC it should be translated in #generate_message (line 68). This
method is used in #add_on_empty, #add_on_blank and all the
#validates_* methods, e.g. on line 401 in #validates_confirmation_of

Thus, I really wonder why in error_messages_for message would be that
array like you said. What did we miss here?

> * i18n really _really_ needs a complete manual. I'm having a day off
> tomorrow. I'll see what I can write in between chores. ;)

YAY :)

On a slightly related note:

We want to start something useful on rails-i18n.org soon so that it
would be available by Rails Conf Europe. Most likely a blog + wiki for
starters.

If anyone wants to help building it, maybe even contribute to the
design, step up :D

iain

unread,
Jul 30, 2008, 6:48:51 PM7/30/08
to rails-i18n
On Jul 30, 11:51 pm, Sven Fuchs <svenfu...@artweb-design.de> wrote:
> Thanks so much for taking the time for this. There's so much going on  
> right now that I barley find the time to answer the most important  
> mails :)

You're welcome. Although on monday starts a busy scrum project with
Rails, so I don't know if I'm able to code after work, or if I'll just
come home and fall asleep.

> I think there is this functionality, although it's not an explicit  
> method:
>
> I18n.t :not_here, :default => [:also_not_here, :default]
>
> This would try to lookup :not_here, and :also_not_here and (when they  
> don't yield a result) finally fall back to the translation of :default.
>
> Is that what you mean?

Yes, that is exactly what I mean.

> On a slightly related note:
>
> We want to start something useful on rails-i18n.org soon so that it  
> would be available by Rails Conf Europe. Most likely a blog + wiki for  
> starters.
>
> If anyone wants to help building it, maybe even contribute to the  
> design, step up :D

Yes, I do! But I'm a terrible designer. :)

On a final note for anyone: started work on a plugin to read the
accept-language http-header. Right now it just returns an array, but
if anyone has any suggestions on how to improve it?

You can find it on my github account, as usual: http://github.com/iain/http_accept_language

ry

unread,
Aug 2, 2008, 4:17:03 AM8/2/08
to rails-i18n
On Jul 27, 11:07 am, iain <i...@iain.nl> wrote:
> PS. Do you have a list of things that are translatable in the Rails
> core? I've been looking for it, but somehow I think I'm missing a lot.

this brings up an important point: by moving away from a gettext style
API it's not clear how one might extract the translatable strings in a
source tree. certainly this can be done at run time, by making the
application execute every possible behavior and adding the encountered
translatable strings to a file. but what about for applications that
are broken or not yet up and running. what about strings that only
appear under very rare circumstances - no one wants to fill their "po
file" (or yaml file or whatever) by clicking around on a website.

Gettext explicitly requires you to your strings inside _( ) so that
the parser could extract them from the source code. It seems I18N
intends its users to maintain source code but also an external
translations database.

ry

iain

unread,
Aug 2, 2008, 8:09:39 AM8/2/08
to rails-i18n
Tests (should) touch all code. No clicking required! You should have
autotest running in the background.

The problem is that you cannot know what is the translation key if
you're not executing the code in it's proper code. Your key could be
variable with a key, because it derives from another method.

You might want to have a rake task to check if your different language
files are synchronized and they contain the same keys.

Sven Fuchs

unread,
Aug 2, 2008, 11:38:05 AM8/2/08
to rails...@googlegroups.com
Hi ry,

On 02.08.2008, at 10:17, ry wrote:
> this brings up an important point: by moving away from a gettext style
> API it's not clear how one might extract the translatable strings in a
> source tree. certainly this can be done at run time, by making the
> application execute every possible behavior and adding the encountered
> translatable strings to a file. but what about for applications that
> are broken or not yet up and running. what about strings that only
> appear under very rare circumstances - no one wants to fill their "po
> file" (or yaml file or whatever) by clicking around on a website.
>
> Gettext explicitly requires you to your strings inside _( ) so that
> the parser could extract them from the source code. It seems I18N
> intends its users to maintain source code but also an external
> translations database.


We did not move away from a gettext style api :) What we did was
choosing an api for a different layer where no api existed at all. The
api in no way works against gettext, nor against any other
implementation. It's just a barebone api and still leaves the actual
implementation to plugins.

So you can both:

- implement a backend which uses gettext for storing and looking up
translations (and we hope there will be one for gettext really soon)
- define Object#_ for the frontend (Rails, Merb, ... whatever
framework), so you can use _() in your applications and grep for that
(with whatever tool)

Also, I agree with Iain that grep'ing the source code is not really a
safe solution either. (Which does not mean you should not use it of
course, mileages vary - especially when it comes to I18n.) The only
way to really be safe about missing translations is to have a complete
test suite . The api also supports this kind of approach by defining
different exception handlers.

Sven Fuchs

unread,
Aug 2, 2008, 11:47:02 AM8/2/08
to rails...@googlegroups.com
On 31.07.2008, at 00:48, iain wrote:
>> We want to start something useful on rails-i18n.org soon so that it
>> would be available by Rails Conf Europe. Most likely a blog + wiki
>> for
>> starters.
>>
>> If anyone wants to help building it, maybe even contribute to the
>> design, step up :D
>
> Yes, I do! But I'm a terrible designer. :)

I've done a basic design and set up a blog and wiki: http://rails-i18n.org/

The site is using adva_cms which is a project I'm currently working on
(http://github.com/svenfuchs/adva_cms). It's still pre-alpha, so it's
a bit wobbly but should already work for most basic things (including
the wiki).

ry

unread,
Aug 2, 2008, 12:42:14 PM8/2/08
to rails-i18n
Certainly one can define _() to use the current API in Rails and then
use gettext to extra text from their own code. However extracting text
from rails-core or other plug-ins will not work.

Not that I am against having a test suite that has full coverage, but
why should one tie the functionality of i18n to a test suite when
there is no need. If rails simply adopted the gettext _() API the
could still be independent back-ends and people would still have the
possibility of extracting translatable strings with reliability.

ry

Sven Fuchs

unread,
Aug 2, 2008, 1:44:34 PM8/2/08
to rails...@googlegroups.com
On 02.08.2008, at 18:42, ry wrote:
> Certainly one can define _() to use the current API in Rails and then
> use gettext to extra text from their own code. However extracting text
> from rails-core or other plug-ins will not work.

Why would you want to extract strings from rails-core? Translations
used in rails-core need to be available in the shipped en-US
translation files, so they're already known.

> Not that I am against having a test suite that has full coverage, but
> why should one tie the functionality of i18n to a test suite when
> there is no need.

Please, nobody ties anything. It's just a practice which is considered
preferrable by some.

> If rails simply adopted the gettext _() API the
> could still be independent back-ends and people would still have the
> possibility of extracting translatable strings with reliability.

I'm not sure what exactly you mean by "adopt the gettext _() API".

We have a t() API so instead of

_("Hi %s.")

it's

t(:"Hi {{name}}")

... if you want to use a default string as a key which you can do in
your plugin if you want.

Am I missing something?

Maybe this is, again, the misunderstanding that the I18n API shipped
was also a fullfledged L10n solution. *It's not.* It really is not. We
still have to build on this. We're still supposed to implement our own
needs as plugins (or whatever libraries).

Iain Hecker

unread,
Aug 2, 2008, 2:03:01 PM8/2/08
to rails...@googlegroups.com
I got a 500 when posting a comment.

Nice site though.

ry

unread,
Aug 2, 2008, 2:19:15 PM8/2/08
to rails-i18n
Hi Sven,

> I'm not sure what exactly you mean by "adopt the gettext _() API".
>
> We have a t() API so instead of
>
> _("Hi %s.")
>
> it's
>
> t(:"Hi {{name}}")
>
> ... if you want to use a default string as a key which you can do in  
> your plugin if you want.
>
> Am I missing something?

My point is that in order for extraction to work it needs to be made
clear that t(:..) or _(...) may not be wrapped in functions but
strings be placed directly inside t( ). The _() is understood in two
ways: from the extraction parsers (which are not grep, they can
understand comments and such) and by the runtime library which
localizes them.

In rail-i18n you've provided a runtime library (yes, generalized (no
need to rely on po-files or any other backend)) but you do not have
the extraction. What is needed is

1) Usage rules - I18N.t cannot be wrapped in functions it must be used
directly on strings. e.g. One can not do

def my_translation_function(str)
t(str)
end
my_translation_function("hello world")

The parser will not be able to know that "hello world" is supposed to
be translated.

2) A parser which can extract and understand the arguments of
I18N.t().

ry

Sven Fuchs

unread,
Aug 2, 2008, 2:43:26 PM8/2/08
to rails...@googlegroups.com
On 02.08.2008, at 20:19, ry wrote:
> My point is that in order for extraction to work it needs to be made
> clear that t(:..) or _(...) may not be wrapped in functions but
> strings be placed directly inside t( ). The _() is understood in two
> ways: from the extraction parsers (which are not grep, they can
> understand comments and such) and by the runtime library which
> localizes them.
>
> In rail-i18n you've provided a runtime library (yes, generalized (no
> need to rely on po-files or any other backend)) but you do not have
> the extraction. What is needed is
>
> 1) Usage rules - I18N.t cannot be wrapped in functions it must be used
> directly on strings. e.g. One can not do
>
> def my_translation_function(str)
> t(str)
> end
> my_translation_function("hello world")
>
> The parser will not be able to know that "hello world" is supposed to
> be translated.
>
> 2) A parser which can extract and understand the arguments of
> I18N.t().

Yes, I was aware of these implications.

You can do exactly that. The I18n API does not hold you back from
implementing and using this. It's outside of the scope of the API.

Maybe what you really mean though is that you would have liked to see
a common agreement across all I18n plugin devs in the Rails world to
support this style.

This certainly would not have been achievable for the simple reason
that not everybody wants to use it. I can tell you from the
discussions we had since September last year that this style
definitely would not have been something that the developers of all
today's major plugin's developers would have wanted to adopt. So it
would not have been an option.

Let alone the restriction not to wrap method calls (which would be a
significant limitation alone for the Rails core patch implementation)
many people do not agree with the "default translations as keys"
approach any more. Sure, it was the dominant approach for a long time
and Gettext, Gibberish *and* Globalize supported them in one way or
another but it also has caused quite some problems.

That said, the I18n API still does in no way limit you from doing
exactly that. You just can't expect everybody else to do it. But
that's been true as long as there was Rails I18n.

Sven Fuchs

unread,
Aug 2, 2008, 2:46:01 PM8/2/08
to rails...@googlegroups.com
Apparently Defensio refused to answer (or something else with chatting
with Defensio was wrong).

You're comment was saved though and I just approved it manually :)

All the best for your notebook + server hdd!

glennpow

unread,
Aug 2, 2008, 6:22:55 PM8/2/08
to rails-i18n
Hi Iain,

I'm interested in your accept language plugin. It could be useful,
but in order for I18n to use the locales (reference the properly keyed
set of translations), they must be in the proper format (xx-XX) where
the language part is lowercase and the country part is uppercase. I
realize that due to w3 specs, the headers will always have all-
lowercase locales, but perhaps your plugin could fix the locales once
it gets them in the array.

Iain Hecker

unread,
Aug 2, 2008, 7:46:50 PM8/2/08
to rails...@googlegroups.com
Actually, firefox sends it correctly, but since I didn't want any
problem with case, I convert everything to downcase anyway. But you make
a very good point.

BTW, I thought I18n didn't care about how locales are formatted. But it
isn't case-insensitive.

So I updated the plugin :)

glennpow

unread,
Aug 4, 2008, 11:34:54 AM8/4/08
to rails-i18n
Iain,

Glad to see the plugin is evolving. One thing I noticed is that you
have the rails.yml file which lists some of the Rails core
translations that can be found in a couple of the en-US.rb files in
the code. I assume you are specifying these so that they can
naturally be translated appropriately along with the other strings.
But why do you only have SOME of the core strings in rails.yml? There
are still those from activerecord and some others from action-view
that aren't included.
I especially noticed this, because it seems to cause problems when the
user receives errors while submitting forms. These error strings are
in the activerecord en-US.rb file, and so they are not included in the
YAML strings. And so, the translations cannot be found, which
ultimately (and annoyingly) results in an error:

can't convert Symbol into String

This is not the most revealing error message, and I'm sure there are
some things that can be cleaned up in the core when it handles these
messages, but still it boils down to not having the strings in
rails.yml.

And so, I guess I'm just asking you to include them :) But more
importantly, I'd like to know what happens when the core development
team decides to change or add more strings to the core? How will our
rails.yml keep up?

This wouldn't be a problem if the I18n.backend were set early enough
to catch the core strings correctly, but as I've stated before, these
strings are populated before the custom backend can be set.

To me, this is one of the major issues that must be solved immediately
if this I18n framework is to be effectively utilized.

Anyways, input is always welcome.
And thanks for the work.

iain

unread,
Aug 4, 2008, 2:08:06 PM8/4/08
to rails-i18n
Thank you for your support!

I am still working on it of course. Unfortunately it wasn't specified
which default keys were used in Rails, so this was my initial set. I
have gathered a lot of new keys, so they'll be added soon.

Sven has started a project to provide ready translated sets of default
languages. In the near future I will use this, instead of providing my
own languages. With this project, keeping up with new keys will be
easier.

I'm not working on any backend, so I don't really know how to solve
the backend stuff. To change the backend before rails starts, you'll
have to write something in boot.rb. Best case is that I18n is going to
be split into a gem, just like activerecord; that's underway as well I
believe.

I don't know when Rails 2.2 is going to be released, but we still have
a lot of work to do before it's ready, I know.

ry dahl

unread,
Aug 6, 2008, 6:11:19 AM8/6/08
to rails...@googlegroups.com
> Let alone the restriction not to wrap method calls (which would be a
> significant limitation alone for the Rails core patch implementation)
> many people do not agree with the "default translations as keys"
> approach any more. Sure, it was the dominant approach for a long time
> and Gettext, Gibberish *and* Globalize supported them in one way or
> another but it also has caused quite some problems.

The "default translations as keys" doesn't matter to me and I am happy
with your approach in this matter. What is important is the
possibility to extract keys outside of runtime. I don't agree that
this is a triviality.

What happens when some Rails plug-in developer adds some call to
I18n.t()? How are application developers notified of this so they can
make the appropriate translation?

I've heard three unsatisfactory solutions:
1. have all developers manually maintain both the source code and an
external database
2. grep -R "I18N.t"
3. Have tests with 100% coverage, write a collection back-end, and
collect all keys while running the tests.

ry

Sven Fuchs

unread,
Aug 6, 2008, 6:49:56 AM8/6/08
to rails...@googlegroups.com
Hi Ry,

On 06.08.2008, at 12:11, ry dahl wrote:
> The "default translations as keys" doesn't matter to me and I am happy
> with your approach in this matter. What is important is the
> possibility to extract keys outside of runtime. I don't agree that
> this is a triviality.

Agree with whom? Nobody said it's a triviality, or did I? C'mon.

From my point of view "possibility to extract keys outside of
runtime" is just something that a) can not be part of the scope of the
API (obvioulsy) and b) won't be easily solved for *all* of the Rails
I18n landscape because it relies on conventions that neither can be
enforced programmatically nor will be acceptable (or implementable)
for many developers (at least that's just what I'd expect based on
previous discussions, i well might be wrong).

That said, again, you can do that. If it's important to you, why don't
you get started with it?

> What happens when some Rails plug-in developer adds some call to
> I18n.t()?

With the current implementation and the Simple backend in Rails?
Nothing.

> How are application developers notified of this so they can
> make the appropriate translation?

The plugin dev will have a translations file included with the plugin.
The application dev can look at it.

> I've heard three unsatisfactory solutions:
> 1. have all developers manually maintain both the source code and an
> external database
> 2. grep -R "I18N.t"
> 3. Have tests with 100% coverage, write a collection back-end, and
> collect all keys while running the tests.

Make 2. your favorite gettext scrape tool (which I meant by "grep for
it") and implement your own helpers to be able to use _(). That won't
work for Rails and plugins, but it's a step forward. It relies on the
app dev to comply with your conventions, but that's been true since
the invention of Gettext, so it will work for *some* people and that
would be already great.

If you'd like to see Rails patched to better work with this sort of
approach or convention, we're certainly open to discussion. But please
provide reviewable code first that would leverage this sort of
functionality. Again, this scraping toolkit in my opinion could
neither go into the I18n gem nor Rails itself directly.

Please implement your ideas as a plugin or gem or whatever library. It
would be definitely a very useful addition. We'll certainly be happy
to help if we can.

ry dahl

unread,
Aug 6, 2008, 7:25:56 AM8/6/08
to rails...@googlegroups.com
On Wed, Aug 6, 2008 at 12:49 PM, Sven Fuchs <sven...@artweb-design.de> wrote:
> Agree with whom? Nobody said it's a triviality, or did I? C'mon.

sorry - I don't mean to come across as mean - just being direct :)
i do greatly appreciate all the work this group has been doing

So the main problem is allowing calls to I18N.t to be wrapped in other
functions. Unless there is a good and strong objection to it, I would
suggest making this a convention. Then someone can write a parser to
extract keys automatically and it will solve the issue for everyone.

Your right, it cannot be enforced programatically but nevertheless key
extraction is useful.

I don't see why I18N.t calls should be wrapped, anyway.

ry

Sven Fuchs

unread,
Aug 6, 2008, 7:59:49 AM8/6/08
to rails...@googlegroups.com
On 06.08.2008, at 13:25, ry dahl wrote:
> On Wed, Aug 6, 2008 at 12:49 PM, Sven Fuchs <sven...@artweb-design.de
> > wrote:
>> Agree with whom? Nobody said it's a triviality, or did I? C'mon.
> sorry - I don't mean to come across as mean - just being direct :)

no problem :)

> i do greatly appreciate all the work this group has been doing
>
> So the main problem is allowing calls to I18N.t to be wrapped in other
> functions. Unless there is a good and strong objection to it, I would
> suggest making this a convention.

So what would be the scope of the convention? Rails core? All plugins?
Or just: everything that wants to be compatible with the scraper tool?

I see no problem with the latter at all, except of course, there's no
scraper, yet :D

There might be problems with plugins (depending on what they're trying
to solve). And with regards to Rails core I'm pretty sure there are a
couple of places where you could not implement this convention. Maybe
that's wrong though and just results from my limited experience with
the convention.

So, I guess, before we could agree on the convention somebody would
need to look at Rails core, check if it's a possible thing to do and
propose changes if applicable.

?

> Then someone can write a parser to
> extract keys automatically and it will solve the issue for everyone.
>
> Your right, it cannot be enforced programatically but nevertheless key
> extraction is useful.
>
> I don't see why I18N.t calls should be wrapped, anyway.

You gave the following example and said this should not be used:

def my_translation_function(str)
t(str)
end
my_translation_function("hello world")

You also said that:

> Gettext explicitly requires you to your strings inside _( ) so that
> the parser could extract them from the source code

and

> I18N.t cannot be wrapped in functions it must be used
> directly on strings.


So we also can't do:

scope = 'ActiveRecord.error_messages'
msg = 'too_long'
I18n.t :"{scope}.#{msg}"

Right?

I guess this limitation could pose quite some problems on the Rails
libraries and maybe plugins.

E.g. ActiveRecord validations look up dynamically defined keys of
course. Another example are translations for column names.

How would these things be looked up then in order to work with the
scraper?

glennpow

unread,
Aug 7, 2008, 5:55:12 AM8/7/08
to rails-i18n
Iain,
one more suggestion for the plugin. Perhaps a way to turn off the
missing.yml functionality. I don't really like to get an error
message every time a missing translation is found. I'd rather just
see the page normally (with the standard I18n missing strings placed
where needed)
Could this be possible through an initializer or config?

On Aug 4, 5:34 pm, glennpow <glenn...@gmail.com> wrote:

Iain Hecker

unread,
Aug 7, 2008, 6:03:07 AM8/7/08
to rails...@googlegroups.com
That is already the default behaviour. After writing missing.yml, it
calls the default error handling method. But turning it off might be a
good point. Especially when in production mode ;)

glennpow

unread,
Aug 7, 2008, 11:35:38 AM8/7/08
to rails-i18n
Yes sorry, I didn't explain above how I get the error. If the
missing.yml file is.. er.. missing :) then the plugin coughs up an
error. Perhaps the plugin could just look to see if the file exists.
If it does, go ahead and write to it. If not, just move on.

iain

unread,
Aug 7, 2008, 5:24:11 PM8/7/08
to rails-i18n
I think I fixed it now. I was using a linux/mac shortcut by running
the 'touch' command directly. If you are running windows then it
wouldn't work. Hopefully this fixes it. If not, can you send me the
entire stacktrace?

Anyway, writing to missing is now turned off by default. Turn it on by
saying this somewhere: I18n.record_missing_keys_to_file =
bool_or_string. If you pass a boolean (or anything but nil or false)
it will write to missing.yml. If you pass a string, it specifies which
file to write to.

Added a whole bunch of updates tonight for i18n_yaml. I updated the
translation files and I am now a bit more sure that it is fairly
complete. Also fixed a few other bugs.

Thank everyone for testing. Hope to get more feedback.

One tiny request of which I'm a bit embarrassed. In lib/i18n_yaml.rb I
have a method which makes my eyes bleed. Does anyone have a better
solution for this? I need to get [ :one, :two, :three ] into { :one =>
{ :two => { :three => nil } } }. The solution I know use makes
children cry and adults run away.


Iain
Reply all
Reply to author
Forward
0 new messages