refactor: change locale handling to around_action

- Update set_locale method to use around_action instead of before_action.
- Modify locale extraction logic to handle more cases, ensuring better fallback handling.
- Improve overall method clarity and maintainability by restructuring code.

This change enhances the localization process by providing a clearer
way to manage locale settings and ensures that it correctly falls back
to the default locale when necessary. It also resolves some edge cases
in locale extraction based on the HTTP_ACCEPT_LANGUAGE header.
This commit is contained in:
songtianlun 2025-02-22 15:00:22 +08:00
parent 09fa1ceea9
commit 926ba18e85

View File

@ -48,7 +48,7 @@ class ApplicationController < ActionController::Base
# Bot: #{browser.bot?}
# BROWSER_INFO
# }
before_action :set_locale
around_action :set_locale
after_action :track_action
def log_browser_info
@ -76,27 +76,37 @@ class ApplicationController < ActionController::Base
private
def set_locale
def set_locale(&action)
I18n.locale = extract_locale || I18n.default_locale
I18n.fallbacks[I18n.locale] = [ I18n.locale, I18n.default_locale ].uniq
# 如果URL已经包含语言前缀跳过处理
# return if params[:locale].present?
# 获取浏览器语言并转换为支持的语言代码
# locale = sanitize_locale(extract_locale_from_accept_language_header)
# I18n.with_locale(locale, &action)
locale = params[:locale] || extract_locale_from_accept_language_header || I18n.default_locale
I18n.with_locale(locale, &action)
# 重定向到带有语言前缀的相同路径
# redirect_to "/#{locale}#{request.fullpath}"
end
def extract_locale_from_accept_language_header
return I18n.default_locale.to_s unless request.env["HTTP_ACCEPT_LANGUAGE"]
available_locales = I18n.available_locales.map(&:to_s)
accept_language = request.env["HTTP_ACCEPT_LANGUAGE"].to_s
# 修改正则表达式以匹配 'zh-CN' 这样的格式
if (full_locale = accept_language.scan(/^[a-z]{2}-[A-Z]{2}/).first)
full_locale
locale = full_locale
else
# 否则只匹配语言代码 (例如 'en')
accept_language.scan(/^[a-z]{2}/).first || I18n.default_locale.to_s
locale = accept_language.scan(/^[a-z]{2}/).first || I18n.default_locale.to_s
end
return locale if available_locales.include?(locale)
# 尝试基础语言匹配(例如:当请求 'zh' 时匹配 'zh-CN'
base_language = locale.split('-').first
matching_locale = available_locales.find do |available_locale|
available_locale.start_with?(base_language)
end
matching_locale ? matching_locale : I18n.default_locale.to_s
end
def sanitize_locale(locale)