Rework locale selection
Implement our own matching algorithm rather than trying to patch the http_accept_language one and make sure everything is using it in a consistent way. Fixes #1125
This commit is contained in:
parent
5f4b7d3f91
commit
4028f4cdb9
12 changed files with 83 additions and 64 deletions
|
@ -190,11 +190,13 @@ class AmfController < ApplicationController
|
|||
user = getuser(usertoken)
|
||||
|
||||
if user && !user.languages.empty?
|
||||
http_accept_language.user_preferred_languages = user.languages
|
||||
langs = Locale.list(user.languages)
|
||||
else
|
||||
langs = Locale.list(http_accept_language.user_preferred_languages)
|
||||
end
|
||||
|
||||
lang = http_accept_language.compatible_language_from(getlocales)
|
||||
(real_lang, localised) = getlocalized(lang)
|
||||
lang = getlocales.preferred(langs)
|
||||
(real_lang, localised) = getlocalized(lang.to_s)
|
||||
|
||||
# Tell Potlatch what language it's using
|
||||
localised["__potlatch_locale"] = real_lang
|
||||
|
@ -874,7 +876,7 @@ class AmfController < ApplicationController
|
|||
end
|
||||
|
||||
def getlocales
|
||||
Dir.glob("#{Rails.root}/config/potlatch/locales/*").collect { |f| File.basename(f, ".yml") }
|
||||
@locales ||= Locale.list(Dir.glob("#{Rails.root}/config/potlatch/locales/*").collect { |f| File.basename(f, ".yml") })
|
||||
end
|
||||
|
||||
##
|
||||
|
|
|
@ -288,47 +288,30 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def preferred_languages
|
||||
@languages ||= if params[:locale]
|
||||
Locale.list(params[:locale])
|
||||
elsif @user
|
||||
@user.preferred_languages
|
||||
else
|
||||
Locale.list(http_accept_language.user_preferred_languages)
|
||||
end
|
||||
end
|
||||
|
||||
helper_method :preferred_languages
|
||||
|
||||
def set_locale
|
||||
response.header["Vary"] = "Accept-Language"
|
||||
|
||||
if @user && !@user.languages.empty?
|
||||
http_accept_language.user_preferred_languages = @user.languages
|
||||
response.header["Vary"] = "*"
|
||||
end
|
||||
|
||||
I18n.locale = select_locale
|
||||
|
||||
if @user && @user.languages.empty? && !http_accept_language.user_preferred_languages.empty?
|
||||
@user.languages = http_accept_language.user_preferred_languages
|
||||
@user.save
|
||||
end
|
||||
|
||||
I18n.locale = Locale.available.preferred(preferred_languages)
|
||||
|
||||
response.headers["Vary"] = "Accept-Language"
|
||||
response.headers["Content-Language"] = I18n.locale.to_s
|
||||
end
|
||||
|
||||
def select_locale(locales = I18n.available_locales)
|
||||
if params[:locale]
|
||||
http_accept_language.user_preferred_languages = [params[:locale]]
|
||||
end
|
||||
|
||||
if http_accept_language.compatible_language_from(locales).nil?
|
||||
http_accept_language.user_preferred_languages = http_accept_language.user_preferred_languages.collect do |pl|
|
||||
pls = [pl]
|
||||
|
||||
while pl.match(/^(.*)-[^-]+$/)
|
||||
pls.push($1) if locales.include?($1) || locales.include?($1.to_sym)
|
||||
pl = $1
|
||||
end
|
||||
|
||||
pls
|
||||
end.flatten
|
||||
end
|
||||
|
||||
http_accept_language.compatible_language_from(locales) || I18n.default_locale
|
||||
end
|
||||
|
||||
helper_method :select_locale
|
||||
|
||||
def api_call_handle_error
|
||||
yield
|
||||
rescue ActiveRecord::RecordNotFound => ex
|
||||
|
|
|
@ -175,14 +175,8 @@ class Notifier < ActionMailer::Base
|
|||
private
|
||||
|
||||
def with_recipient_locale(recipient)
|
||||
old_locale = I18n.locale
|
||||
|
||||
begin
|
||||
I18n.locale = recipient.preferred_language_from(I18n.available_locales)
|
||||
|
||||
I18n.with_locale Locale.available.preferred(recipient.preferred_languages) do
|
||||
yield
|
||||
ensure
|
||||
I18n.locale = old_locale
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -131,8 +131,8 @@ class User < ActiveRecord::Base
|
|||
languages.find { |l| Language.exists?(:code => l) }
|
||||
end
|
||||
|
||||
def preferred_language_from(array)
|
||||
(languages & array.collect(&:to_s)).first
|
||||
def preferred_languages
|
||||
@locales ||= Locale.list(languages)
|
||||
end
|
||||
|
||||
def nearby(radius = NEARBY_RADIUS, num = NEARBY_USERS)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<script type="text/javascript">alert("<%= t 'site.edit.potlatch2_not_configured' %>")</script>
|
||||
<% end %>
|
||||
|
||||
<% locale = select_locale(Potlatch2::LOCALES.keys).to_s %>
|
||||
<% locale = Locale.list(Potlatch2::LOCALES.keys).preferred(preferred_languages).to_s %>
|
||||
|
||||
<script type="text/javascript" defer="defer">
|
||||
var changesaved=true;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
'Please upgrade your browser or use Potlatch 2 to edit the map.';
|
||||
document.getElementById('id-container').className = 'unsupported';
|
||||
} else {
|
||||
<% locale = select_locale(ID::LOCALES).to_s %>
|
||||
<% locale = ID::LOCALES.preferred(preferred_languages).to_s %>
|
||||
|
||||
var id = iD()
|
||||
.presets(iD.data.presets)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#
|
||||
# Monkey patch HttpAcceptLanguage pending integration of
|
||||
# https://github.com/iain/http_accept_language/pull/6
|
||||
#
|
||||
module HttpAcceptLanguage
|
||||
class Parser
|
||||
def compatible_language_from(available_languages)
|
||||
user_preferred_languages.find do |x|
|
||||
available_languages.find { |y| y.to_s == x.to_s } ||
|
||||
available_languages.find { |y| y.to_s =~ /^#{Regexp.escape(x.to_s)}-/ }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,6 +8,16 @@ module I18n
|
|||
ex.entry[:other]
|
||||
end
|
||||
end
|
||||
|
||||
class Simple
|
||||
def store_translations_with_normalisation(locale, data, options = {})
|
||||
locale = I18n::Locale::Tag::Rfc4646.tag(locale).to_s
|
||||
|
||||
store_translations_without_normalisation(locale, data, options)
|
||||
end
|
||||
|
||||
alias_method_chain :store_translations, :normalisation
|
||||
end
|
||||
end
|
||||
|
||||
module JS
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module ID
|
||||
LOCALES = Rails.root.join("vendor/assets/iD/iD/locales").entries.map { |p| p.basename.to_s[/(.*).json/] && $1 }.compact
|
||||
LOCALES = Locale.list(Rails.root.join("vendor/assets/iD/iD/locales").entries.map { |p| p.basename.to_s[/(.*).json/] && $1 }.compact)
|
||||
end
|
||||
|
|
44
lib/locale.rb
Normal file
44
lib/locale.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
class Locale < I18n::Locale::Tag::Rfc4646
|
||||
class List < Array
|
||||
attr_reader :locales
|
||||
|
||||
def initialize(tags)
|
||||
super(tags.map { |tag| Locale.tag(tag) })
|
||||
end
|
||||
|
||||
def candidates(preferred)
|
||||
preferred.expand & self
|
||||
end
|
||||
|
||||
def preferred(preferred)
|
||||
candidates(preferred).first
|
||||
end
|
||||
|
||||
def expand
|
||||
map(&:candidates).flatten.uniq << Locale.default
|
||||
end
|
||||
end
|
||||
|
||||
def self.list(*tags)
|
||||
List.new(tags.flatten)
|
||||
end
|
||||
|
||||
def self.default
|
||||
tag(I18n.default_locale)
|
||||
end
|
||||
|
||||
def self.available
|
||||
@available ||= List.new(I18n.available_locales)
|
||||
end
|
||||
|
||||
def candidates
|
||||
[self.class.new(language, script, region, variant),
|
||||
self.class.new(language, script, region),
|
||||
self.class.new(language, script, nil, variant),
|
||||
self.class.new(language, script),
|
||||
self.class.new(language, nil, region, variant),
|
||||
self.class.new(language, nil, region),
|
||||
self.class.new(language, nil, nil, variant),
|
||||
self.class.new(language)]
|
||||
end
|
||||
end
|
|
@ -40,7 +40,7 @@ class UserCreationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
assert_response :success
|
||||
assert_template "user/new"
|
||||
assert_equal response.headers["Content-Language"][0..1], locale.to_s[0..1] unless locale == :root
|
||||
assert_equal locale.to_s, response.headers["Content-Language"] unless locale == :root
|
||||
assert_select "form > fieldset > div.form-row > input.field_with_errors#user_email"
|
||||
assert_no_missing_translations
|
||||
end
|
||||
|
|
|
@ -199,7 +199,7 @@ class UserTest < ActiveSupport::TestCase
|
|||
assert_equal %w(de fr en), user.languages
|
||||
user.languages = %w(fr de sl)
|
||||
assert_equal "de", user.preferred_language
|
||||
assert_equal "de", user.preferred_language_from(%w(en sl de es))
|
||||
assert_equal %w(fr de sl), user.preferred_languages.map(&:to_s)
|
||||
user = users(:public_user)
|
||||
assert_equal %w(en de), user.languages
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue