Bug 1258199: [webext] Return an empty string for missing keys in getMessage. r?bsilverberg
MozReview-Commit-ID: KEQYq4nZbfk
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -115,17 +115,17 @@ var api = context => {
return context.lastError;
},
inIncognitoContext: PrivateBrowsingUtils.isContentWindowPrivate(context.contentWindow),
},
i18n: {
getMessage: function(messageName, substitutions) {
- return context.extension.localizeMessage(messageName, substitutions);
+ return context.extension.localizeMessage(messageName, substitutions, {cloneScope: context.cloneScope});
},
getAcceptLanguages: function(callback) {
let result = context.extension.localeData.acceptLanguages;
return context.wrapPromise(Promise.resolve(result), callback);
},
getUILanguage: function() {
--- a/toolkit/components/extensions/ExtensionUtils.jsm
+++ b/toolkit/components/extensions/ExtensionUtils.jsm
@@ -312,16 +312,17 @@ class BaseContext {
}
}
}
function LocaleData(data) {
this.defaultLocale = data.defaultLocale;
this.selectedLocale = data.selectedLocale;
this.locales = data.locales || new Map();
+ this.missingKeys = new Set();
// Map(locale-name -> Map(message-key -> localized-string))
//
// Contains a key for each loaded locale, each of which is a
// Map of message keys to their localized strings.
this.messages = data.messages || new Map();
if (data.builtinMessages) {
@@ -343,18 +344,26 @@ LocaleData.prototype = {
BUILTIN: "@@BUILTIN_MESSAGES",
has(locale) {
return this.messages.has(locale);
},
// https://developer.chrome.com/extensions/i18n
- localizeMessage(message, substitutions = [], locale = this.selectedLocale, defaultValue = "??") {
- let locales = new Set([this.BUILTIN, locale, this.defaultLocale]
+ localizeMessage(message, substitutions = [], options = {}) {
+ let defaultOptions = {
+ locale: this.selectedLocale,
+ defaultValue: "",
+ cloneScope: null,
+ };
+
+ options = Object.assign(defaultOptions, options);
+
+ let locales = new Set([this.BUILTIN, options.locale, this.defaultLocale]
.filter(locale => this.messages.has(locale)));
// Message names are case-insensitive, so normalize them to lower-case.
message = message.toLowerCase();
for (let locale of locales) {
let messages = this.messages.get(locale);
if (messages.has(message)) {
let str = messages.get(message);
@@ -393,18 +402,25 @@ LocaleData.prototype = {
return rtl ? "ltr" : "rtl";
} else if (message == "@@bidi_start_edge") {
return rtl ? "right" : "left";
} else if (message == "@@bidi_end_edge") {
return rtl ? "left" : "right";
}
}
- Cu.reportError(`Unknown localization message ${message}`);
- return defaultValue;
+ if (!this.missingKeys.has(message)) {
+ let error = `Unknown localization message ${message}`;
+ if (options.cloneScope) {
+ error = new options.cloneScope.Error(error);
+ }
+ Cu.reportError(error);
+ this.missingKeys.add(message);
+ }
+ return options.defaultValue;
},
// Localize a string, replacing all |__MSG_(.*)__| tokens with the
// matching string from the current locale, as determined by
// |this.selectedLocale|.
//
// This may not be called before calling either |initLocale| or
// |initAllLocales|.
--- a/toolkit/components/extensions/ext-i18n.js
+++ b/toolkit/components/extensions/ext-i18n.js
@@ -6,17 +6,17 @@ Cu.import("resource://gre/modules/Extens
var {
detectLanguage,
} = ExtensionUtils;
extensions.registerSchemaAPI("i18n", null, (extension, context) => {
return {
i18n: {
getMessage: function(messageName, substitutions) {
- return extension.localizeMessage(messageName, substitutions);
+ return extension.localizeMessage(messageName, substitutions, {cloneScope: context.cloneScope});
},
getAcceptLanguages: function() {
let result = extension.localeData.acceptLanguages;
return Promise.resolve(result);
},
getUILanguage: function() {
--- a/toolkit/components/extensions/test/mochitest/test_ext_i18n.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_i18n.html
@@ -23,20 +23,20 @@ add_task(function* test_i18n() {
let url = browser.runtime.getURL("/");
assertEq(url, `moz-extension://${_("@@extension_id")}/`, "@@extension_id builtin message");
assertEq("Foo.", _("Foo"), "Simple message in selected locale.");
assertEq("(bar)", _("bar"), "Simple message fallback in default locale.");
- assertEq("??", _("some-unknown-locale-string"), "Unknown locale string.");
+ assertEq("", _("some-unknown-locale-string"), "Unknown locale string.");
- assertEq("??", _("@@unknown_builtin_string"), "Unknown built-in string.");
- assertEq("??", _("@@bidi_unknown_builtin_string"), "Unknown built-in bidi string.");
+ assertEq("", _("@@unknown_builtin_string"), "Unknown built-in string.");
+ assertEq("", _("@@bidi_unknown_builtin_string"), "Unknown built-in bidi string.");
assertEq("Føo.", _("Föo"), "Multi-byte message in selected locale.");
let substitutions = [];
substitutions[4] = "5";
substitutions[13] = "14";
assertEq("'$0' '14' '' '5' '$$$$' '$'.", _("basic_substitutions", substitutions),