Reputation: 683
I am trying to localize my extension's manifest file, of which the beginning looks as following:
{
"name": "__MSG_appName__",
"version": "1.0",
"manifest_version": 2,
"description": "__MSG_appDescription__",
"options_page": "__MSG_optionsPage__",
My message.json file looks like this:
{
"appName": {
"message": "The Great Grouper",
"description": "The name of the application"
},
"appDescription": {
"message": "Flooded with tabs? Store them easily into groups, reopen them whenever you feel like it.",
"description": "The description of the application"
},
"popupPage" : {
"message": "popup.html"
},
"welcomePage": {
"message": "welcome.html"
},
"optionsPage": {
"message": "options.html"
},
the MSG_appName and MSG_appDescription work just fine, but not the MSG_optionsPage, which throws me the following error:
Could not load options page '__MSG_optionsPage__'.
What have I done that Chrome hates me?
Upvotes: 2
Views: 2727
Reputation: 73596
As per the source code LocalizeManifest
function localizes only text strings in the manifest file such as name
, description
and other descriptive labels, and web URLs, and CSS files. This is how chrome.i18n API works: one local layout file with message placeholders that are fetched from a corresponding language definition file in _locales folder.
Unfortunately, Chrome won't autolocalize your html files. So just make one options.html
and use placeholders for all localizable strings it has, then fetch the localized values in options.js script manually.
message.json:
"optionsLabel1": {
"message": "This is a <strong>cool</strong> label"
},
manifest.json:
"options_page": "options.html",
options.html:
.............
<label id="label1"></label>
.............
<script src="options.js"></script>
</body>
options.js:
document.getElementById('label1').innerHTML = chrome.i18n.getMessage('optionsLabel1');
In case you have a lot of localizable strings the above primitive JS code could be enhanced to translate the current document on-the-fly replacing the placeholders with actual text before it's shown on the page:
options.html:
<head>
<script src="localizehtml.js"></script> <!-- should be the first -->
<title tl="optionsTitle"></title>
</head>
<body>
.............
<h1 tl="optionsHeader"></h1>
<label tl="html:optionsLabel1" for="input1"></label>
<input tl="placeholder:optionsInput1" id="input1"></input>
.............
<script src="options.js"></script>
</body>
localizehtml.js:
new MutationObserver(function(mutations) {
for (var mutation of mutations) {
translateNodes(mutation.addedNodes);
}
}).observe(document, {subtree: true, childList: true});
function translateNodes(nodes)
for (var node of nodes) {
if (node.nodeType != 1) // skip if not ELEMENT_NODE
continue;
var tl = node.getAttribute('tl');
if (!tl)
continue;
node.removeAttribute('tl');
var hasTarget = tl.indexOf(':') > 0;
var target = hasTarget ? tl.split(':')[0] : '';
var msgId = hasTarget ? tl.split(':')[1] : tl;
var message = chrome.i18n.getMessage(msgId);
switch (target) {
case 'html':
node.innerHTML = message;
break;
case '':
case 'text':
node.textContent = message;
break;
default:
node.setAttribute(target, message);
}
}
}
There are other methods of on-the-fly localization in HTML files, for example custom elements.
Upvotes: 2