OK, just had a play around with that idea, and this is my version with arguments, allowing you to do translations with syntax like “days?3|title”. Note that I replaced the ternary operator out of personal preference, as I don’t think heavy-weight statements should be run as the result of a ternary operator. I also changed to use HTML, as I think it’s fine to include HTML in translations using the placeholders feature, like this:
"optionsContact": {
"message": "Send bug reports to $MAILTO$.",
"placeholders": {
"mailto": {"content": "<a href='mailto:support@foo.com'>support@foo.com</a>"}
}
}
Not including it in the translations, I would need to make an assumption about sentence structure for all languages.
The code is:
for (const elem of document.querySelectorAll("[data-i18n]")) {
let [stub, attr] = elem.dataset.i18n.split("|", 2);
stub = stub.split("?");
let text = browser.i18n.getMessage(stub[0], stub.slice(1));
if (attr)
elem[attr] = text;
else
elem.insertAdjacentHTML("beforeend", text);
}
I also extended that idea to include number localisation with the # character. So, you can just add a # to the key to indicate that any numbers should be localised e.g. “days#?3”, or to localise a number without any translations, you can do “#123”. The final code is:
function translate() {
var num_format = new Intl.NumberFormat();
for (const elem of document.querySelectorAll("[data-i18n]")) {
let [stub, attr] = elem.dataset.i18n.split("|", 2);
stub = stub.split("?");
let [key, format_num] = stub[0].split("#");
let text;
if (key)
text = browser.i18n.getMessage(key, stub.slice(1));
else
text = format_num;
if (format_num !== undefined)
text = text.replace(/\d+/g, num_format.format);
if (attr)
elem[attr] = text;
else
elem.insertAdjacentHTML("beforeend", text);
}
}
document.addEventListener("DOMContentLoaded", translate);
I think that now handles all the use cases I’ve encountered, and is still fairly concise.