fix: Extend the locale without variant check for article locales as well (#11021)
We allow users to select locale variants when creating the help center (e.g., pt_BR or en_UK). However, the selected variant may not always be available for translation in the app. In such cases, we need to fall back to either the base language or the default locale. While this fallback logic was implemented for the portal locale, it was missing for article locales. This PR fixes that issue.
This commit is contained in:
@@ -5,10 +5,11 @@ module SwitchLocale
|
||||
|
||||
def switch_locale(&)
|
||||
# priority is for locale set in query string (mostly for widget/from js sdk)
|
||||
locale ||= locale_from_params
|
||||
locale ||= params[:locale]
|
||||
|
||||
locale ||= locale_from_custom_domain
|
||||
# if locale is not set in account, let's use DEFAULT_LOCALE env variable
|
||||
locale ||= locale_from_env_variable
|
||||
locale ||= ENV.fetch('DEFAULT_LOCALE', nil)
|
||||
set_locale(locale, &)
|
||||
end
|
||||
|
||||
@@ -32,26 +33,30 @@ module SwitchLocale
|
||||
end
|
||||
|
||||
def set_locale(locale, &)
|
||||
# if locale is empty, use default_locale
|
||||
locale ||= I18n.default_locale
|
||||
safe_locale = validate_and_get_locale(locale)
|
||||
# Ensure locale won't bleed into other requests
|
||||
# https://guides.rubyonrails.org/i18n.html#managing-the-locale-across-requests
|
||||
I18n.with_locale(locale, &)
|
||||
I18n.with_locale(safe_locale, &)
|
||||
end
|
||||
|
||||
def locale_from_params
|
||||
I18n.available_locales.map(&:to_s).include?(params[:locale]) ? params[:locale] : nil
|
||||
def validate_and_get_locale(locale)
|
||||
return I18n.default_locale.to_s if locale.blank?
|
||||
|
||||
available_locales = I18n.available_locales.map(&:to_s)
|
||||
locale_without_variant = locale.split('_')[0]
|
||||
|
||||
if available_locales.include?(locale)
|
||||
locale
|
||||
elsif available_locales.include?(locale_without_variant)
|
||||
locale_without_variant
|
||||
else
|
||||
I18n.default_locale.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def locale_from_account(account)
|
||||
return unless account
|
||||
|
||||
I18n.available_locales.map(&:to_s).include?(account.locale) ? account.locale : nil
|
||||
end
|
||||
|
||||
def locale_from_env_variable
|
||||
return unless ENV.fetch('DEFAULT_LOCALE', nil)
|
||||
|
||||
I18n.available_locales.map(&:to_s).include?(ENV.fetch('DEFAULT_LOCALE')) ? ENV.fetch('DEFAULT_LOCALE') : nil
|
||||
account.locale
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class Public::Api::V1::Portals::BaseController < PublicController
|
||||
include SwitchLocale
|
||||
|
||||
before_action :show_plain_layout
|
||||
before_action :set_color_scheme
|
||||
before_action :set_global_config
|
||||
@@ -27,14 +29,7 @@ class Public::Api::V1::Portals::BaseController < PublicController
|
||||
end
|
||||
|
||||
def switch_locale_with_portal(&)
|
||||
locale_without_variant = params[:locale].split('_')[0]
|
||||
is_locale_available = I18n.available_locales.map(&:to_s).include?(params[:locale])
|
||||
is_locale_variant_available = I18n.available_locales.map(&:to_s).include?(locale_without_variant)
|
||||
if is_locale_available
|
||||
@locale = params[:locale]
|
||||
elsif is_locale_variant_available
|
||||
@locale = locale_without_variant
|
||||
end
|
||||
@locale = validate_and_get_locale(params[:locale])
|
||||
|
||||
I18n.with_locale(@locale, &)
|
||||
end
|
||||
@@ -44,12 +39,12 @@ class Public::Api::V1::Portals::BaseController < PublicController
|
||||
Rails.logger.info "Article: not found for slug: #{params[:article_slug]}"
|
||||
render_404 && return if article.blank?
|
||||
|
||||
@locale = if article.category.present?
|
||||
article.category.locale
|
||||
else
|
||||
article.portal.default_locale
|
||||
end
|
||||
|
||||
article_locale = if article.category.present?
|
||||
article.category.locale
|
||||
else
|
||||
article.portal.default_locale
|
||||
end
|
||||
@locale = validate_and_get_locale(article_locale)
|
||||
I18n.with_locale(@locale, &)
|
||||
end
|
||||
|
||||
|
||||
74
spec/models/concerns/switch_locale_spec.rb
Normal file
74
spec/models/concerns/switch_locale_spec.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'SwitchLocale Concern', type: :controller do
|
||||
controller(ApplicationController) do
|
||||
include SwitchLocale
|
||||
|
||||
def index
|
||||
switch_locale { render plain: I18n.locale }
|
||||
end
|
||||
|
||||
def account_locale
|
||||
switch_locale_using_account_locale { render plain: I18n.locale }
|
||||
end
|
||||
end
|
||||
|
||||
let(:account) { create(:account, locale: 'es') }
|
||||
let(:portal) { create(:portal, custom_domain: 'custom.example.com', config: { default_locale: 'fr_FR' }) }
|
||||
|
||||
describe '#switch_locale' do
|
||||
context 'when locale is provided in params' do
|
||||
it 'sets locale from params' do
|
||||
get :index, params: { locale: 'es' }
|
||||
expect(response.body).to eq('es')
|
||||
end
|
||||
|
||||
it 'falls back to default locale if invalid' do
|
||||
get :index, params: { locale: 'invalid' }
|
||||
expect(response.body).to eq('en')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when request is from custom domain' do
|
||||
before { request.host = portal.custom_domain }
|
||||
|
||||
it 'sets locale from portal' do
|
||||
get :index
|
||||
expect(response.body).to eq('fr')
|
||||
end
|
||||
|
||||
it 'overrides portal locale with param' do
|
||||
get :index, params: { locale: 'es' }
|
||||
expect(response.body).to eq('es')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when locale is not provided anywhere' do
|
||||
it 'sets locale from environment variable' do
|
||||
with_modified_env(DEFAULT_LOCALE: 'de_DE') do
|
||||
get :index
|
||||
expect(response.body).to eq('de')
|
||||
end
|
||||
end
|
||||
|
||||
it 'falls back to default locale if env locale invalid' do
|
||||
with_modified_env(DEFAULT_LOCALE: 'invalid') do
|
||||
get :index
|
||||
expect(response.body).to eq('en')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#switch_locale_using_account_locale' do
|
||||
before do
|
||||
routes.draw { get 'account_locale' => 'anonymous#account_locale' }
|
||||
end
|
||||
|
||||
it 'sets locale from account' do
|
||||
controller.instance_variable_set(:@current_account, account)
|
||||
get :account_locale
|
||||
expect(response.body).to eq('es')
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user