How can I go about making my routes recognise an optional prefix parameter as follows:
/*lang/controller/id
In that the lang part is optional, and has a default value if it's not specified in the URL:
/en/posts/1 => lang = en /fr/posts/1 => lang = fr /posts/1 => lang = en
EDIT
Ideally, I'm looking to do this across many controllers and actions by mapping a namespace:
map.namespace "*lang" do |lang| lang.resources :posts lang.resources :stories end
Basically, you can use the ? character to make the parameter optional.
You use parenthesis ( ) to wrap the optional parts of route, including the leading slash ( / ). Check out the Route Matching Guide page of the official documentation. Note: The :paramName parameter matches a URL segment up to the next / , ? , or # . For more about paths and params specifically, read more here.
root 'topics#index' is a Rails route that says the default address for your site is topics#index . topics#index is the topics list page (the topics controller with the index action). Rails routes control how URLs (web addresses) get matched with code on the server.
OK, I've managed to sort out this problem:
THere is no way of doing this in Rails by default (at least, not yet). Instead of using namespaces and default values, I needed to install Sven Fuchs' routing filter.
Once the plugin is installed, I added the following file to my lib directory:
require 'routing_filter/base' module RoutingFilter class Locale < Base # remove the locale from the beginning of the path, pass the path # to the given block and set it to the resulting params hash def around_recognize(path, env, &block) locale = nil path.sub! %r(^/([a-zA-Z]{2})(?=/|$)) do locale = $1; '' end returning yield do |params| params[:locale] = locale || 'en' end end def around_generate(*args, &block) locale = args.extract_options!.delete(:locale) || 'en' returning yield do |result| if locale != 'en' result.sub!(%r(^(http.?://[^/]*)?(.*))){ "#{$1}/#{locale}#{$2}" } end end end end end
I added this line to routes.rb:
map.filter 'locale'
This basically fills out a before and after hook, generated by the plugin, that wraps the rails routing.
When a url is recognised, and before Rails gets to do anything with it, the around_recognize method is called. This will extract a two-letter code representing the locale, and pass it through in the params, defaulting to 'en' if no locale is specified.
Likewise, when a url is generated, the locale parameter will be pushed into the URL on the left side.
This gives me the following urls and mappings:
/ => :locale => 'en' /en => :locale => 'en' /fr => :locale => 'fr'
All existing url helpers work as before, with the only difference being that unless the locale is specified, it is preserved:
home_path => / home_path(:locale => 'en') => / home_path(:locale => 'fr') => /fr
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With