Reputation: 373
I'm trying out the internationalization of a Rails app with i18n. I did some small tests with 2 languages: english and french.
The problem I have is that i18n always translate to the default locale. So if it's english, everything will be in english, and the same with french.
Here is what I tried:
config/initializers/locales.rb
# Permitted locales available for the application
I18n.available_locales = [:en, :fr]
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def default_url_options
{ locale: I18n.locale }
end
end
config/application.rb
module LanguageApp
class Application < Rails::Application
...
config.i18n.load_path += Dir["#{Rails.root.to_s}/config/locales/**/*.{rb,yml}"]
config.i18n.default_locale = :en
# I change the default locale here to :fr or :en
end
end
config/routes.rb
root to: "home#index"
get '/:locale/about' => 'about#index'
get '/:locale' => 'home#index'
I organized my yml files like this:
config/locales/views/about/en.yml
en:
about: "This page is about us."
config/locales/views/about/fr.yml
fr:
about: "Cette page est à propos de nous."
config/locales/views/home/en.yml
en:
welcome: "Hello world"
config/locales/views/home/fr.yml
fr:
welcome: "Bonjour le monde"
And finally my views:
app/views/about/index.html.erb
About us page. <%= t(:about) %>
app/views/home/index.html.erb
This is the homepage. <%= t(:welcome) %>
I think the problem may come from the way I organized my yml files but I don't understand why i18n only translate to the default locale and 'ignore' the other language.
EDIT:
To try this out in the browser with the rails server running, I tried to visit these URL:
localhost:3000
localhost:3000/en
localhost:3000/fr
These 3 URL give me the same content, so the :fr locale doesn't actually work (it returns the same translation as :en)
Same for
localhost:3000/en/about
localhost:3000/fr/about
I also tried it in the rails console:
> I18n.t(:welcome, :en)
"Hello world"
> I18n.t(:welcome, :fr)
"Hello world"
Upvotes: 1
Views: 7391
Reputation: 102250
First set the locale for the request:
class ApplicationController < ActionController::Base
around_action :switch_locale
def switch_locale(&action)
I18n.with_locale(params[:locale] || I18n.default_locale, &action)
end
def default_url_options
{ locale: I18n.locale }
end
end
Don't use I18n.locale=
as many older answers / tutorials do.
I18n.locale can leak into subsequent requests served by the same thread/process if it is not consistently set in every controller. For example executing I18n.locale = :es in one POST requests will have effects for all later requests to controllers that don't set the locale, but only in that particular thread/process. For that reason, instead of I18n.locale = you can use I18n.with_locale which does not have this leak issue.
If you want to create translations for specific views you should nest the keys instead of just using flat hashes:
en:
home:
welcome: "Hello World"
fr:
home:
welcome: "Bonjour le monde"
And then use an implicit lookup in the view:
<h1><%= t('.welcome') %></h1>
This resolves the key to home.welcome
.
Upvotes: 2