diff --git a/static/skin/i18n.js b/static/skin/i18n.js
index ed92d6f3..94aee785 100644
--- a/static/skin/i18n.js
+++ b/static/skin/i18n.js
@@ -23,7 +23,8 @@ const Translations = {
return;
const errorMsg = `Error loading translations for language '${lang}': `;
- this.promises[lang] = fetch(`./skin/i18n/${lang}.json`).then(async (resp) => {
+ const translationJsonUrl = import.meta.resolve(`./i18n/${lang}.json`);
+ this.promises[lang] = fetch(translationJsonUrl).then(async (resp) => {
if ( resp.ok ) {
this.data[lang] = JSON.parse(await resp.text());
} else {
@@ -190,8 +191,40 @@ function initUILanguageSelector(activeLanguage, languageChangeCallback) {
languageSelector.onchange = languageChangeCallback;
}
+function parseDom(html) {
+ const domParser = new DOMParser();
+ return domParser.parseFromString(html, "text/html").documentElement;
+}
+
+function translatePageInWindow(w) {
+ if ( w.KIWIX_RESPONSE_TEMPLATE && w.KIWIX_RESPONSE_DATA ) {
+ const template = parseDom(w.KIWIX_RESPONSE_TEMPLATE).textContent;
+
+ // w.KIWIX_RESPONSE_DATA may belong to a different context and running
+ // I18n.render() on it directly won't work correctly
+ // because the type checks (obj.__proto__ == ???.prototype) in
+ // I18n.instantiateParameterizedMessages() will fail (String.prototype
+ // refers to different objects in different contexts).
+ // Work arround that issue by copying the object into our context.
+ const params = JSON.parse(JSON.stringify(w.KIWIX_RESPONSE_DATA));
+
+ const newHtml = I18n.render(template, params);
+ w.document.documentElement.innerHTML = parseDom(newHtml).innerHTML;
+ }
+}
+
+function translateSelf() {
+ if ( window.KIWIX_RESPONSE_TEMPLATE && window.KIWIX_RESPONSE_DATA ) {
+ setUserLanguage(getUserLanguage(), () => {
+ translatePageInWindow(window)
+ });
+ }
+};
+
window.$t = $t;
window.getUserLanguage = getUserLanguage;
window.setUserLanguage = setUserLanguage;
window.initUILanguageSelector = initUILanguageSelector;
+window.translatePageInWindow = translatePageInWindow;
window.I18n = I18n;
+window.addEventListener('load', translateSelf);
diff --git a/static/skin/viewer.js b/static/skin/viewer.js
index bbdbc74d..0b7a6787 100644
--- a/static/skin/viewer.js
+++ b/static/skin/viewer.js
@@ -262,22 +262,7 @@ function handle_location_hash_change() {
}
function translateErrorPageIfNeeded() {
- const cw = contentIframe.contentWindow;
- if ( cw.KIWIX_RESPONSE_TEMPLATE && cw.KIWIX_RESPONSE_DATA ) {
- const template = htmlDecode(cw.KIWIX_RESPONSE_TEMPLATE);
-
- // cw.KIWIX_RESPONSE_DATA belongs to the iframe context and running
- // I18n.render() on it directly in the top context doesn't work correctly
- // because the type checks (obj.__proto__ == ???.prototype) in
- // I18n.instantiateParameterizedMessages() always fail (String.prototype
- // refers to different objects in different contexts).
- // Work arround that issue by copying the object into our context.
- const params = JSON.parse(JSON.stringify(cw.KIWIX_RESPONSE_DATA));
-
- const html = I18n.render(template, params);
- const htmlDoc = new DOMParser().parseFromString(html, "text/html");
- cw.document.documentElement.innerHTML = htmlDoc.documentElement.innerHTML;
- }
+ translatePageInWindow(contentIframe.contentWindow);
}
function handle_content_url_change() {
diff --git a/static/templates/captured_external.html b/static/templates/captured_external.html
index 2e22b4bd..24379880 100644
--- a/static/templates/captured_external.html
+++ b/static/templates/captured_external.html
@@ -5,10 +5,11 @@
{{external_link_detected}}
-{{#KIWIX_RESPONSE_DATA}}
+ {{/KIWIX_RESPONSE_DATA}}
+
diff --git a/test/server.cpp b/test/server.cpp
index d79c7d02..dfd5b81b 100644
--- a/test/server.cpp
+++ b/test/server.cpp
@@ -61,7 +61,7 @@ const ResourceCollection resources200Compressible{
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/error.css" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/error.css?cacheid=b3fa90cf" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/i18n.js" },
- { STATIC_CONTENT, "/ROOT%23%3F/skin/i18n.js?cacheid=071abc9a" },
+ { STATIC_CONTENT, "/ROOT%23%3F/skin/i18n.js?cacheid=e9a10ac1" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=ae79e41a" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.js" },
@@ -77,7 +77,7 @@ const ResourceCollection resources200Compressible{
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css?cacheid=80d56607" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/viewer.js" },
- { STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=d6f747f5" },
+ { STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=7f05bf6c" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf?cacheid=af705837" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Roboto.ttf" },
@@ -296,7 +296,7 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/kiwix.css?cacheid=3948b846"
-
+
@@ -331,9 +331,9 @@ R"EXPECTEDRESULT(
-
+
-
+
const blankPageUrl = root + "/skin/blank.html?cacheid=6b1fa032";
@@ -355,7 +355,8 @@ R"EXPECTEDRESULT(
- window.KIWIX_RESPONSE_TEMPLATE = "<!DOCTYPE html>\n<html>\n <head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />\n <title>{{external_link_detected}}</title>\n <link type="text/css" href="{{root}}/skin/error.css?cacheid=b3fa90cf" rel="Stylesheet" />\n{{#KIWIX_RESPONSE_DATA}} <script>\n window.KIWIX_RESPONSE_TEMPLATE = "{{KIWIX_RESPONSE_TEMPLATE}}";\n window.KIWIX_RESPONSE_DATA = {{{KIWIX_RESPONSE_DATA}}};\n </script>{{/KIWIX_RESPONSE_DATA}}\n </head>\n <body>\n <header>\n <img src="{{root}}/skin/blocklink.svg?cacheid=bd56b116"\n alt="Caution!"\n aria-label="Caution!"\n title="Caution!">\n </header>\n <section class="intro">\n <h1>{{external_link_detected}}</h1>\n <p>You are about to leave Kiwix's ZIM reader to go online to</p>\n <p><a href="{{source}}">{{ source }}</a></p>\n </section>\n <section class="advice">\n <p>The link you're trying to access is not part of your offline package and requires an internet connection.</p>\n <p>If you can go online, you can attempt to open the link.</p>\n <p>You can otherwise return to your ZIM's offline content by using your browser's back button.</p>\n </section>\n </body>\n</html>\n";
+
+ window.KIWIX_RESPONSE_TEMPLATE = "<!DOCTYPE html>\n<html>\n <head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />\n <title>{{external_link_detected}}</title>\n <link type="text/css" href="{{root}}/skin/error.css?cacheid=b3fa90cf" rel="Stylesheet" />\n <script type="module" src="{{root}}/skin/i18n.js?cacheid=e9a10ac1"></script>\n <script>\n window.KIWIX_RESPONSE_TEMPLATE = "{{KIWIX_RESPONSE_TEMPLATE}}";\n window.KIWIX_RESPONSE_DATA = {{{KIWIX_RESPONSE_DATA}}};\n </script>\n </head>\n <body>\n <header>\n <img src="{{root}}/skin/blocklink.svg?cacheid=bd56b116"\n alt="Caution!"\n aria-label="Caution!"\n title="Caution!">\n </header>\n <section class="intro">\n <h1>{{external_link_detected}}</h1>\n <p>You are about to leave Kiwix's ZIM reader to go online to</p>\n <p><a href="{{source}}">{{ source }}</a></p>\n </section>\n <section class="advice">\n <p>The link you're trying to access is not part of your offline package and requires an internet connection.</p>\n <p>If you can go online, you can attempt to open the link.</p>\n <p>You can otherwise return to your ZIM's offline content by using your browser's back button.</p>\n </section>\n </body>\n</html>\n";
