diff options
Diffstat (limited to 'tools/addon-sdk-1.5/packages/addon-kit/lib/l10n.js')
-rw-r--r-- | tools/addon-sdk-1.5/packages/addon-kit/lib/l10n.js | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.5/packages/addon-kit/lib/l10n.js b/tools/addon-sdk-1.5/packages/addon-kit/lib/l10n.js new file mode 100644 index 0000000..1bd7e57 --- /dev/null +++ b/tools/addon-sdk-1.5/packages/addon-kit/lib/l10n.js @@ -0,0 +1,126 @@ +/* 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"; + +let prefs = require("preferences-service"); +let { Cc, Ci } = require("chrome"); + +let globalHash = {}; + +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]; + let pluralForm = "other"; + // TODO: Make this rule specific to each language + if (n <= 1) + pluralForm = "one"; + localized = localized[pluralForm]; + // 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; +} + +// Returns URI of the best locales file to use from the XPI +// Reproduce platform algorithm, see `LanguagesMatch` and +// `nsChromeRegistryChrome::nsProviderArray::GetProvider` functions: +// http://mxr.mozilla.org/mozilla-central/source/chrome/src/nsChromeRegistryChrome.cpp#93 +// TODO: Implement a better matching algorithm using "intl.accept_languages" +// and following: http://tools.ietf.org/html/rfc4647#page-14 +function searchAddonLocaleFile(preferred) { + // Get URI for the addon root folder: + let rootURI = require("@packaging").rootURI; + + // Read localization manifest file that contains list of available languages + let localesManifest = JSON.parse(readURI(rootURI + "locales.json")); + let locales = localesManifest.locales; + + let localeFile = null; + // Select exact matching first + if (locales.indexOf(preferred) != -1) { + localeFile = preferred; + } + // Then ignore yy in "xx-yy" pattern. + // Ex: accept "fr-FR", if `preferred` is "fr" + else { + let prefix = preferred.replace(/-.*$/, ""); + for each(let filename in locales) { + if (filename.indexOf(prefix + "-") == 0) { + localeFile = filename; + break; + } + } + } + if (!localeFile) + return null; + + return rootURI + "locale/" + localeFile + ".json"; +} + +function init() { + // First, search for a locale file: + let preferred = prefs.get("general.useragent.locale", "en-US"); + let localeURI = searchAddonLocaleFile(preferred); + if (!localeURI) + return; + + let manifestJSON = readURI(localeURI); + let manifest = JSON.parse(manifestJSON); + + // 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 = manifest; +} +init(); |