Skip to content

Instantly share code, notes, and snippets.

@BroHandTW
Created January 22, 2022 16:32
Show Gist options
  • Save BroHandTW/b44716106f0e45b875406618ad27b68d to your computer and use it in GitHub Desktop.
Save BroHandTW/b44716106f0e45b875406618ad27b68d to your computer and use it in GitHub Desktop.
module WebI18nLocale
extend ActiveSupport::Concern
included do
prepend_before_action :digest_locale_params
before_action :set_locale
helper_method :set_locale_path
end
private
def digest_locale_params
return unless params[:locale] && request.get?
session[:locale] = resolve_locale(params[:locale])
redirect_to url_for(request.params.except(:locale).merge(only_path: true))
end
def set_locale_path(locale)
url_for(request.params.merge(locale: locale, only_path: true))
end
def set_locale
the_locale = session_locale || browser_locale
I18n.locale = the_locale
@pagy_locale = the_locale.to_s # for pagy i18n
end
def resolve_locale(str)
locale = String(str).to_sym
I18n.available_locales.include?(locale) ? locale : nil
end
def session_locale
@session_locale ||= resolve_locale(session[:locale])
end
def browser_locale
@browser_locale ||= compatible_language_from(I18n.available_locales)
end
# references http_accept_language gem
def user_preferred_languages # rubocop:disable all
@user_preferred_languages ||= begin
header = request.env['HTTP_ACCEPT_LANGUAGE']
locale_quality_array = header.to_s.gsub(/\s+/, '').split(',').map do |language|
locale, quality = language.split(';q=')
raise ArgumentError, 'Not correctly formatted' unless locale =~ /^[a-z\-0-9]+|\*$/i
locale = locale.downcase.gsub(/-[a-z0-9]+$/i, &:upcase) # Uppercase territory
locale = nil if locale == '*' # Ignore wildcards
quality = quality ? quality.to_f : 1.0
[locale, quality]
end
locale_quality_array.sort { |(_, left), (_, right)| right <=> left }.map(&:first).compact
rescue ArgumentError # Just rescue anything if the browser messed up badly.
[]
end
end
# references http_accept_language gem
def compatible_language_from(available_languages)
user_preferred_languages.map do |preferred| # en-US
preferred = preferred.downcase
preferred_language = preferred.split('-', 2).first
available_languages.find do |available| # en
available = available.to_s.downcase
preferred == available || preferred_language == available.split('-', 2).first
end
end.compact.first
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment