/myapp
/myapp/lang
/myapp/lang/en
/myapp/lang/en/en.yml
/myapp/lang/en/en_about.yml
/myapp/lang/en/en_app.yml
/myapp/lang/is/is.yml
/myapp/lang/is/is_about.yml
/myapp/lang/is/is_app.yml
## /myapp/config/environment.rb
I18n.default_locale = "en"
LOCALES_DIRECTORY = "#{RAILS_ROOT}/lang/"
LOCALES_AVAILABLE = Dir["#{LOCALES_DIRECTORY}/*/*.yml"].collect do |locale_file|
File.basename(locale_file, ".yml")
end.uniq
## /myapp/app/controllers/application.rb
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] if params[:locale]
end
## /myapp/app/helpers/application_helper.rb
def t(*args)
translate(*args)
end
## /myapp/app/views/admin/preferences/edit.html.erb
<%= f.label "locale", t(:"locale") %><%= f.select("locale",
options_for_select(LOCALES_AVAILABLE, I18n.locale) %>
You're missing a few parts. First is the loading of the files into
I18n. Put this into your environment:
I18n.load_translations(*Dir.glob(LOCALES_DIRECTORY+'/**/*.yml'))
look here how to get available_locales:
http://rails-i18n.org/wiki/pages/i18n-available_locales (put it in an
initializer)
Secondly, you need to set the proper locale at every request, so in
your before_filter you need to default to the locale stored in the
user's session or from preferences stored in the database.
def set_locale
I18n.locale = params[:locale] or session[:locale] or I18n.default_locale
session[:locale] = I18n.locale
end
Hope this helps,
Iain
Thanks a lot man for this wonderful advice. I'll give it a go and report back.
Maybe it's just me but isn't module Backend in
http://rails-i18n.org/wiki/pages/i18n-available_locales missing an
end?
The other option is using the hostname (i.e. a subdomain), but you're
not always able to use this (if you're not the only website on one
domain or if you're using https with a valid certificate).
I'd love to hear some advice.
What seems to me an elegant solution is some routes work:
map.with_options :path_prefix => '/:locale' do |localized|
localized.resources :projects
end
It seems nice, but how to fill the locale with the currently selected
locale? I don't like to do this all the time: projects_path(:locale =>
I18n.locale)
Rails seems to have an answer to it, called default_url_options[1],
but it doesn't seem to work. I've overwritten the method like the api
tells me, but somehow it is ignored into generating the path. It is
called, because it will break if I raise somthing in it. The options
passed to it are what you'd expect (containing all the parameters
you'd pass to url_for)
Here's my method:
def default_url_options(options = {})
{ :locale => I18n.locale }
end
While typing this message I found something perculiar. It only happens
with new_post_path and posts_path in my own little example (without
the route described above).
I have a scaffolded view and when in index the edit/delete and show
links all get the parameter properly, but not the new and index links.
Why not those two? The only difference I found between those two and
the rest is that new and index don't use params[:id].
Furthermore, I found that if I use the route I specified above, the
post object gets assigned to the locale-param. This results in an
error like:
edit_post_url failed to generate from {:action=>"edit",
:locale=>#<Post id: 1, title: "Foo", etc...
What is going on?
[1] http://api.rubyonrails.com/classes/ActionController/Base.html#M000851
<shameless-self-promotion>
http://github.com/raul/translate_routes/tree/master
</shameless-self-promotion>
--
Raul Murciano - Freelance Web Developer
http://raul.murciano.net
How? Like this?
def set_locale
I18n.locale = params[:locale] if params[:locale]
end
I wanted to say:
> On 03.10.2008, at 14:51, Karel Minarik wrote:
>> *please* don't advise people to use `session` for setting locale!
>> That
I agree.
>> is an unfortunate choice by the official i18n demo app and completely
>> breaks RESTfullnes of anything.
Which one? where? something we need to correct?
sessions are not restful by the definition of rest :)
Storing a locale in the session of a client means that state is stored
on the clientside. The simple test for this aspect of rest probably
is: if you can copy and paste the URL to an email, send it off to a
buddy and be sure that your buddy will see the same page as you're
looking at ... then that's ok. If he sees a different page, it's not.
To me displaying a page in an entirely different language means that
it's a "different" page, so I agree with Karel that we definitely
should not advise peopel to use the session for this.
Instead, use subdomains, parts of the path or even query params for
that. Even though it's more work or might look ugly, it does not break
the internet ;)
As for the "more work" part, when it comes to locales as path
segments: that's a question of better support in Rails. Raul already
plugged his solution, so lemme add mine:
<shameless-self-promotion>
http://github.com/svenfuchs/routing-filter
</shameless-self-promotion>
Also:
1. Will I (in Preferences#edit) be able to choose locale from a select
box, like in Clemens Kofler's demo? I don't think I need any of that
URL stuff. I just want it plain and simple, one language only.
2. Is the organization of my locales proper? Or must en.yml,
en_about.yml and en_app.yml be put into a single file for the
Preferences#edit select box to work?
The following is also available at http://pastie.org/286698
/myapp
/myapp/app/controllers/application.rb
/myapp/app/helpers/application_helper.rb
/myapp/app/views/admin/preferences/edit.html.erb
/myapp/config/environment.rb
/myapp/config/initializers/i18n.rb
/myapp/lang
/myapp/lang/en
/myapp/lang/en/en.yml
/myapp/lang/en/en_about.yml
/myapp/lang/en/en_app.yml
/myapp/lang/is/is.yml
/myapp/lang/is/is_about.yml
/myapp/lang/is/is_app.yml
## /myapp/config/environment.rb
I18n.load_path = RAILS_ROOT + "/lang"
I18n.default_locale = "en"
## /myapp/config/initializers/i18n.rb
module I18n
class << self
def available_locales
backend.available_locales
end
end
module Backend
class Simple
def available_locales
translations.keys
end
end
end
end
## /myapp/app/controllers/application.rb
before_filter :set_locale
def set_locale
I18n.locale = extract_locale_from_params || "en"
end
## /myapp/app/helpers/application_helper.rb
def t(*args)
translate(*args)
end
## /myapp/app/views/admin/preferences/edit.html.erb
<%= f.label "locale", t(:"locale") %><%= f.select("locale",
options_for_select(I18n.available_locales) %>