- 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.
131 lines
4.6 KiB
Ruby
131 lines
4.6 KiB
Ruby
class ApplicationController < ActionController::Base
|
||
include SeoConcern
|
||
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
||
before_action :log_browser_info
|
||
before_action :set_content_type_for_rss, if: -> { request.format.rss? }
|
||
# allow_browser versions: :modern
|
||
# allow_browser versions: :modern,
|
||
# patterns: [
|
||
# # 鸿蒙系统相关
|
||
# /OpenHarmony/, # 鸿蒙系统标识
|
||
# /ArkWeb\/[\d.]+/, # 鸿蒙浏览器内核
|
||
# /Mobile HuaweiBrowser/, # 华为浏览器(新格式)
|
||
# /HuaweiBrowser\/[\d.]+/, # 华为浏览器(旧格式)
|
||
#
|
||
# # 夸克浏览器(更宽松的匹配)
|
||
# /Quark[\s\/][\d.]+/, # 匹配 "Quark/7.4.6.681" 或 "Quark 7.4.6.681"
|
||
#
|
||
# /Mobile Safari/,
|
||
# /Chrome\/[\d.]+/,
|
||
# /Quark\/[\d.]+/,
|
||
# /HuaweiBrowser\/[\d.]+/,
|
||
# /MiuiBrowser\/[\d.]+/,
|
||
# /VivoBrowser\/[\d.]+/,
|
||
# /OppoBrowser\/[\d.]+/,
|
||
# /UCBrowser\/[\d.]+/,
|
||
# /QQBrowser\/[\d.]+/,
|
||
# /MicroMessenger\/[\d.]+/,
|
||
# /Alipay/,
|
||
# /BaiduBoxApp/,
|
||
# /baiduboxapp/i,
|
||
# /SogouMobile/,
|
||
# /Weibo/,
|
||
# /DingTalk/,
|
||
# /ToutiaoMicroApp/,
|
||
# /BytedanceWebview/,
|
||
# /ArkWeb/
|
||
# ],
|
||
# on_failure: ->(browser) {
|
||
# Rails.logger.warn <<~BROWSER_INFO
|
||
# Browser Blocked:
|
||
# User Agent: #{browser.ua}
|
||
# Name: #{browser.name}
|
||
# Version: #{browser.version}
|
||
# Platform: #{browser.platform.name}
|
||
# Device: #{browser.device.name}
|
||
# Mobile: #{browser.mobile?}
|
||
# Modern: #{browser.modern?}
|
||
# Bot: #{browser.bot?}
|
||
# BROWSER_INFO
|
||
# }
|
||
around_action :set_locale
|
||
after_action :track_action
|
||
|
||
def log_browser_info
|
||
# 构建详细的浏览器信息
|
||
Rails.logger.debug "User Agent: #{request.user_agent}"
|
||
|
||
# 如果是被拦截的浏览器,记录额外信息
|
||
# unless browser_allowed?
|
||
# Rails.logger.info "User Agent: #{request.user_agent}"
|
||
# end
|
||
end
|
||
|
||
protected
|
||
|
||
def track_action
|
||
ahoy.track "Viewed Application", request.path_parameters
|
||
end
|
||
|
||
def authenticate_admin_user!
|
||
unless current_user&.admin?
|
||
flash[:alert] = "您没有权限访问该页面。"
|
||
redirect_to root_path
|
||
end
|
||
end
|
||
|
||
private
|
||
|
||
def set_locale(&action)
|
||
I18n.locale = extract_locale || I18n.default_locale
|
||
I18n.fallbacks[I18n.locale] = [ I18n.locale, I18n.default_locale ].uniq
|
||
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)
|
||
locale = full_locale
|
||
else
|
||
# 否则只匹配语言代码 (例如 'en')
|
||
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)
|
||
# 直接使用 I18n.available_locales
|
||
locale = locale.to_sym
|
||
I18n.available_locales.include?(locale) ? locale : I18n.default_locale
|
||
end
|
||
|
||
def extract_locale
|
||
parsed_locale = params[:locale]
|
||
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
|
||
end
|
||
|
||
def default_url_options
|
||
{ locale: I18n.locale }
|
||
end
|
||
|
||
def set_content_type_for_rss
|
||
response.headers["Content-Type"] = "application/rss+xml; charset=utf-8"
|
||
end
|
||
end
|