From 7307a9a1b7bd2497f3bdecc7dfeb6ac819b56171 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Fri, 25 Nov 2022 14:11:19 +0400 Subject: [PATCH 01/15] First translation on the welcome page --- static/skin/i18n/en.json | 1 + static/skin/i18n/qqq.json | 2 +- static/skin/i18n/test.json | 1 + static/skin/index.js | 11 +++++++++-- static/templates/index.html | 1 + test/server.cpp | 5 +++-- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/static/skin/i18n/en.json b/static/skin/i18n/en.json index bf8441fc1..e2ce7a463 100644 --- a/static/skin/i18n/en.json +++ b/static/skin/i18n/en.json @@ -28,4 +28,5 @@ , "random-page-button-text": "Go to a randomly selected page" , "searchbox-tooltip": "Search '{{BOOK_TITLE}}'" , "confusion-of-tongues": "Two or more books in different languages would participate in search, which may lead to confusing results." + , "welcome-page-overzealous-filter": "No result. Would you like to reset filter?" } diff --git a/static/skin/i18n/qqq.json b/static/skin/i18n/qqq.json index 2175d24a1..6a1c17236 100644 --- a/static/skin/i18n/qqq.json +++ b/static/skin/i18n/qqq.json @@ -29,5 +29,5 @@ "library-button-text": "Tooltip of the button leading to the welcome page", "home-button-text": "Tooltip of the button leading to the main page of a book", "random-page-button-text": "Tooltip of the button opening a randomly selected page", - "searchbox-tooltip": "Tooltip displayed for the search box" + , "welcome-page-overzealous-filter": "Text shown when book filtering on the welcome page produces zero results" } diff --git a/static/skin/i18n/test.json b/static/skin/i18n/test.json index a96eac241..bf8bd49f0 100644 --- a/static/skin/i18n/test.json +++ b/static/skin/i18n/test.json @@ -17,4 +17,5 @@ , "home-button-text": "[I18N TESTING] Jump to the main page of '{{BOOK_TITLE}}'" , "random-page-button-text": "[I18N TESTING] I am tired of determinism" , "searchbox-tooltip": "[I18N TESTING] Let's search in '{{BOOK_TITLE}}'" + , "welcome-page-overzealous-filter": "[I18N TESTING] Nothing found. Reset filter" } diff --git a/static/skin/index.js b/static/skin/index.js index 036e18516..9c7fe5613 100644 --- a/static/skin/index.js +++ b/static/skin/index.js @@ -298,7 +298,7 @@ const kiwixHomeBody = document.querySelector('.kiwixHomeBody'); const divTag = document.createElement('div'); divTag.setAttribute('class', 'noResults'); - divTag.innerHTML = `No result. Would you like to reset filter?`; + divTag.innerHTML = $t("welcome-page-overzealous-filter"); kiwixHomeBody.append(divTag); kiwixHomeBody.setAttribute('style', 'display: flex; justify-content: center; align-items: center'); loader.setAttribute('style', 'position: absolute; top: 50%'); @@ -462,7 +462,7 @@ } }); - window.onload = async () => { + async function onload() { iso = new Isotope( '.book__list', { itemSelector: '.book', getSortData:{ @@ -508,6 +508,13 @@ } updateFeedLink(); setCookie(filterCookieName, params.toString()); + }; + + // required by i18n.js:setUserLanguage() + window.setPermanentGlobalCookie = function(name, value) { + document.cookie = `${name}=${value};path=${root};max-age=31536000`; } + + window.onload = () => { setUserLanguage(getUserLanguage(), onload); } })(); diff --git a/static/templates/index.html b/static/templates/index.html index 0274e9a3a..f2a80342e 100644 --- a/static/templates/index.html +++ b/static/templates/index.html @@ -37,6 +37,7 @@ src: url("{{root}}/skin/fonts/Roboto.ttf?KIWIXCACHEID") format("truetype"); } + diff --git a/test/server.cpp b/test/server.cpp index 23f05135b..c0d3fa7a9 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -63,7 +63,7 @@ const ResourceCollection resources200Compressible{ { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=316dbc21" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.js" }, - { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=b0cc9d6b" }, + { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=ffc9a141" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js?cacheid=ecde2bb3" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/isotope.pkgd.min.js" }, @@ -280,9 +280,10 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/index.css?cacheid=316dbc21" src: url("/ROOT%23%3F/skin/fonts/Poppins.ttf?cacheid=af705837") format("truetype"); src: url("/ROOT%23%3F/skin/fonts/Roboto.ttf?cacheid=84d10248") format("truetype"); + - + )EXPECTEDRESULT" }, From d42fa224505d0e295ac84e2ab53b07d2dac54242 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 26 Nov 2022 13:04:55 +0400 Subject: [PATCH 02/15] Translation of static text on the welcome page Note that i18n/test.json overgrew the non-compressible size limit, that is why it had to move to a richer neighbourhood. --- static/skin/i18n/en.json | 4 ++++ static/skin/i18n/qqq.json | 5 +++++ static/skin/i18n/test.json | 4 ++++ static/skin/index.js | 10 ++++++++++ static/templates/index.html | 2 +- test/server.cpp | 10 +++++----- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/static/skin/i18n/en.json b/static/skin/i18n/en.json index e2ce7a463..b8f8abf4b 100644 --- a/static/skin/i18n/en.json +++ b/static/skin/i18n/en.json @@ -29,4 +29,8 @@ , "searchbox-tooltip": "Search '{{BOOK_TITLE}}'" , "confusion-of-tongues": "Two or more books in different languages would participate in search, which may lead to confusing results." , "welcome-page-overzealous-filter": "No result. Would you like to reset filter?" + , "powered-by-kiwix-html": "Powered by Kiwix" + , "search": "Search" + , "book-filtering-all-categories": "All categories" + , "book-filtering-all-languages": "All languages" } diff --git a/static/skin/i18n/qqq.json b/static/skin/i18n/qqq.json index 6a1c17236..b33b3929b 100644 --- a/static/skin/i18n/qqq.json +++ b/static/skin/i18n/qqq.json @@ -29,5 +29,10 @@ "library-button-text": "Tooltip of the button leading to the welcome page", "home-button-text": "Tooltip of the button leading to the main page of a book", "random-page-button-text": "Tooltip of the button opening a randomly selected page", + "searchbox-tooltip": "Tooltip displayed for the search box in the viewer" , "welcome-page-overzealous-filter": "Text shown when book filtering on the welcome page produces zero results" + , "powered-by-kiwix-html": "Link to Kiwix website" + , "search": "A general search action (text displayed on search buttons or as aplaceholder in searchboxes)" + , "book-filtering-all-categories": "Choosing this filter will disable filtering of books by category" + , "book-filtering-all-languages": "Choosing this filter will disable filtering of books by language" } diff --git a/static/skin/i18n/test.json b/static/skin/i18n/test.json index bf8bd49f0..6e5c42d74 100644 --- a/static/skin/i18n/test.json +++ b/static/skin/i18n/test.json @@ -18,4 +18,8 @@ , "random-page-button-text": "[I18N TESTING] I am tired of determinism" , "searchbox-tooltip": "[I18N TESTING] Let's search in '{{BOOK_TITLE}}'" , "welcome-page-overzealous-filter": "[I18N TESTING] Nothing found. Reset filter" + , "powered-by-kiwix-html": "[I18N TESTING] Powered by Kiwix (nominal power: 1.23 kW)" + , "search": "[I18N Search TESTING]" + , "book-filtering-all-categories": "All [I18N TESTING] categories" + , "book-filtering-all-languages": "All [I18N TESTING] languages" } diff --git a/static/skin/index.js b/static/skin/index.js index 9c7fe5613..1ce0973b4 100644 --- a/static/skin/index.js +++ b/static/skin/index.js @@ -462,6 +462,15 @@ } }); + function updateUIText() { + footer.innerHTML = $t("powered-by-kiwix-html"); + const searchText = $t("search"); + document.getElementById('searchFilter').placeholder = searchText; + document.getElementById('searchButton').value = searchText; + document.getElementById('categoryFilter').children[0].innerHTML = $t("book-filtering-all-categories"); + document.getElementById('languageFilter').children[0].innerHTML = $t("book-filtering-all-languages"); + } + async function onload() { iso = new Isotope( '.book__list', { itemSelector: '.book', @@ -478,6 +487,7 @@ } }); footer = document.getElementById('kiwixfooter'); + updateUIText(); fadeOutDiv = document.getElementById('fadeOut'); loader = document.querySelector('.loader'); await loadAndDisplayOptions('#languageFilter', `${root}/catalog/v2/languages`, 'language'); diff --git a/static/templates/index.html b/static/templates/index.html index f2a80342e..2b2039a19 100644 --- a/static/templates/index.html +++ b/static/templates/index.html @@ -62,7 +62,7 @@
- +
diff --git a/test/server.cpp b/test/server.cpp index c0d3fa7a9..4eb7e2056 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -63,7 +63,7 @@ const ResourceCollection resources200Compressible{ { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=316dbc21" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.js" }, - { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=ffc9a141" }, + { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=73356624" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js?cacheid=ecde2bb3" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/isotope.pkgd.min.js" }, @@ -78,6 +78,9 @@ const ResourceCollection resources200Compressible{ { STATIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf?cacheid=af705837" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Roboto.ttf" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/fonts/Roboto.ttf?cacheid=84d10248" }, + { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/i18n/test.json" }, + // TODO: implement cache management of i18n resources + //{ STATIC_CONTENT, "/ROOT%23%3F/skin/i18n/test.json?cacheid=unknown" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/catalog/search" }, @@ -141,9 +144,6 @@ const ResourceCollection resources200Uncompressible{ { STATIC_CONTENT, "/ROOT%23%3F/skin/search-icon.svg?cacheid=b10ae7ed" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/search_results.css" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/search_results.css?cacheid=76d39c84" }, - { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/i18n/test.json" }, - // TODO: implement cache management of i18n resources - //{ STATIC_CONTENT, "/ROOT%23%3F/skin/i18n/test.json?cacheid=unknown" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/languages.js" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/languages.js?cacheid=fe100348" }, @@ -283,7 +283,7 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/index.css?cacheid=316dbc21" - + )EXPECTEDRESULT" }, From fa7d044037f94c431d6132184bd6f3553e671fca Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 26 Nov 2022 13:36:53 +0400 Subject: [PATCH 03/15] One more translation on the welcome page This translation has to deal with handling of plural forms which is a tricky part of internationalization, but we are not going to complicate things in our code and will offload the headache to translators (they will have to invent a single message for all numbers). --- static/skin/i18n/en.json | 1 + static/skin/i18n/qqq.json | 1 + static/skin/i18n/test.json | 1 + static/skin/index.js | 14 ++++---------- test/server.cpp | 4 ++-- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/static/skin/i18n/en.json b/static/skin/i18n/en.json index b8f8abf4b..332c25ab8 100644 --- a/static/skin/i18n/en.json +++ b/static/skin/i18n/en.json @@ -33,4 +33,5 @@ , "search": "Search" , "book-filtering-all-categories": "All categories" , "book-filtering-all-languages": "All languages" + , "count-of-matching-books": "{{COUNT}} book(s)" } diff --git a/static/skin/i18n/qqq.json b/static/skin/i18n/qqq.json index b33b3929b..ebf8bfbc1 100644 --- a/static/skin/i18n/qqq.json +++ b/static/skin/i18n/qqq.json @@ -35,4 +35,5 @@ , "search": "A general search action (text displayed on search buttons or as aplaceholder in searchboxes)" , "book-filtering-all-categories": "Choosing this filter will disable filtering of books by category" , "book-filtering-all-languages": "Choosing this filter will disable filtering of books by language" + , "count-of-matching-books": "Reporting the count of books matching the filter" } diff --git a/static/skin/i18n/test.json b/static/skin/i18n/test.json index 6e5c42d74..2609b945d 100644 --- a/static/skin/i18n/test.json +++ b/static/skin/i18n/test.json @@ -22,4 +22,5 @@ , "search": "[I18N Search TESTING]" , "book-filtering-all-categories": "All [I18N TESTING] categories" , "book-filtering-all-languages": "All [I18N TESTING] languages" + , "count-of-matching-books": "[I18N TESTING] Number of matching books: {{COUNT}}" } diff --git a/static/skin/index.js b/static/skin/index.js index 1ce0973b4..0f8237f1c 100644 --- a/static/skin/index.js +++ b/static/skin/index.js @@ -262,16 +262,10 @@ } else { toggleFooter(); } - const kiwixResultText = document.querySelector('.kiwixHomeBody__results') - if (results) { - let resultText = `${results} books`; - if (results === 1) { - resultText = `${results} book`; - } - kiwixResultText.innerHTML = resultText; - } else { - kiwixResultText.innerHTML = ``; - } + const text = results + ? $t("count-of-matching-books", {COUNT: results}) + : ''; + document.querySelector('.kiwixHomeBody__results').innerHTML = text; loader.style.display = 'none'; return books; }); diff --git a/test/server.cpp b/test/server.cpp index 4eb7e2056..7f171cdcf 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -63,7 +63,7 @@ const ResourceCollection resources200Compressible{ { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=316dbc21" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.js" }, - { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=73356624" }, + { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=e0a31131" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js?cacheid=ecde2bb3" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/isotope.pkgd.min.js" }, @@ -283,7 +283,7 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/index.css?cacheid=316dbc21" - + )EXPECTEDRESULT" }, From 2825c4c63d2888ee02ed434805155d921cc50de0 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 26 Nov 2022 13:49:18 +0400 Subject: [PATCH 04/15] Fixed links to various download option icons --- static/skin/index.js | 8 ++++---- test/server.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/static/skin/index.js b/static/skin/index.js index 0f8237f1c..7d8dc0fad 100644 --- a/static/skin/index.js +++ b/static/skin/index.js @@ -209,26 +209,26 @@ @@ -209,27 +209,27 @@ diff --git a/test/server.cpp b/test/server.cpp index 00568a7d4..a1277a77d 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -63,7 +63,7 @@ const ResourceCollection resources200Compressible{ { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=316dbc21" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.js" }, - { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=a1d9a5d5" }, + { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=1f5f1cce" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js?cacheid=ecde2bb3" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/isotope.pkgd.min.js" }, @@ -283,7 +283,7 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/index.css?cacheid=316dbc21" - + )EXPECTEDRESULT" }, @@ -294,10 +294,10 @@ R"EXPECTEDRESULT( background-image: url('../skin/search-icon.svg?cacheid=b10a }, { /* url */ "/ROOT%23%3F/skin/index.js", -R"EXPECTEDRESULT( direct download - download hash - download magnet - download torrent +R"EXPECTEDRESULT( ${$t( + ${$t( + ${$t( + ${$t( )EXPECTEDRESULT" }, { From ac742e9da29f64a32f412268a08d0abcb46b12f5 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 9 Feb 2023 15:13:38 +0100 Subject: [PATCH 06/15] Redirection of slashless root URL With non-empty root location, the canonic form of the root URL for a kiwix server is now required to end with a slash (to match the situation for an empty root location). This requirement enables usage of relative URLs on the welcome page and resources/scripts loaded through that page. A slashless root URL is redirected to the slashful version. --- src/server/internalServer.cpp | 28 +++++++++++++++++++--------- src/server/request_context.cpp | 2 +- test/server.cpp | 34 ++++++++++++++++++++++++++++++++++ test/server_testing_tools.h | 34 +++++++++++++++++++++------------- 4 files changed, 75 insertions(+), 23 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 89b2efb13..76d1494f7 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -97,14 +97,19 @@ inline std::string normalizeRootUrl(std::string rootUrl) std::string fullURL2LocalURL(const std::string& fullUrl, const std::string& rootLocation) { - assert(rootLocation.size() > 0 && rootLocation.back() == '/'); if ( kiwix::startsWith(fullUrl, rootLocation) ) { - return fullUrl.substr(rootLocation.size() - 1); + return fullUrl.substr(rootLocation.size()); } else { - return ""; + return "INVALID URL"; } } +std::string getSearchComponent(const RequestContext& request) +{ + const std::string query = request.get_query(); + return query.empty() ? query : "?" + query; +} + Filter get_search_filter(const RequestContext& request, const std::string& prefix="") { auto filter = kiwix::Filter().valid(true).local(true); @@ -415,7 +420,7 @@ InternalServer::InternalServer(Library* library, m_addr(addr), m_port(port), m_root(normalizeRootUrl(root)), - m_rootPrefixOfDecodedURL(m_root + "/"), + m_rootPrefixOfDecodedURL(m_root), m_nbThreads(nbThreads), m_multizimSearchLimit(multizimSearchLimit), m_verbose(verbose), @@ -585,6 +590,13 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r + urlNotFoundMsg; } + if ( request.get_url() == "" ) { + // Redirect /ROOT_LOCATION to /ROOT_LOCATION/ (note the added slash) + // so that relative URLs are resolved correctly + const std::string query = getSearchComponent(request); + return Response::build_redirect(*this, m_root + "/" + query); + } + const ETag etag = get_matching_if_none_match_etag(request, getLibraryId()); if ( etag ) return Response::build_304(*this, etag); @@ -623,11 +635,9 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r if (isEndpointUrl(url, "catch")) return handle_catch(request); - std::string contentUrl = m_root + "/content" + urlEncode(url); - const std::string query = request.get_query(); - if ( ! query.empty() ) - contentUrl += "?" + query; - return Response::build_redirect(*this, contentUrl); + const std::string contentUrl = m_root + "/content" + urlEncode(url); + const std::string query = getSearchComponent(request); + return Response::build_redirect(*this, contentUrl + query); } catch (std::exception& e) { fprintf(stderr, "===== Unhandled error : %s\n", e.what()); return HTTP500Response(*this, request) diff --git a/src/server/request_context.cpp b/src/server/request_context.cpp index 017521666..9e0b965c0 100644 --- a/src/server/request_context.cpp +++ b/src/server/request_context.cpp @@ -181,7 +181,7 @@ std::string RequestContext::get_root_path() const { } bool RequestContext::is_valid_url() const { - return !url.empty(); + return url.empty() || url[0] == '/'; } ByteRange RequestContext::get_range() const { diff --git a/test/server.cpp b/test/server.cpp index a1277a77d..94a3da5c9 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -359,6 +359,10 @@ TEST_F(ServerTest, 400) const char* urls404[] = { "/", "/zimfile", + "/ROOT", + "/ROOT%23%", + "/ROOT%23%3", + "/ROOT%23%3Fxyz", "/ROOT%23%3F/skin/non-existent-skin-resource", "/ROOT%23%3F/skin/autoComplete.min.js?cacheid=wrongcacheid", "/ROOT%23%3F/catalog", @@ -1268,6 +1272,36 @@ TEST_F(ServerTest, UserLanguageControl) } } +TEST_F(ServerTest, SlashlessRootURLIsRedirectedToSlashfulURL) +{ + const std::pair test_data[] = { + // URL redirect + { "/ROOT%23%3F", "/ROOT%23%3F/" }, + { "/ROOT%23%3F?abcd=123&xyz=890", "/ROOT%23%3F/?abcd=123&xyz=890" } + }; + + for ( const auto& t : test_data ) + { + const TestContext ctx{ {"url", t.first} }; + const auto g = zfs1_->GET(t.first); + ASSERT_EQ(302, g->status) << ctx; + ASSERT_TRUE(g->has_header("Location")) << ctx; + ASSERT_EQ(g->get_header_value("Location"), t.second) << ctx; + ASSERT_EQ(getCacheControlHeader(*g), "max-age=0, must-revalidate") << ctx; + ASSERT_FALSE(g->has_header("ETag")) << ctx; + } +} + +TEST_F(ServerTest, EmptyRootIsNotRedirected) +{ + ZimFileServer::Cfg serverCfg; + serverCfg.root = ""; + + resetServer(serverCfg); + + ASSERT_EQ(200, zfs1_->GET("/")->status); +} + TEST_F(ServerTest, RandomPageRedirectsToAnExistingArticle) { auto g = zfs1_->GET("/ROOT%23%3F/random?content=zimfile"); diff --git a/test/server_testing_tools.h b/test/server_testing_tools.h index 6fa147588..777bb48e8 100644 --- a/test/server_testing_tools.h +++ b/test/server_testing_tools.h @@ -68,10 +68,18 @@ public: // types DEFAULT_OPTIONS = WITH_TASKBAR | WITH_LIBRARY_BUTTON }; + struct Cfg + { + std::string root = "ROOT#?"; + Options options = DEFAULT_OPTIONS; + + Cfg(Options opts = DEFAULT_OPTIONS) : options(opts) {} + }; + public: // functions - ZimFileServer(int serverPort, Options options, std::string libraryFilePath); + ZimFileServer(int serverPort, Cfg cfg, std::string libraryFilePath); ZimFileServer(int serverPort, - Options options, + Cfg cfg, const FilePathCollection& zimpaths, std::string indexTemplateString = ""); ~ZimFileServer(); @@ -95,12 +103,12 @@ private: // data std::unique_ptr nameMapper; std::unique_ptr server; std::unique_ptr client; - const Options options = DEFAULT_OPTIONS; + const Cfg cfg; }; -ZimFileServer::ZimFileServer(int serverPort, Options _options, std::string libraryFilePath) +ZimFileServer::ZimFileServer(int serverPort, Cfg _cfg, std::string libraryFilePath) : manager(&this->library) -, options(_options) +, cfg(_cfg) { if ( kiwix::isRelativePath(libraryFilePath) ) libraryFilePath = kiwix::computeAbsolutePath(kiwix::getCurrentDirectory(), libraryFilePath); @@ -109,11 +117,11 @@ ZimFileServer::ZimFileServer(int serverPort, Options _options, std::string libra } ZimFileServer::ZimFileServer(int serverPort, - Options _options, + Cfg _cfg, const FilePathCollection& zimpaths, std::string indexTemplateString) : manager(&this->library) -, options(_options) +, cfg(_cfg) { for ( const auto& zimpath : zimpaths ) { if (!manager.addBookFromPath(zimpath, zimpath, "", false)) @@ -125,19 +133,19 @@ ZimFileServer::ZimFileServer(int serverPort, void ZimFileServer::run(int serverPort, std::string indexTemplateString) { const std::string address = "127.0.0.1"; - if (options & NO_NAME_MAPPER) { + if (cfg.options & NO_NAME_MAPPER) { nameMapper.reset(new kiwix::IdNameMapper()); } else { nameMapper.reset(new kiwix::HumanReadableNameMapper(library, false)); } server.reset(new kiwix::Server(&library, nameMapper.get())); - server->setRoot("ROOT#?"); + server->setRoot(cfg.root); server->setAddress(address); server->setPort(serverPort); server->setNbThreads(2); server->setVerbose(false); - server->setTaskbar(options & WITH_TASKBAR, options & WITH_LIBRARY_BUTTON); - server->setBlockExternalLinks(options & BLOCK_EXTERNAL_LINKS); + server->setTaskbar(cfg.options & WITH_TASKBAR, cfg.options & WITH_LIBRARY_BUTTON); + server->setBlockExternalLinks(cfg.options & BLOCK_EXTERNAL_LINKS); server->setMultiZimSearchLimit(3); if (!indexTemplateString.empty()) { server->setIndexTemplateString(indexTemplateString); @@ -171,9 +179,9 @@ protected: resetServer(ZimFileServer::DEFAULT_OPTIONS); } - void resetServer(ZimFileServer::Options options) { + void resetServer(ZimFileServer::Cfg cfg) { zfs1_.reset(); - zfs1_.reset(new ZimFileServer(SERVER_PORT, options, ZIMFILES)); + zfs1_.reset(new ZimFileServer(SERVER_PORT, cfg, ZIMFILES)); } void TearDown() override { From 351bc872316c670b706f03ba71e06fd7e05d3601 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 9 Feb 2023 15:30:37 +0100 Subject: [PATCH 07/15] Moved initUILanguageSelector() into i18n.js --- static/skin/i18n.js | 12 ++++++++++++ static/skin/viewer.js | 12 +----------- static/viewer.html | 2 +- test/server.cpp | 10 +++++----- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/static/skin/i18n.js b/static/skin/i18n.js index d451f11b4..6c5eb0ad1 100644 --- a/static/skin/i18n.js +++ b/static/skin/i18n.js @@ -97,6 +97,18 @@ function setUserLanguage(lang, callback) { Translations.whenReady(callback); } +function initUILanguageSelector(activeLanguage, languageChangeCallback) { + const languageSelector = document.getElementById("ui_language"); + for (const lang of uiLanguages ) { + const lang_name = Object.getOwnPropertyNames(lang)[0]; + const lang_code = lang[lang_name]; + const is_selected = lang_code == activeLanguage; + languageSelector.appendChild(new Option(lang_name, lang_code, is_selected, is_selected)); + } + languageSelector.onchange = languageChangeCallback; +} + window.$t = $t; window.getUserLanguage = getUserLanguage; window.setUserLanguage = setUserLanguage; +window.initUILanguageSelector = initUILanguageSelector; diff --git a/static/skin/viewer.js b/static/skin/viewer.js index db7bc2ba8..3349a2d8b 100644 --- a/static/skin/viewer.js +++ b/static/skin/viewer.js @@ -416,16 +416,6 @@ function makeURL(search, hash) { return url; } -function initUILanguageSelector() { - const languageSelector = document.getElementById("ui_language"); - for (const lang of uiLanguages ) { - const lang_name = Object.getOwnPropertyNames(lang)[0]; - const lang_code = lang[lang_name]; - const is_selected = lang_code == viewerState.uiLanguage; - languageSelector.appendChild(new Option(lang_name, lang_code, is_selected, is_selected)); - } -} - function updateUILanguageSelector(userLang) { console.log(`updateUILanguageSelector(${userLang})`); const languageSelector = document.getElementById("ui_language"); @@ -481,7 +471,7 @@ function setupViewer() { document.getElementById("kiwix_serve_taskbar_library_button").remove(); } - initUILanguageSelector(); + initUILanguageSelector(viewerState.uiLanguage, changeUILanguage); setupSuggestions(); // cybook hack diff --git a/static/viewer.html b/static/viewer.html index 4c66abbcd..2fcbfb9e6 100644 --- a/static/viewer.html +++ b/static/viewer.html @@ -29,7 +29,7 @@