Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
## Storing the locale in the URL without having to pass it into resource helpers Goal: article_path(@article) #=> /en/article/1 ## Overriding define_url_helper All I did was add one line to this method. I have placed this code in my environment.rb file. I know there is a cleaner way, but I'm just testing this for now. This should get some ideas going. module ActionController module Routing class RouteSet class NamedRouteCollection def define_url_helper(route, name, kind, options) selector = url_helper_name(name, kind) # The segment keys used for positional paramters segment_keys = route.segments.collect do |segment| segment.key if segment.respond_to? :key end.compact hash_access_method = hash_access_name(name, kind) @module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks def #{selector}(*args) !! #{'args << { :locale => @current_locale }' if segment_keys.include?(:locale)} opts = if args.empty? || Hash === args.first args.first || {} else args.zip(#{segment_keys.inspect}).inject({}) do |h, (v, k)| h[k] = v h end end url_for(#{hash_access_method}(opts)) end end_eval @module.send(:protected, selector) helpers << selector end end end end end ## The Application Controller - Setting the @current_locale before_filter :set_locale def set_locale default_locale = 'en-US' request_language = request.env['HTTP_ACCEPT_LANGUAGE'] request_language = request_language.nil? ? nil : request_language[/[^,;]+/] @current_locale = params[:locale] || session[:locale] || request_language || default_locale session[:locale] = @current_locale begin Locale.set @current_locale rescue Locale.set default_locale end end private :set_locale ## The routes map.index ':locale', :controller => 'general', :locale => 'en-US' map.hello ':locale/admin', :controller => 'general', :action => 'admin' map.connect 'test', :controller => 'general', :action => 'test' map.resources :features map.resources :articles, :path_prefix => ":locale" # Install the default route as the lowest priority. map.connect ':locale/:controller/:action/:id.:format' map.connect ':locale/:controller/:action/:id' # You can also define another set of default routes for when the locale is not in the params map.connect ':controller/:action/:id.:format' map.connect ':controller/:action/:id' ## The Result Assuming params[:locale] = 'en' and params[:controller] => 'general' link_to 'Articles', articles_path #=> /en/articles link_to 'Articles', articles_path(:locale => 'fr') #=> /fr/articles link_to 'Features', features_path #=> /features link_to 'Home', index_url #=> / link_to 'Home', index_url(:locale => 'fr') #=> /fr link_to 'Test', :action => 'test' #=> /en/general/test # The only caveat that I've found so far is that you need to specify the controller when trying to change the locale without a named route link_to 'Always French', :controller => 'general', :action => 'french', :locale => 'fr' # This returns an error that I haven't had time to investigate. Be my guest. :) link_to 'Always French', :action => 'french', :locale => 'fr'
This paste will be private.
From the Design Piracy series on my blog: