Solution to prefixing urls with /:locale without collisions

240 views
Skip to first unread message

Chack

unread,
Apr 2, 2011, 2:47:31 AM4/2/11
to I18n Routing
Hello again,

First thanks for the great gem. I've been playing around for a while
to figure out how to prefix urls with the locale. In generally this is
very easy to accomplish via scoping like this:

#routes.rb
Multilang::Application.routes.draw do
localized(I18n.available_locales, :verbose => true) do
scope "/:locale", :locale => /#{I18n.available_locales.join('|')}/
do
match "/asdf" => 'home#asdf', :as => :asdf
match "/abcd" => 'home#abcd', :as => :abcd
root :to => 'home#index'
end
end
end

However, this can lead to routing conflicts when a route can have
different meanings depending on your locale. Imagine some language xy
translating 'asdf' to 'word', and language yz translating 'abcd' to
'word' also. Now /xz/word will as well point to home#asdf since the
translation allows to use the locale across all language prefixes.

However I found a solution to this problem i want to share with you :)
It doesnt even require monkey patching anything. Since this gem sets
the i18n_locale constraint, we can just use that instead in our
routing.

localized(I18n.available_locales, :verbose => true) do
scope "/:i18n_locale", :constraints => {:i18n_locale => /
#{I18n.available_locales.join('|')}/} do
match "/asdf" => 'home#asdf', :as => :asdf
match "/abcd" => 'home#abcd', :as => :abcd
root :to => 'home#index'
end
end

Now, since i18n_routing internally set the constraint to the locale, /
xy/word and /yz/word can be used independently and no longer conflict.
Obviously you also have to make according changes in your
application_controller like this:

#application_controller.rb

before_filter :set_locale

def set_locale
I18n.locale = params[:i18n_locale]
end

def default_url_options(options={})
logger.debug "default_url_options is passed options:
#{options.inspect}\n"
{ :i18n_locale => I18n.locale }
end

Maybe this should be added to the wiki pages? :)

Guillaume Luccisano

unread,
Apr 4, 2011, 10:39:31 PM4/4/11
to i18n-r...@googlegroups.com
Thanks for sharing this tips Chack.
I plan to find some time, hopefully next week, to work again on the gem.
I will add your advice in the wiki at that time.

Cheers !

2011/4/1 Chack <ch...@clan-fwd.com>
Message has been deleted

opetznick

unread,
May 17, 2011, 5:10:29 AM5/17/11
to I18n Routing
for those who need a redirect based on HTTP_ACCEPT_LANGUAGE:

#home_controller.rb
class HomeController < ApplicationController

def choose_language
accept_language = request.env["HTTP_ACCEPT_LANGUAGE"]
accept_language = accept_language[0..1].to_sym unless
accept_language.blank?
locale = I18n.default_locale
locale = I18n.locale = accept_language if not
accept_language.blank? and I18n.available_locales.include?
accept_language
redirect_to root_path(locale)
end

end

#routes.rb
match "/" => "home#choose_language"
Reply all
Reply to author
Forward
Message has been deleted
0 new messages