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)
|
user = getuser(usertoken)
|
||||||
|
|
||||||
if user && !user.languages.empty?
|
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
|
end
|
||||||
|
|
||||||
lang = http_accept_language.compatible_language_from(getlocales)
|
lang = getlocales.preferred(langs)
|
||||||
(real_lang, localised) = getlocalized(lang)
|
(real_lang, localised) = getlocalized(lang.to_s)
|
||||||
|
|
||||||
# Tell Potlatch what language it's using
|
# Tell Potlatch what language it's using
|
||||||
localised["__potlatch_locale"] = real_lang
|
localised["__potlatch_locale"] = real_lang
|
||||||
|
@ -874,7 +876,7 @@ class AmfController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def getlocales
|
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
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -288,47 +288,30 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
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
|
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?
|
if @user && @user.languages.empty? && !http_accept_language.user_preferred_languages.empty?
|
||||||
@user.languages = http_accept_language.user_preferred_languages
|
@user.languages = http_accept_language.user_preferred_languages
|
||||||
@user.save
|
@user.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
I18n.locale = Locale.available.preferred(preferred_languages)
|
||||||
|
|
||||||
|
response.headers["Vary"] = "Accept-Language"
|
||||||
response.headers["Content-Language"] = I18n.locale.to_s
|
response.headers["Content-Language"] = I18n.locale.to_s
|
||||||
end
|
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
|
def api_call_handle_error
|
||||||
yield
|
yield
|
||||||
rescue ActiveRecord::RecordNotFound => ex
|
rescue ActiveRecord::RecordNotFound => ex
|
||||||
|
|
|
@ -175,14 +175,8 @@ class Notifier < ActionMailer::Base
|
||||||
private
|
private
|
||||||
|
|
||||||
def with_recipient_locale(recipient)
|
def with_recipient_locale(recipient)
|
||||||
old_locale = I18n.locale
|
I18n.with_locale Locale.available.preferred(recipient.preferred_languages) do
|
||||||
|
|
||||||
begin
|
|
||||||
I18n.locale = recipient.preferred_language_from(I18n.available_locales)
|
|
||||||
|
|
||||||
yield
|
yield
|
||||||
ensure
|
|
||||||
I18n.locale = old_locale
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,8 @@ class User < ActiveRecord::Base
|
||||||
languages.find { |l| Language.exists?(:code => l) }
|
languages.find { |l| Language.exists?(:code => l) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def preferred_language_from(array)
|
def preferred_languages
|
||||||
(languages & array.collect(&:to_s)).first
|
@locales ||= Locale.list(languages)
|
||||||
end
|
end
|
||||||
|
|
||||||
def nearby(radius = NEARBY_RADIUS, num = NEARBY_USERS)
|
def nearby(radius = NEARBY_RADIUS, num = NEARBY_USERS)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<script type="text/javascript">alert("<%= t 'site.edit.potlatch2_not_configured' %>")</script>
|
<script type="text/javascript">alert("<%= t 'site.edit.potlatch2_not_configured' %>")</script>
|
||||||
<% end %>
|
<% 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">
|
<script type="text/javascript" defer="defer">
|
||||||
var changesaved=true;
|
var changesaved=true;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
'Please upgrade your browser or use Potlatch 2 to edit the map.';
|
'Please upgrade your browser or use Potlatch 2 to edit the map.';
|
||||||
document.getElementById('id-container').className = 'unsupported';
|
document.getElementById('id-container').className = 'unsupported';
|
||||||
} else {
|
} else {
|
||||||
<% locale = select_locale(ID::LOCALES).to_s %>
|
<% locale = ID::LOCALES.preferred(preferred_languages).to_s %>
|
||||||
|
|
||||||
var id = iD()
|
var id = iD()
|
||||||
.presets(iD.data.presets)
|
.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]
|
ex.entry[:other]
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
module JS
|
module JS
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module ID
|
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
|
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
|
end
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "user/new"
|
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_select "form > fieldset > div.form-row > input.field_with_errors#user_email"
|
||||||
assert_no_missing_translations
|
assert_no_missing_translations
|
||||||
end
|
end
|
||||||
|
|
|
@ -199,7 +199,7 @@ class UserTest < ActiveSupport::TestCase
|
||||||
assert_equal %w(de fr en), user.languages
|
assert_equal %w(de fr en), user.languages
|
||||||
user.languages = %w(fr de sl)
|
user.languages = %w(fr de sl)
|
||||||
assert_equal "de", user.preferred_language
|
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)
|
user = users(:public_user)
|
||||||
assert_equal %w(en de), user.languages
|
assert_equal %w(en de), user.languages
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue