Skip to content
This repository
Browse code

Finished section "Setting locale from the URL params" in i18n guide (…

…+ various typos/formatting fixes)
  • Loading branch information...
commit 6cd4fed61303426dbaf8cfa20c9c7738ea5e7305 1 parent 97d9585
Karel Minarik karmi authored

Showing 1 changed file with 54 additions and 10 deletions. Show diff stats Hide diff stats

  1. +54 10 railties/doc/guides/source/i18n.txt
64 railties/doc/guides/source/i18n.txt
@@ -123,7 +123,7 @@ If you want to translate your Rails application to a *single language other than
123 123
124 124 However, you would probably like to *provide support for more locales* in your application. In such case, you need to set and pass the locale between requests.
125 125
126   -WARNING: You may be tempted to store choosed locale in a _session_ or a _cookie_. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being http://en.wikipedia.org/wiki/Representational_State_Transfer[_RESTful_]. There may be some exceptions to this rule, which are discussed below.
  126 +WARNING: You may be tempted to store choosed locale in a _session_ or a _cookie_. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being http://en.wikipedia.org/wiki/Representational_State_Transfer[_RESTful_]. Read more about RESTful approach in http://www.infoq.com/articles/rest-introduction[Stefan Tilkov's articles]. There may be some exceptions to this rule, which are discussed below.
127 127
128 128 The _setting part_ is easy. You can set locale in a +before_filter+ in the ApplicationController like this:
129 129
@@ -132,11 +132,11 @@ The _setting part_ is easy. You can set locale in a +before_filter+ in the Appli
132 132 before_filter :set_locale
133 133 def set_locale
134 134 # if params[:locale] is nil then I18n.default_locale will be used
135   - I18n.locale = params[:locale]
  135 + I18n.locale = params[:locale]
136 136 end
137 137 -------------------------------------------------------
138 138
139   -This requires you to pass the locale as a URL query parameter as in +http://example.com/books?locale=pt+. (This is eg. Google's approach). So +http://localhost:3000?locale=pt+ will load the Portugese localization, whereas +http://localhost:3000?locale=de+ would load the German localization, and so on.
  139 +This requires you to pass the locale as a URL query parameter as in +http://example.com/books?locale=pt+. (This is eg. Google's approach). So +http://localhost:3000?locale=pt+ will load the Portugese localization, whereas +http://localhost:3000?locale=de+ would load the German localization, and so on. You may skip the next section and head over to the *Internationalize your application* section, if you want to try things out by manually placing locale in the URL and reloading the page.
140 140
141 141 Of course, you probably don't want to manually include locale in every URL all over your application, or want the URLs look differently, eg. the usual +http://example.com/pt/books+ versus +http://example.com/en/books+. Let's discuss the different options you have.
142 142
@@ -179,7 +179,7 @@ end
179 179
180 180 === Setting locale from the domain name
181 181
182   -One option you have is to set the locale from the domain name, where your application runs. For example, we want +www.example.com+ to load English (or default) locale, and +www.example.es+ to load Spanish locale. Thus the _top-level domain name_ is used for locale setting. This has several advantages:
  182 +One option you have is to set the locale from the domain name where your application runs. For example, we want +www.example.com+ to load English (or default) locale, and +www.example.es+ to load Spanish locale. Thus the _top-level domain name_ is used for locale setting. This has several advantages:
183 183
184 184 * Locale is an _obvious_ part of the URL
185 185 * People intuitively grasp in which language the content will be displayed
@@ -233,14 +233,58 @@ This solution has aforementioned advantages, however, you may not be able or may
233 233
234 234 === Setting locale from the URL params
235 235
236   -* TODO : Based on *+default_url options+*, http://github.com/karmi/test_default_url_options/blob/master/app/controllers/application.rb#L22-26
  236 +Most usual way of setting (and passing) the locale would be to include it in URL params, as we did in the +I18n.locale = params[:locale]+ _before_filter_ in the first example. We would like to have URLs like +www.example.com/books?locale=ja+ or +www.example.com/ja/books+ in this case.
237 237
238   -* TODO : Discussion of plugins (translate_routes and routing_filter)
  238 +This approach has almost the same set of advantages as setting the locale from domain name: namely that it's RESTful and in accord with rest of the World Wide Web. It does require a little bit more work to implement, though.
239 239
  240 +Getting the locale from +params+ and setting it accordingly is not hard; including it in every URL and thus *passing it through the requests* is. To include an explicit option in every URL (eg. +link_to( books_url(:locale => I18n.locale) )+) would be tedious and probably impossible, of course.
240 241
241   -TIP: For setting locale from URL see http://rails-i18n.org/wiki/pages/how-to-encode-the-current-locale-in-the-url[How to encode the current locale in the URL] in the Rails i18n Wiki.
  242 +Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its http://api.rubyonrails.org/classes/ActionController/Base.html#M000515[+*ApplicationController#default_url_options*+], which is useful precisely in this scenario: it enables us to set "defaults" for http://api.rubyonrails.org/classes/ActionController/Base.html#M000503[+url_for+] and helper methods dependent on it (by implementing/overriding this method).
242 243
243   -Now you've initialized I18n support for your application and told it which locale should be used. With that in place you're now ready for the really interesting stuff.
  244 +We can include something like this in our ApplicationController then:
  245 +
  246 +[source, ruby]
  247 +-------------------------------------------------------
  248 +# app/controllers/application_controller.rb
  249 +def default_url_options(options={})
  250 + logger.debug "default_url_options is passed options: #{options.inspect}\n"
  251 + { :locale => I18n.locale }
  252 +end
  253 +-------------------------------------------------------
  254 +
  255 +Every helper method dependent on +url_for+ (eg. helpers for named routes like +root_path+ or +root_url+, resource routes like +books_path+ or +books_url+, etc.) will now *automatically include the locale in the query string*, like this: +http://localhost:3001/?locale=ja+.
  256 +
  257 +You may be satisfied with this. It does impact the readability of URLs, though, when the locale "hangs" at the end of every URL in your application. Moreover, from the architectural standpoint, locale is usually hierarchically above the other parts of application domain: and URLs should reflect this.
  258 +
  259 +You probably want URLs look like this: +www.example.com/en/books+ versus +www.example.com/nl/books+. This is achievable with the over-riding +default_url_options+ strategy: you just have to set up your routes with http://api.rubyonrails.org/classes/ActionController/Resources.html#M000354[+path_prefix+] option in this way:
  260 +
  261 +[source, ruby]
  262 +-------------------------------------------------------
  263 +# config/routes.rb
  264 +map.resources :books, :path_prefix => '/:locale'
  265 +-------------------------------------------------------
  266 +
  267 +Now, when you call +books_path+ method you should get +"/en/books"+ (for the default locale). An URL like +http://localhost:3001/nl/books+ should load the Netherlands locale, then, and so on.
  268 +
  269 +Of course, you need to take special care of root URL (usually "homepage" or "dashboard") of your application. An URL like +http://localhost:3001/nl+ will not work automatically, because the +map.root :controller => "dashboard"+ declaration in your +routes.rb+ doesn't take locale into account. (And rightly so. There's only one "root" URL.)
  270 +
  271 +You would probably need to map URLs like these:
  272 +
  273 +[source, ruby]
  274 +-------------------------------------------------------
  275 +# config/routes.rb
  276 +map.dashboard '/:locale', :controller => "dashboard"
  277 +-------------------------------------------------------
  278 +
  279 +Do take special care about the *order of your routes*, so this route declaration does not "eat" other ones. (You may want to add it directly before the +map.root+ declaration.)
  280 +
  281 +IMPORTANT: This solution has currently one rather big *downside*. Due to the _default_url_options_ implementation, you have to pass the +:id+ option explicitely, like this: +link_to 'Show', book_url(:id => book)+ and not depend on Rails' magic in code like +link_to 'Show', book+. If this should be a problem, have a look on two plugins which simplify working with routes in this way: Sven Fuchs's http://github.com/svenfuchs/routing-filter/tree/master[_routing_filter_] and Raul Murciano's http://github.com/raul/translate_routes/tree/master[_translate_routes_]. See also the page http://rails-i18n.org/wiki/pages/how-to-encode-the-current-locale-in-the-url[How to encode the current locale in the URL] in the Rails i18n Wiki.
  282 +
  283 +=== Setting locale from the client supplied information
  284 +
  285 +# TODO: Accept-Language, GeoIP, etc. Explain why it is not such a good idea in most cases.
  286 +
  287 +OK! Now you've initialized I18n support for your application and told it which locale should be used and how to preserve it between requests. With that in place you're now ready for the really interesting stuff.
244 288
245 289 == Internationalize your application
246 290
@@ -795,8 +839,8 @@ If you find your own locale (language) missing from our http://github.com/svenfu
795 839
796 840 == Authors
797 841
798   -* Sven Fuchs[http://www.workingwithrails.com/person/9963-sven-fuchs] (initial author)
799   -* Karel Minarik[http://www.workingwithrails.com/person/7476-karel-mina-k]
  842 +* http://www.workingwithrails.com/person/9963-sven-fuchs[Sven Fuchs] (initial author)
  843 +* http://www.workingwithrails.com/person/7476-karel-mina-k[Karel Minarik]
800 844
801 845 If you found this guide useful please consider recommending its authors on http://www.workingwithrails.com[workingwithrails].
802 846

0 comments on commit 6cd4fed

Please sign in to comment.
Something went wrong with that request. Please try again.