Merge pull request #4006 from scossar/set-locale-from-header
Feature: (WIP) Set locale from Accept-Language header
This commit is contained in:
commit
1135d2094a
2
Gemfile
2
Gemfile
|
@ -45,6 +45,8 @@ gem 'active_model_serializers', '~> 0.8.3'
|
|||
|
||||
gem 'onebox'
|
||||
|
||||
gem 'http_accept_language', '~>2.0.5'
|
||||
|
||||
gem 'ember-rails'
|
||||
gem 'ember-source', '1.12.2'
|
||||
gem 'barber'
|
||||
|
|
|
@ -127,6 +127,7 @@ GEM
|
|||
htmlentities (4.3.4)
|
||||
http-cookie (1.0.2)
|
||||
domain_name (~> 0.5)
|
||||
http_accept_language (2.0.5)
|
||||
i18n (0.7.0)
|
||||
image_optim (0.20.2)
|
||||
exifr (~> 1.1, >= 1.1.3)
|
||||
|
@ -426,6 +427,7 @@ DEPENDENCIES
|
|||
highline
|
||||
hiredis
|
||||
htmlentities
|
||||
http_accept_language (~> 2.0.5)
|
||||
image_optim (= 0.20.2)
|
||||
librarian (>= 0.0.25)
|
||||
listen (= 0.7.3)
|
||||
|
|
|
@ -164,7 +164,15 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def set_locale
|
||||
I18n.locale = current_user.try(:effective_locale) || SiteSetting.default_locale
|
||||
if !current_user
|
||||
if SiteSetting.allow_user_locale
|
||||
I18n.locale = locale_from_header
|
||||
else
|
||||
I18n.locale = SiteSetting.default_locale
|
||||
end
|
||||
else
|
||||
I18n.locale = current_user.effective_locale
|
||||
end
|
||||
I18n.ensure_all_loaded!
|
||||
end
|
||||
|
||||
|
@ -309,6 +317,18 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
private
|
||||
|
||||
def locale_from_header
|
||||
begin
|
||||
# Rails I18n uses underscores between the locale and the region; the request
|
||||
# headers use hyphens.
|
||||
available_locales = I18n.available_locales.map { |locale| locale.to_s.gsub(/_/, '-') }
|
||||
http_accept_language.language_region_compatible_from(available_locales).gsub(/-/, '_')
|
||||
rescue
|
||||
# If Accept-Language headers are not set.
|
||||
I18n.default_locale
|
||||
end
|
||||
end
|
||||
|
||||
def preload_anonymous_data
|
||||
store_preloaded("site", Site.json_for(guardian))
|
||||
store_preloaded("siteSettings", SiteSetting.client_settings_json)
|
||||
|
|
|
@ -715,7 +715,12 @@ class UsersController < ApplicationController
|
|||
|
||||
def user_params
|
||||
params.permit(:name, :email, :password, :username, :active)
|
||||
.merge(ip_address: request.remote_ip, registration_ip_address: request.remote_ip)
|
||||
.merge(ip_address: request.remote_ip, registration_ip_address: request.remote_ip,
|
||||
locale: user_locale)
|
||||
end
|
||||
|
||||
def user_locale
|
||||
I18n.locale
|
||||
end
|
||||
|
||||
def fail_with(key)
|
||||
|
|
|
@ -60,7 +60,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def rtl_class
|
||||
RTL.new(current_user).css_class
|
||||
rtl? ? 'rtl' : ''
|
||||
end
|
||||
|
||||
def escape_unicode(javascript)
|
||||
|
@ -111,7 +111,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def rtl?
|
||||
["ar", "fa_IR", "he"].include?(user_locale)
|
||||
["ar", "fa_IR", "he"].include? I18n.locale.to_s
|
||||
end
|
||||
|
||||
def user_locale
|
||||
|
|
|
@ -13,6 +13,10 @@ describe TopicsController do
|
|||
request.env['HTTP_REFERER'] = ref
|
||||
end
|
||||
|
||||
def set_accept_language(locale)
|
||||
request.env['HTTP_ACCEPT_LANGUAGE'] = locale
|
||||
end
|
||||
|
||||
it "doesn't store an incoming link when there's no referer" do
|
||||
expect {
|
||||
get :show, id: topic.id
|
||||
|
@ -33,7 +37,7 @@ describe TopicsController do
|
|||
end
|
||||
|
||||
it "uses the application layout even with an escaped fragment param" do
|
||||
get :show, {'topic_id' => topic.id, 'slug' => topic.slug, '_escaped_fragment_' => 'true'}
|
||||
get :show, {'topic_id' => topic.id, 'slug' => topic.slug, '_escaped_fragment_' => 'true'}
|
||||
expect(response).to render_template(layout: 'application')
|
||||
assert_select "meta[name=fragment]", false, "it doesn't have the meta tag"
|
||||
end
|
||||
|
@ -51,7 +55,7 @@ describe TopicsController do
|
|||
end
|
||||
|
||||
it "uses the crawler layout when there's an _escaped_fragment_ param" do
|
||||
get :show, topic_id: topic.id, slug: topic.slug, _escaped_fragment_: 'true'
|
||||
get :show, topic_id: topic.id, slug: topic.slug, _escaped_fragment_: 'true'
|
||||
expect(response).to render_template(layout: 'crawler')
|
||||
assert_select "meta[name=fragment]", false, "it doesn't have the meta tag"
|
||||
end
|
||||
|
@ -114,25 +118,87 @@ describe TopicsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'set_locale' do
|
||||
it 'sets the one the user prefers' do
|
||||
SiteSetting.stubs(:allow_user_locale).returns(true)
|
||||
describe "set_locale" do
|
||||
context "allow_user_locale disabled" do
|
||||
context "accept-language header differs from default locale" do
|
||||
before do
|
||||
SiteSetting.stubs(:allow_user_locale).returns(false)
|
||||
SiteSetting.stubs(:default_locale).returns("en")
|
||||
set_accept_language("fr")
|
||||
end
|
||||
|
||||
user = Fabricate(:user, locale: :fr)
|
||||
log_in_user(user)
|
||||
context "with an anonymous user" do
|
||||
it "uses the default locale" do
|
||||
get :show, {topic_id: topic.id}
|
||||
|
||||
get :show, {topic_id: topic.id}
|
||||
expect(I18n.locale).to eq(:en)
|
||||
end
|
||||
end
|
||||
|
||||
expect(I18n.locale).to eq(:fr)
|
||||
context "with a logged in user" do
|
||||
it "it uses the default locale" do
|
||||
user = Fabricate(:user, locale: :fr)
|
||||
log_in_user(user)
|
||||
|
||||
get :show, {topic_id: topic.id}
|
||||
|
||||
expect(I18n.locale).to eq(:en)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'is sets the default locale when the setting not enabled' do
|
||||
user = Fabricate(:user, locale: :fr)
|
||||
log_in_user(user)
|
||||
context "allow_user_locale enabled" do
|
||||
context "accept-language header differs from default locale" do
|
||||
before do
|
||||
SiteSetting.stubs(:allow_user_locale).returns(true)
|
||||
SiteSetting.stubs(:default_locale).returns("en")
|
||||
set_accept_language("fr")
|
||||
end
|
||||
|
||||
get :show, {topic_id: topic.id}
|
||||
context "with an anonymous user" do
|
||||
it "uses the locale from the headers" do
|
||||
get :show, {topic_id: topic.id}
|
||||
|
||||
expect(I18n.locale).to eq(:en)
|
||||
expect(I18n.locale).to eq(:fr)
|
||||
end
|
||||
end
|
||||
|
||||
context "with a logged in user" do
|
||||
it "uses the user's preferred locale" do
|
||||
user = Fabricate(:user, locale: :fr)
|
||||
log_in_user(user)
|
||||
|
||||
get :show, {topic_id: topic.id}
|
||||
|
||||
expect(I18n.locale).to eq(:fr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "the preferred locale includes a region" do
|
||||
it "returns the locale and region separated by an underscore" do
|
||||
SiteSetting.stubs(:allow_user_locale).returns(true)
|
||||
SiteSetting.stubs(:default_locale).returns("en")
|
||||
set_accept_language("zh-CN")
|
||||
|
||||
get :show, {topic_id: topic.id}
|
||||
|
||||
expect(I18n.locale).to eq(:zh_CN)
|
||||
end
|
||||
end
|
||||
|
||||
context 'accept-language header is not set' do
|
||||
it 'uses the site default locale' do
|
||||
SiteSetting.stubs(:allow_user_locale).returns(true)
|
||||
SiteSetting.stubs(:default_locale).returns('en')
|
||||
set_accept_language('')
|
||||
|
||||
get :show, {topic_id: topic.id}
|
||||
|
||||
expect(I18n.locale).to eq(:en)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -479,6 +479,15 @@ describe UsersController do
|
|||
email: @user.email
|
||||
end
|
||||
|
||||
context 'when creating a user' do
|
||||
it 'sets the user locale to I18n.locale' do
|
||||
SiteSetting.stubs(:default_locale).returns('en')
|
||||
I18n.stubs(:locale).returns(:fr)
|
||||
post_user
|
||||
expect(User.find_by(username: @user.username).locale).to eq('fr')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when creating a non active user (unconfirmed email)' do
|
||||
|
||||
it 'returns a 500 when local logins are disabled' do
|
||||
|
@ -1181,6 +1190,19 @@ describe UsersController do
|
|||
|
||||
end
|
||||
|
||||
context 'a locale is chosen that differs from I18n.locale' do
|
||||
it "updates the user's locale" do
|
||||
I18n.stubs(:locale).returns('fr')
|
||||
|
||||
put :update,
|
||||
username: user.username,
|
||||
locale: :fa_IR
|
||||
|
||||
expect(User.find_by(username: user.username).locale).to eq('fa_IR')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "with user fields" do
|
||||
context "an editable field" do
|
||||
let!(:user_field) { Fabricate(:user_field) }
|
||||
|
|
|
@ -84,5 +84,16 @@ describe ApplicationHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#rtl_class' do
|
||||
it "returns 'rtl' when the I18n.locale is rtl" do
|
||||
I18n.stubs(:locale).returns(:he)
|
||||
expect(helper.rtl_class).to eq('rtl')
|
||||
end
|
||||
|
||||
it 'returns an empty string when the I18n.locale is not rtl' do
|
||||
I18n.stubs(:locale).returns(:zh_TW)
|
||||
expect(helper.rtl_class).to eq('')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue