FEATURE: new site setting to set locale from cookie for anonymous users. (#18377)

This new hidden default-disabled site setting `set_locale_from_cookie` will set locale from anonymous user's cookie value.
This commit is contained in:
Vinoth Kannan 2022-09-27 14:26:06 +05:30 committed by GitHub
parent 0b6c89dc62
commit 076abe46fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 12 deletions

View File

@ -400,11 +400,8 @@ class ApplicationController < ActionController::Base
if check_current_user && (user = current_user rescue nil) if check_current_user && (user = current_user rescue nil)
locale = user.effective_locale locale = user.effective_locale
else else
if SiteSetting.set_locale_from_accept_language_header locale = Discourse.anonymous_locale(request)
locale = locale_from_header locale ||= SiteSetting.default_locale
else
locale = SiteSetting.default_locale
end
end end
if !I18n.locale_available?(locale) if !I18n.locale_available?(locale)
@ -624,10 +621,6 @@ class ApplicationController < ActionController::Base
private private
def locale_from_header
HttpLanguageParser.parse(request.env["HTTP_ACCEPT_LANGUAGE"])
end
def preload_anonymous_data def preload_anonymous_data
store_preloaded("site", Site.json_for(guardian)) store_preloaded("site", Site.json_for(guardian))
store_preloaded("siteSettings", SiteSetting.client_settings_json) store_preloaded("siteSettings", SiteSetting.client_settings_json)

View File

@ -123,6 +123,11 @@ basic:
default: false default: false
client: true client: true
validator: "AllowUserLocaleEnabledValidator" validator: "AllowUserLocaleEnabledValidator"
set_locale_from_cookie:
default: false
hidden: true
client: true
validator: "AllowUserLocaleEnabledValidator"
support_mixed_text_direction: support_mixed_text_direction:
client: true client: true
default: false default: false

View File

@ -1085,4 +1085,10 @@ module Discourse
Theme.all.each(&:update_javascript_cache!) Theme.all.each(&:update_javascript_cache!)
Theme.expire_site_cache! Theme.expire_site_cache!
end end
def self.anonymous_locale(request)
locale = HttpLanguageParser.parse(request.cookies["locale"]) if SiteSetting.set_locale_from_cookie
locale ||= HttpLanguageParser.parse(request.env["HTTP_ACCEPT_LANGUAGE"]) if SiteSetting.set_locale_from_accept_language_header
locale
end
end end

View File

@ -100,8 +100,8 @@ module Middleware
end end
def key_locale def key_locale
if SiteSetting.set_locale_from_accept_language_header if locale = Discourse.anonymous_locale(@request)
HttpLanguageParser.parse(@env["HTTP_ACCEPT_LANGUAGE"]) locale
else else
"" # No need to key, it is the same for all anon users "" # No need to key, it is the same for all anon users
end end

View File

@ -53,7 +53,7 @@ RSpec.describe Middleware::AnonymousCache do
end end
end end
context "with header-based locale locale" do context "with header or cookie based custom locale" do
it "handles different languages" do it "handles different languages" do
# Normally does not check the language header # Normally does not check the language header
french1 = new_helper("HTTP_ACCEPT_LANGUAGE" => "fr").cache_key french1 = new_helper("HTTP_ACCEPT_LANGUAGE" => "fr").cache_key
@ -76,6 +76,9 @@ RSpec.describe Middleware::AnonymousCache do
expect(none).to eq(english) expect(none).to eq(english)
expect(french1).to eq(french2) expect(french1).to eq(french2)
expect(french1).not_to eq(none) expect(french1).not_to eq(none)
SiteSetting.set_locale_from_cookie = true
expect(new_helper("HTTP_COOKIE" => "locale=es;").cache_key).to include("l=es")
end end
end end

View File

@ -895,6 +895,44 @@ RSpec.describe ApplicationController do
end end
end end
end end
context "with set_locale_from_cookie enabled" do
context "when cookie locale differs from default locale" do
before do
SiteSetting.allow_user_locale = true
SiteSetting.set_locale_from_cookie = true
SiteSetting.default_locale = "en"
end
context "with an anonymous user" do
it "uses the locale from the cookie" do
get "/bootstrap.json", headers: { Cookie: "locale=es" }
expect(response.status).to eq(200)
expect(response.parsed_body['bootstrap']['locale_script']).to end_with("es.js")
expect(I18n.locale.to_s).to eq(SiteSettings::DefaultsProvider::DEFAULT_LOCALE) # doesn't leak after requests
end
end
context "when the preferred locale includes a region" do
it "returns the locale and region separated by an underscore" do
get "/bootstrap.json", headers: { Cookie: "locale=zh-CN" }
expect(response.status).to eq(200)
expect(response.parsed_body['bootstrap']['locale_script']).to end_with("zh_CN.js")
end
end
end
context 'when locale cookie is not set' do
it 'uses the site default locale' do
SiteSetting.allow_user_locale = true
SiteSetting.default_locale = 'en'
get "/bootstrap.json", headers: { Cookie: "" }
expect(response.status).to eq(200)
expect(response.parsed_body['bootstrap']['locale_script']).to end_with("en.js")
end
end
end
end end
describe 'vary header' do describe 'vary header' do