diff options
Diffstat (limited to 'tools/addon-sdk-1.7/packages/addon-kit/lib/l10n.js')
-rw-r--r-- | tools/addon-sdk-1.7/packages/addon-kit/lib/l10n.js | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.7/packages/addon-kit/lib/l10n.js b/tools/addon-sdk-1.7/packages/addon-kit/lib/l10n.js new file mode 100644 index 0000000..198f711 --- /dev/null +++ b/tools/addon-sdk-1.7/packages/addon-kit/lib/l10n.js @@ -0,0 +1,149 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { Cc, Ci } = require("chrome"); +const { getPreferedLocales, findClosestLocale } = require("api-utils/l10n/locale"); +const { getRulesForLocale } = require("api-utils/l10n/plural-rules"); + +// Get URI for the addon root folder: +const { rootURI } = require("@packaging"); + +let globalHash = {}; +let pluralMappingFunction = getRulesForLocale("en"); + +exports.get = function get(k) { + + // For now, we only accept a "string" as first argument + // TODO: handle plural forms in gettext pattern + if (typeof k !== "string") + throw new Error("First argument of localization method should be a string"); + + // Get translation from big hashmap or default to hard coded string: + let localized = globalHash[k] || k; + + // # Simplest usecase: + // // String hard coded in source code: + // _("Hello world") + // // Identifier of a key stored in properties file + // _("helloString") + if (arguments.length <= 1) + return localized; + + let args = arguments; + + if (typeof localized == "object" && "other" in localized) { + // # Plural form: + // // Strings hard coded in source code: + // _(["One download", "%d downloads"], 10); + // // Identifier of a key stored in properties file + // _("downloadNumber", 0); + let n = arguments[1]; + + // First handle simple universal forms that may not be mandatory + // for each language, (i.e. not different than 'other' form, + // but still usefull for better phrasing) + // For example 0 in english is the same form than 'other' + // but we accept 'zero' form if specified in localization file + if (n === 0 && "zero" in localized) + localized = localized["zero"]; + else if (n === 1 && "one" in localized) + localized = localized["one"]; + else if (n === 2 && "two" in localized) + localized = localized["two"]; + else { + let pluralForm = pluralMappingFunction(n); + if (pluralForm in localized) + localized = localized[pluralForm]; + else // Fallback in case of error: missing plural form + localized = localized["other"]; + } + + // Simulate a string with one placeholder: + args = [null, n]; + } + + // # String with placeholders: + // // Strings hard coded in source code: + // _("Hello %s", username) + // // Identifier of a key stored in properties file + // _("helloString", username) + // * We supports `%1s`, `%2s`, ... pattern in order to change arguments order + // in translation. + // * In case of plural form, we has `%d` instead of `%s`. + let offset = 1; + localized = localized.replace(/%(\d*)(s|d)/g, function (v, n) { + let rv = args[n != "" ? n : offset]; + offset++; + return rv; + }); + + return localized; +} + +function readURI(uri) { + let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. + createInstance(Ci.nsIXMLHttpRequest); + request.open('GET', uri, false); + request.overrideMimeType('text/plain'); + request.send(); + return request.responseText; +} + +function readJsonUri(uri) { + try { + return JSON.parse(readURI(uri)); + } + catch(e) { + console.error("Error while reading locale file:\n" + uri + "\n" + e); + } + return {}; +} + +// Returns the array stored in `locales.json` manifest that list available +// locales files +function getAvailableLocales() { + let uri = rootURI + "locales.json"; + let manifest = readJsonUri(uri); + + return "locales" in manifest && Array.isArray(manifest.locales) ? + manifest.locales : []; +} + +// Returns URI of the best locales file to use from the XPI +function getBestLocaleFile() { + + // Read localization manifest file that contains list of available languages + let availableLocales = getAvailableLocales(); + + // Retrieve list of prefered locales to use + let preferedLocales = getPreferedLocales(); + + // Compute the most preferable locale to use by using these two lists + let bestMatchingLocale = findClosestLocale(availableLocales, preferedLocales); + + // It may be null if the addon doesn't have any locale file + if (!bestMatchingLocale) + return null; + + // Retrieve the related plural mapping function + let shortLocaleCode = bestMatchingLocale.split("-")[0].toLowerCase(); + pluralMappingFunction = getRulesForLocale(shortLocaleCode); + + return rootURI + "locale/" + bestMatchingLocale + ".json"; +} + +function init() { + // First, search for a locale file: + let localeURI = getBestLocaleFile(); + if (!localeURI) + return; + + // Locale files only contains one big JSON object that is used as + // an hashtable of: "key to translate" => "translated key" + // TODO: We are likely to change this in order to be able to overload + // a specific key translation. For a specific package, module or line? + globalHash = readJsonUri(localeURI); +} +init(); |