From ac5a8bcdda8eb08aba84144053ddcec25de2ad9b Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Mon, 2 Feb 2015 12:32:55 +0100 Subject: [PATCH] [l10n] Treat language as case-insensitive See "Case-insensitive language comparisons per RFC 4646" https://github.com/fabi1cazenave/webL10n/pull/51 Removed the "patch" in compatibility.js and fixed the bug in webL10n, because the logic belongs to webL10n instead of PDF.js. The immediate motivation for this patch is that Chrome 40 converts navigator.language to lower case: https://crbug.com/454331 --- external/webL10n/l10n.js | 28 ++++++++++++++++++++++++---- web/compatibility.js | 14 ++------------ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/external/webL10n/l10n.js b/external/webL10n/l10n.js index 9f7a0c94945e0..6c9421bc92249 100644 --- a/external/webL10n/l10n.js +++ b/external/webL10n/l10n.js @@ -142,7 +142,7 @@ document.webL10n = (function(window, document, undefined) { * URL of the l10n resource to parse. * * @param {string} lang - * locale (language) to parse. + * locale (language) to parse. Must be a lowercase string. * * @param {Function} successCallback * triggered when the l10n resource has been successully parsed. @@ -188,7 +188,7 @@ document.webL10n = (function(window, document, undefined) { function parseRawLines(rawText, extendedSyntax) { var entries = rawText.replace(reBlank, '').split(/[\r\n]+/); var currentLang = '*'; - var genericLang = lang.replace(/-[a-z]+$/i, ''); + var genericLang = lang.split('-', 1)[0]; var skipLang = false; var match = ''; @@ -203,7 +203,9 @@ document.webL10n = (function(window, document, undefined) { if (extendedSyntax) { if (reSection.test(line)) { // section start? match = reSection.exec(line); - currentLang = match[1]; + // RFC 4646, section 4.4, "All comparisons MUST be performed + // in a case-insensitive manner." + currentLang = match[1].toLowerCase(); skipLang = (currentLang !== '*') && (currentLang !== lang) && (currentLang !== genericLang); continue; @@ -268,6 +270,12 @@ document.webL10n = (function(window, document, undefined) { // load and parse all resources for the specified locale function loadLocale(lang, callback) { + // RFC 4646, section 2.1 states that language tags have to be treated as + // case-insensitive. Convert to lowercase for case-insensitive comparisons. + if (lang) { + lang = lang.toLowerCase(); + } + callback = callback || function _callback() {}; clear(); @@ -282,7 +290,19 @@ document.webL10n = (function(window, document, undefined) { var dict = getL10nDictionary(); if (dict && dict.locales && dict.default_locale) { console.log('using the embedded JSON directory, early way out'); - gL10nData = dict.locales[lang] || dict.locales[dict.default_locale]; + gL10nData = dict.locales[lang]; + if (!gL10nData) { + var defaultLocale = dict.default_locale.toLowerCase(); + for (var anyCaseLang in dict.locales) { + anyCaseLang = anyCaseLang.toLowerCase(); + if (anyCaseLang === lang) { + gL10nData = dict.locales[lang]; + break; + } else if (anyCaseLang === defaultLocale) { + gL10nData = dict.locales[defaultLocale]; + } + } + } callback(); } else { console.log('no resource to load, early way out'); diff --git a/web/compatibility.js b/web/compatibility.js index 967e312a998b5..424d5af32d2ea 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -447,20 +447,10 @@ if (typeof PDFJS === 'undefined') { // Checks if navigator.language is supported (function checkNavigatorLanguage() { - if ('language' in navigator && - /^[a-z]+(-[A-Z]+)?$/.test(navigator.language)) { + if ('language' in navigator) { return; } - function formatLocale(locale) { - var split = locale.split(/[-_]/); - split[0] = split[0].toLowerCase(); - if (split.length > 1) { - split[1] = split[1].toUpperCase(); - } - return split.join('-'); - } - var language = navigator.language || navigator.userLanguage || 'en-US'; - PDFJS.locale = formatLocale(language); + PDFJS.locale = navigator.userLanguage || 'en-US'; })(); (function checkRangeRequests() {