I am adding I18N to my rails application by passing the locale using url params. My urls are looking like http://example.com/en/users and http://example.com/ar/users (for th
You can parse request_uri, and replace your locale in the path with regular expression
Ok, here is helper example. If I correctly understand the goal
def locale_url(url, locale)
url.gsub(/\/\w*$/, "/#{locale}")
end
url = "http://www.domain.com/products/1/ru" # or request.request_uri
locale = "en"
locale_url(url, locale) #=> "http://www.domain.com/products/1/en"
This is a start point, so you can make some different stuff that you need
You can safely use url_for
to switch locales with url params
if you set only_path: true
:
<%= link_to I18n.t('language_name', locale: I18n.locale), url_for( params.clone.permit!.merge(locale: locale, only_path: true ) %>
We .clone
the params
before permitting them all (.permit!
), to preserve strong parameters elsewhere. The only more secure solution I could find would be to time consumingly whitelist all params instead...
Robust I18n implementation:
Add a locales.rb
initializer to define what I18n.available_locales
you support:
# config/initializers/locales.rb
# Permitted locales available for the application
I18n.available_locales = [:en, :fr]
Set a language_name
value in each language's locale file (e.g. fr.yml
):
fr:
language_name: "Français"
As you add more languages, this ERB will let you generically switch between them:
// app/views/layouts/_languages.html.erb
<span class="languages">
<% I18n.available_locales.each do |locale| %>
<% if I18n.locale == locale %>
<%= link_to I18n.t('language_name', locale: locale), url_for( params.clone.permit!.merge(locale: locale, only_path: true ), {style: "display:none" } %>
<% else %>
<%= link_to I18n.t('language_name', locale: locale), url_for( params.clone.permit!.merge(locale: locale, only_path: true ) %>
<% end %>
<% end %>
</span>
For the controller, we automatically find the correct language for the user by detecting their browser's Accept-Language
HTTP header (using the http_accept_language gem).
Set a session
cookie to preserve locale across requests.
Or optionally, use default_url_options
to insert the ?locale=
param into your app's url. I do both.
Controller:
class ApplicationController < ActionController::Base
before_action :set_locale
private
def set_locale
I18n.locale = begin
extract_locale ||
session[:locale] ||
http_accept_language.compatible_language_from(I18n.available_locales) ||
I18n.default_locale
end
session[:locale] = I18n.locale
end
def extract_locale
parsed_locale = params[:locale].dup
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
def default_url_options
{ locale: I18n.locale }
end
end