FEATURE: Allow setting locale from 'lang' param (#30952)

As we start to translate more pages, we'll need a way for other sites to
link back to our translated topics.

This commit gives us the ability to use the "lang" URL param to define what
language a site should be in.

Related: https://github.com/discourse/discourse-translator/pull/199
This commit is contained in:
Natalie Tay
2025-01-24 11:53:13 +08:00
committed by GitHub
parent 5d4bb4b54e
commit 8d45755a06
4 changed files with 47 additions and 6 deletions

View File

@ -1737,6 +1737,7 @@ en:
allow_user_locale: "Allow users to choose their own language interface preference" allow_user_locale: "Allow users to choose their own language interface preference"
set_locale_from_accept_language_header: "set interface language for anonymous users from their web browser's language headers" set_locale_from_accept_language_header: "set interface language for anonymous users from their web browser's language headers"
set_locale_from_cookie: "Allows setting an anonymous user's locale via the 'locale' browser cookie" set_locale_from_cookie: "Allows setting an anonymous user's locale via the 'locale' browser cookie"
set_locale_from_param: "Allows setting an anonymous user's locale via the 'lang' URL param, e.g. ?lang=es"
support_mixed_text_direction: "Support mixed left-to-right and right-to-left text directions." support_mixed_text_direction: "Support mixed left-to-right and right-to-left text directions."
min_post_length: "Minimum allowed post length in characters (excluding personal messages)" min_post_length: "Minimum allowed post length in characters (excluding personal messages)"
min_first_post_length: "Minimum allowed first post (topic body) length (excluding personal messages)" min_first_post_length: "Minimum allowed first post (topic body) length (excluding personal messages)"

View File

@ -154,6 +154,10 @@ basic:
default: false default: false
client: true client: true
validator: "AllowUserLocaleEnabledValidator" validator: "AllowUserLocaleEnabledValidator"
set_locale_from_param:
default: false
client: true
validator: "AllowUserLocaleEnabledValidator"
support_mixed_text_direction: support_mixed_text_direction:
client: true client: true
default: false default: false

View File

@ -1215,13 +1215,11 @@ module Discourse
end end
def self.anonymous_locale(request) def self.anonymous_locale(request)
locale = locale = request.params["lang"] if SiteSetting.set_locale_from_param
HttpLanguageParser.parse(request.cookies["locale"]) if SiteSetting.set_locale_from_cookie locale ||= request.cookies["locale"] if SiteSetting.set_locale_from_cookie
locale ||= locale ||=
HttpLanguageParser.parse( request.env["HTTP_ACCEPT_LANGUAGE"] if SiteSetting.set_locale_from_accept_language_header
request.env["HTTP_ACCEPT_LANGUAGE"], HttpLanguageParser.parse(locale)
) if SiteSetting.set_locale_from_accept_language_header
locale
end end
# For test environment only # For test environment only

View File

@ -1126,6 +1126,44 @@ RSpec.describe ApplicationController do
end end
end end
end end
context "with set_locale_from_param enabled" do
context "when param locale differs from default locale" do
before do
SiteSetting.allow_user_locale = true
SiteSetting.set_locale_from_param = true
SiteSetting.default_locale = "en"
end
context "with an anonymous user" do
it "uses the locale from the param" do
get "/latest?lang=es"
expect(response.status).to eq(200)
expect(locale_scripts(response.body)).to contain_exactly("/assets/locales/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 "/latest?lang=zh-CN"
expect(response.status).to eq(200)
expect(locale_scripts(response.body)).to contain_exactly("/assets/locales/zh_CN.js")
end
end
end
context "when locale param is not set" do
it "uses the site default locale" do
SiteSetting.allow_user_locale = true
SiteSetting.default_locale = "en"
get "/latest"
expect(response.status).to eq(200)
expect(locale_scripts(response.body)).to contain_exactly("/assets/locales/en.js")
end
end
end
end end
describe "vary header" do describe "vary header" do