URL and routing consideration

7 views
Skip to first unread message

yannski

unread,
Sep 15, 2008, 8:51:16 AM9/15/08
to rails-i18n
Hi Folks,

I'm following with envy the current work being done in Rails 2.2
regarding i18n support.

However, I don't see anything on the subject of i18n of URLs
(especially important in case of SEO). By the past, I'd have to do
pretty ugly things to have something useful.

For example, I'd like to have things like :

/journaux/23-le-parisien routed to the controller "newpapers" with
params[:id] = "23-le-parisien" and the locale set to "fr" or "FR-fr"

whereas

/newspapers/23-le-parisien routed to the controller "newspapers" with
params[:id] = "23-le-parisien" and the locale set to "en" or "EN-en"

Maybe such things are more about l10n than i18n, but I thought I
should ask the question here...

Thanks in advance,

++

yk

iain hecker

unread,
Sep 15, 2008, 3:35:41 PM9/15/08
to rails-i18n
Hi,

Do you want to make a single language site or multiple languaged site.
If it's a single language site you want, it's quite easy to change
you're urls to something nicer, even in Rails 2.1 (and perhaps older),
when you're using REST.

In your routes, call

map.resources :newspapers, :as => 'journeaux'

which will translate the controller name for you.

If you want to change 'edit' and 'new', use this line in your
environment file:

config.action_controller.resources_path_names = { :new =>
'nieuw', :edit => 'aanpassen' }
I18n.locale = 'fr'

To change the id, use the to_param method in the model, like:

class Newspaper < ActiveRecord::Base
def to_param
"#{id}-#{name.gsub(/\W/,'-')}"
end
end

That should do the trick. If you're doing multiple languages each with
each own urls, you still have to jump through some hoops though...


Iain

Yann KLIS

unread,
Sep 15, 2008, 3:51:51 PM9/15/08
to rails...@googlegroups.com
Yeah of course, I'd really like to support multi-language webapp. But,
thanks for the tricks anyway (I used to do nasty things with Rails
1.2...).

++

yk

2008/9/15 iain hecker <ia...@iain.nl>:

Sven Fuchs

unread,
Sep 16, 2008, 6:48:26 AM9/16/08
to rails...@googlegroups.com
Hi Yann,

I've received a private email from somebody who told he that he
implemented URL translation as a plugin. I've asked him to register to
this mailinglist and introduce his plugin.

Kwi

unread,
Sep 16, 2008, 7:36:21 AM9/16/08
to rails-i18n
Hi people,

I am the Sven's secret mailer.
So I developed a personal globalize plugin in order to translate
named_routes and resources few months ago (This plugin do not set the
locale automatically, it's just focus on url translation).

I don't really like the way I did it, but It was my best idea at the
time (feel free to make some better suggestions)

First of all, you have to declare in your routes.rb wich route you
want to translate with the options :globalized, for example with the
map.with_options :

map.with_options :globalized => true do |m|
#build content routes
%w(how_to about help legal_notice partners privacy changelog).each
do |r|
m.send(r.to_sym, r, {:controller => 'contents', :action => r})
end

m.resources :registration
m.resources :users
end

Then i wrote a bunch of code that override methods : resource,
resources and add_named_route.
I modified the treatment in order to not just create the routes
specified, but to create routes for each languages supported, for
example :

map.resources :users will create routes : users, users_fr, users_en,
users_es, and so on... with a path translated by calling users.t()

Then i override the method define_url_helper wich is used internally
by rails routing to create helper for routes, and when you will call
users_path, the localized helper will be called, so if the french
locale is set, users_path will return the result of users_fr_path.

All of this is really tricky and make your "$>rake routes" ugly, but
that's working fine.


So that's all for the url translation plugin, I also developed a full
ajaxed and ergonomic interface for translating a website in an easy
way (with a "lazby boy" feature : auto translation help coming from
google translator). It's just composed of a css, a controller, views
and a model. If people are interested I can release that too.

Yann KLIS

unread,
Sep 17, 2008, 3:17:48 PM9/17/08
to rails...@googlegroups.com
Could you release the url translation plugin ? It could be good start
to look at.

++

yk

2008/9/16 Kwi <guillaume...@gmail.com>:

Redd Vinylene

unread,
Sep 18, 2008, 1:09:04 AM9/18/08
to rails...@googlegroups.com
On Wed, Sep 17, 2008 at 9:17 PM, Yann KLIS <yann...@gmail.com> wrote:

Could you release the url translation plugin ? It could be good start
to look at.

++

yk

Yeah, or put it in the globalize 2 demo / i18n demo apps :-)

This stuff is quite important right?

--
http://www.home.no/reddvinylene

Kwi

unread,
Sep 18, 2008, 4:42:04 AM9/18/08
to rails-i18n
Hi again

As I'm really busy currently and as I'm not really familiar with open
source and git hub, I don't really know what the right thing to do,
but I'm ok to integrate properly the plugin in gloablize2 when i find
the time if someone can take a little bit of his time to explain me
the right way to do that.

But if you are in a hurry, here follow my source code (It's working
fine on Rails2.1 and Globalize1), You just have to change the way I
iterate the supported languages (MkdGlobalize::Langs.each_key). Just
include the file and add :globalized => true option to your resource
and named_route, then run "rake routes" and watch the magic.


module ActionController
module Routing
class RouteSet #:nodoc:
class NamedRouteCollection #:nodoc:

alias_method :mkd_define_url_helper, :define_url_helper
def define_url_helper(route, name, kind, options)

mkd_define_url_helper(route, name, kind, options)

# globalization surcouche
if options[:globalized] or options[:globalized_p] or
options[:globalized_s]
selector = url_helper_name(name, kind)

# surcharge de l'helper
@module.module_eval <<-end_eval # We use module_eval to
avoid leaks
alias_method :gl#{selector}, :#{selector}

def #{selector}(*args)
selector_g = "\#{lang}_
\#{'#{selector}'.gsub('_#{kind}', '')}_#{kind}"

if respond_to? selector_g.to_sym and
selector_g.to_sym != :#{selector}
send(selector_g.to_sym, *args)
else
gl#{selector}(*args)
end
end
protected :gl#{selector}
end_eval

end
end
end

alias_method :gl_add_named_route, :add_named_route
def add_named_route(name, path, options = {}) #:nodoc:
gl_add_named_route(name, path, options)
return if !options[:globalized]

options.delete(:globalized)
name = name.to_s
MkdGlobalize::Langs.each_key do |l|
Globalize::Locale.set(l.to_s)
nt = "#{l}_#{name}"
if nt != name
gl_add_named_route(nt, path.to_s.t(nil, nil,
'named_routes_path'), options)
end
end
end

end
end
end

module ActionController
module Resources
alias_method :gl_resources, :resources
def resources(*entities, &block)
opts = entities.dup.extract_options!
gl_resources(*entities, &block)
return if !opts[:globalized]
name = entities.shift.to_s

opts[:controller] = name if !opts[:controller]

opts.delete(:globalized)
MkdGlobalize::Langs.each_key do |l|
Globalize::Locale.set(l.to_s)
nt = "#{l}_#{name}"#name.t(nil, nil, 'resources')
if nt != name
opts[:as] = name.t(nil, nil, 'resources')
gl_resources(nt.to_sym, opts, &block)
end
end
end

alias_method :gl_resource, :resource
def resource(*entities, &block)
opts = entities.dup.extract_options!
gl_resource(*entities, &block)
return if !opts[:globalized]
name = entities.shift.to_s

opts[:controller] = name if !opts[:controller]

opts.delete(:globalized)
MkdGlobalize::Langs.each_key do |l|
Globalize::Locale.set(l.to_s)
nt = "#{l}_#{name}"#name.t(nil, nil, 'resource')
if nt != name
opts[:as] = name.t(nil, nil, 'resource')
gl_resource(nt.to_sym, opts, &block)
end
end
end

private
def action_options_for(action, resource, method = nil)
default_options = { :action => action.to_s }
if resource.options[:globalized]
default_options[:globalized_p] = resource.plural
if resource.uncountable?
default_options[:globalized_p] = resource.plural.to_s +
'_index'
end
default_options[:globalized_s] = resource.singular
end
require_id = !resource.kind_of?(SingletonResource)
case default_options[:action]
when "index", "new";
default_options.merge(add_conditions_for(resource.conditions, method
|| :get)).merge(resource.requirements)
when "create";
default_options.merge(add_conditions_for(resource.conditions, method
|| :post)).merge(resource.requirements)
when "show", "edit";
default_options.merge(add_conditions_for(resource.conditions, method
|| :get)).merge(resource.requirements(require_id))
when "update";
default_options.merge(add_conditions_for(resource.conditions, method
|| :put)).merge(resource.requirements(require_id))
when "destroy";
default_options.merge(add_conditions_for(resource.conditions, method
|| :delete)).merge(resource.requirements(require_id))
else
default_options.merge(add_conditions_for(resource.conditions,
method)).merge(resource.requirements)
end
end
end
end

Raul Murciano

unread,
Sep 19, 2008, 8:08:17 PM9/19/08
to rails-i18n

Hi all,

This is my very first message on the list :)

yannski: maybe my translate_routes plugin could be useful on your
task:

http://github.com/raul/translate_routes/tree/master

The current status is as follows:
- it's been extracted from a real-world project and designed to be
simple to use and easy to configure
- translations can be provided with per-language hashes or YAML files,
so it doesn't mess your routing definitions with translation strings
- it transparently transforms your *_path and *_url helpers to the
current language to generate URLs accordingly
- beside the tutorial & configuration doc, it includes a sample
application so you can see how easily can be integrated on your app
- it's being used on commercial Rails 2.X applications with no
reported problems from Dec'07. 1 bug has been found and fixed, always
on development stage.
- it's free software
- the developer is always open to suggestions and extremely responsive
to bug reports and any kind of feedback :D

I'm pretty busy right now but I'd like to integrate it with the new
i18n stuff included in Rails 2.2.
If somebody checks it out I'll be glad to know your opinion, whatever
it is :)

Kind regards

--
Raul Murciano - Freelance Web Developer
http://raul.murciano.net
Reply all
Reply to author
Forward
0 new messages