Fix Bug 1138117 - Translation Bar comes up even when the page is offered in user's secondary accept language

This commit is contained in:
Kohei Yoshino 2015-03-17 12:28:44 -04:00
Родитель 71f571171a
Коммит 2955f97dca
2 изменённых файлов: 71 добавлений и 54 удалений

Просмотреть файл

@ -388,73 +388,85 @@ var Tabzilla = (function (Tabzilla) {
return false;
}
// Normalize the user language in the form of ab or ab-CD
var normalize = function (lang) {
return lang.replace(/^(\w+)(?:-(\w+))?$/, function (m, p1, p2) {
return p1.toLowerCase() + ((p2) ? '-' + p2.toUpperCase() : '');
});
};
// Normalize every language for easier comparison
userLangs = $.map(userLangs, function (lang) { return normalize(lang); });
pageLang = normalize(pageLang);
// If the page language is the user's primary language, there is nothing
// to do here
if (pageLang === userLangs[0]) {
return false;
}
var offeredLang;
var langLinks = [];
var langOptions = [];
var availableLangs = {};
var $links = $('link[hreflang]');
var $options = $('#language option');
// Compare the user's accept languages against the available languages
// to find the best language. Use an alternate URL in <head> or a
// language option in <form>
// Make a dictionary from alternate URLs or a language selector. The key
// is a language, the value is the relevant <link> or <option> element.
// If those lists cannot be found, there is nothing to do
if ($links.length) {
$links.each(function () {
availableLangs[normalize(this.hreflang)] = this;
});
} else if ($options.length) {
$options.each(function () {
availableLangs[normalize(this.value.match(/^\/?([\w\-]+)/)[1])] = this;
});
} else {
return false;
}
// Compare the user's accept languages against the page's current
// language and other available languages to find the best language
$.each(userLangs, function(index, userLang) {
// Languages in the language switcher are uncapitalized on some
// sites (AMO, Firefox Flicks)
var userLangLower = userLang.toLowerCase();
// The user language can be ab-CD while the page language is ab
// (Example: fr-FR vs fr, ja-JP vs ja)
var userLangShort = userLangLower.split('-')[0];
// Compare in lower case
var pageLangLower = pageLang.toLowerCase();
// Compare the user's language and the page's language
if (userLangLower === pageLangLower ||
// Consider some legacy locales like fr-FR, it-IT or el-GR
userLangShort === pageLangLower) {
// The user is already seeing the page in his/her own language.
// No need to show the Translation Bar
if (pageLang === userLang || pageLang === userLang.split('-')[0]) {
offeredLang = 'self';
return false; // Break the loop
}
$.each([userLang, userLangLower, userLangShort], function(index, lang) {
var links = $('link[hreflang="' + lang + '"]');
var options = $('#language [value="' + lang + '"], \
#language [value^="/' + lang + '/"]');
if (!links.length && !options.length) {
return true; // Continue the loop
}
if (links.length) {
langLinks = links;
}
if (options.length) {
langOptions = options;
}
offeredLang = lang;
return false; // Break the loop
});
if (offeredLang) {
if (userLang in availableLangs) {
offeredLang = userLang;
return false; // Break the loop
}
});
// If the page language is one of the user's secondary languages and no
// other higher-priority language cannot be found in the translations,
// there is nothing to do
if (offeredLang === 'self') {
return false;
}
// If an offered language cannot be detected, try again with shorter
// language names, like en-US -> en, fr-FR -> fr
if (!offeredLang) {
$.each(userLangs, function(index, userLang) {
userLang = userLang.split('-')[0];
if (userLang in availableLangs) {
offeredLang = userLang;
return false; // Break the loop
}
});
}
// If there is no offered language yet, there is nothing to do
if (!offeredLang) {
// No translation is available for the user
return false;
}
// Do not show Chrome's built-in Translation Bar
$('head').append('<meta name="google" value="notranslate">');
// Normalize the user language in the form of ab or ab-CD
offeredLang = offeredLang.replace(/^(\w+)(?:-(\w+))?$/, function (m, p1, p2) {
return p1.toLowerCase() + ((p2) ? '-' + p2.toUpperCase() : '');
});
// Log the language of the current page
transbar.onshow.trackLabel = transbar.oncancel.trackLabel = offeredLang;
transbar.oncancel.trackAction = 'hide';
@ -464,10 +476,13 @@ var Tabzilla = (function (Tabzilla) {
trackAction: 'change',
trackLabel: offeredLang,
callback: function () {
if (langLinks.length) {
location.href = langLinks.attr('href').replace(/^https?\:\/\/[^/]+/, '');
} else {
langOptions.attr('selected', 'selected').get(0).form.submit();
var element = availableLangs[offeredLang];
if (element.form) { // <option>
element.selected = true;
element.form.submit();
} else { // <link>
location.href = element.href.replace(/^https?\:\/\/[^/]+/, '');
}
}
};

Просмотреть файл

@ -54,6 +54,7 @@ describe("tabzilla.js", function() {
expect(setup(['fr', 'de'], 'fr')).toBeFalsy();
expect(setup(['de', 'fr', 'en'], 'fr')).toBeFalsy();
expect(setup(['ja', 'pt-PT', 'el', 'fr', 'en'], 'el')).toBeFalsy();
expect(setup(['en-ZA', 'en-GB', 'en'], 'en-GB')).toBeFalsy();
// obsolete ab-XX
expect(setup(['fr-FR'], 'fr')).toBeFalsy();
expect(setup(['el-GR'], 'el')).toBeFalsy();
@ -76,6 +77,7 @@ describe("tabzilla.js", function() {
expect(setup(['ar', 'fr'], 'el')).toEqual('fr');
expect(setup(['de', 'fr', 'en'], 'en-US')).toEqual('fr');
expect(setup(['de', 'el', 'fr', 'en-US'], 'fr')).toEqual('el');
expect(setup(['el', 'en-US'], 'en-US')).toEqual('el');
// obsolete ab-XX
expect(setup(['fr-FR'], 'en-US')).toEqual('fr');
expect(setup(['el-GR'], 'fr')).toEqual('el');