Locale Selection Strategies in Rails Applications

TML SDK for Rails offers a number of ways for telling your Rails application about which language to use for rendering your views. You can use locale parameter, pre-path and pre-domain configurations and even provide custom domains for every language. This post will describe each approach and show you how to configure it in a Rails application using the TML for Rails gem.

Locale Parameter

This is the default and simplest way to tell your application which locale to use. If you don’t provide custom locale configuration, this approach will be used out of the box.

[ruby title=”app/config/initializers/tml.rb” class=”lang:ruby”]
Tml.configure do |config|

config.locale = {
default: ‘en’,
strategy: ‘param’,
param: ‘locale’,
cookie: true
}

end
[/ruby]

You can customize the parameter name and indicate if you want to store the locale in the cookie. Although we offer cookie support, we recommend passing the locale in every url. So in case your users want to share the URL with anyone, the language will be passed with the URL itself.

To pass the locale in every URL, simply add default_url_options to your application controller as in the following example:

[ruby title=”app/controllers/application_controller.rb” class=”lang:ruby”>
def default_url_options
{ Tml.config.locale_param => tml_current_locale }
end
[/ruby]

And any url you define using url_for method will automatically include the locale parameter.

http://myapp.com/?locale=en
http://myapp.com/welcome?locale=ru

A better and a cleaner approach is to pass the locale as a pre-path fragment.

Pre-Path

This approach seems to pickup more popularity over other options. It is SEO friendly and does not pollute your URLs with an extra locale parameter.

http://myapp.com/en
http://myapp.com/ru/welcome

You should create a sitemap file that would point to all your pages using all locales so the search engines can index all your multi-lingual content.

To configure pre-path settings, change the locale mode in the TML init file:

[ruby title=”app/config/initializers/tml.rb” class=”lang:ruby”]
Tml.configure do |config|

config.locale = {
default: ‘en’,
strategy: ‘pre-path’,
param: ‘locale’
}

end
[/ruby]

Now you need to surround all your routes with a locale scope:

[ruby title=”app/controllers/application_controller.rb” class=”lang:ruby”]
Rails.application.routes.draw do

# make sure you have a default path outside of the scope to capture your root url
get “/:#{Tml.config.locale_param}” => ‘controller#action’

scope “(:#{Tml.config.locale_param})” do
root ‘controller#action’

# all your routes go here

end

end
[/ruby]

If you want your default language not to appear in the URL path, you can add a “skip_default” parameter to the locale configuration.

[ruby title=”app/config/initializers/tml.rb” class=”lang:ruby”]
Tml.configure do |config|

config.locale = {
default: ‘en’,
strategy: ‘pre-path’,
param: ‘locale’,
skip_default: true

}

end
[/ruby]

The library will handle all the automatic redirections for you. For instance, if user has Russian as the default locale in the browser, then visiting:

http://myapp.com

will automatically redirect the user to:

http://myapp.com/ru

If you want to handle redirection yourself, then add a “redirect” parameter and set it to false. In this case you should check the tml_current_locale in your before_filter method and perform any redirections that you need.

Pre-Domain

This approach is similar to the pre-path method, but instead of using path fragments it uses the first element of the subdomain.

http://en.lvh.me
http://ru.lvh.me/welcome

To make this approach work, change the locale strategy in the TML init file:

[ruby title=”app/config/initializers/tml.rb” class=”lang:ruby”]
Tml.configure do |config|

config.domain = ‘lvh.me’,
config.locale = {
default: ‘en’,
strategy: ‘pre-domain’
}

end
[/ruby]

You will need to configure your subdomains to share cookies. This can be done in your session store:

[ruby title=”app/config/initializers/session_store.rb” class=”lang:ruby”]
Rails.application.config.session_store(:cookie_store, {
key: “_session”,
domain: :all,
secure: %w(production staging).include?(Rails.env.to_s),
httponly: true,
expire_after: 24.hours
})
[/ruby]

By settings “domain” to “all”, your cookies will be shared and accessible by all your subdomains.

Similarly to the pre-path approach, you can specify if you want the user to be redirect to the appropriate locale. For example, if user navigates to your main site, but the user’s browser preferred locale is set to a supported non-default language, the user will be navigated to the appropriate subdomain.

Custom Domains

If you prefer to use TLDs or completely custom domains for different languages, you can use the custom-domain strategy.

[ruby title=”app/config/initializers/tml.rb” class=”lang:ruby”]
Tml.configure do |config|

config.locale = {
default: ‘en’,
strategy: ‘custom-domain’,
mapping: {
‘en’ => ‘my-en.lvh.me’,
‘ru’ => ‘my-ru.lvh.me’,
‘ko’ => ‘my-ko.lvh.me’
}
}

end
[/ruby]

Simply map your domains for every locale, and the language will be selected for you automatically.

User Selected Locale

On top of all the selected strategies, you may want to store locale selection per user. You can customize the TML library to handle that as well.

For any of the above strategy, simply add:

[ruby title=”app/config/initializers/tml.rb” class=”lang:ruby”]
Tml.configure do |config|

config.locale = {

method: ‘current_locale’

}

end
[/ruby]

And define the method in your ApplicationController, as in the following example:

[ruby title=”app/controllers/application_controller.rb” class=”lang:ruby”]

def current_locale
current_user.locale
end

[/ruby]

Now any time you store the locale in your user’s account, that locale will automatically be used and the user will be redirected to the appropriate URL.

You would also need to make sure to store the new locale once user changes it. You can do that in a “before_filter” method as well.

[ruby title=”app/controllers/application_controller.rb” class=”lang:ruby”]

before_filter :update_user_locale

def update_user_locale
if params[Tml.config.locale_param]
current_user.update_attributes(locale: params[Tml.config.locale_param])
end
end

[/ruby]

If you have any questions, please don’t hesitate to contact us.

Get Started Today!

Create an account to get started now! No credit card required.

Get Started