Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translation of search results page #1046

Merged
merged 6 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/search_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ class SearchRenderer
this->pageLength = pageLength;
}

/**
* set user language
*/
void setUserLang(const std::string& lang){
this->userlang = lang;
}

/**
* Generate the html page with the resutls of the search.
*
Expand Down Expand Up @@ -105,6 +112,7 @@ class SearchRenderer
unsigned int pageLength;
unsigned int estimatedResultCount;
unsigned int resultStart;
std::string userlang = "en";
};


Expand Down
63 changes: 54 additions & 9 deletions src/search_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,42 @@
#include "libkiwix-resources.h"
#include "tools/stringTools.h"

#include "server/i18n.h"

namespace kiwix
{

namespace
{

ParameterizedMessage searchResultsPageTitleMsg(const std::string& searchPattern)
{
return ParameterizedMessage("search-results-page-title",
{{"SEARCH_PATTERN", searchPattern}}
);
}

ParameterizedMessage searchResultsPageHeaderMsg(const std::string& searchPattern,
const kainjow::mustache::data& r)
{
if ( r.get("count")->string_value() == "0" ) {
return ParameterizedMessage("empty-search-results-page-header",
{{"SEARCH_PATTERN", searchPattern}}
);
} else {
return ParameterizedMessage("search-results-page-header",
{
{"SEARCH_PATTERN", searchPattern},
{"START", r.get("start")->string_value()},
{"END", r.get("end") ->string_value()},
{"COUNT", r.get("count")->string_value()},
}
);
}
}

} // unnamed namespace

/* Constructor */
SearchRenderer::SearchRenderer(zim::SearchResultSet srs,
unsigned int start, unsigned int estimatedResultCount)
Expand Down Expand Up @@ -170,18 +203,27 @@ std::string SearchRenderer::renderTemplate(const std::string& tmpl_str, const Na
result.set("absolutePath", absPathPrefix + urlEncode(path));
result.set("snippet", it.getSnippet());
if (library) {
result.set("bookTitle", library->getBookById(zim_id).getTitle());
const std::string bookTitle = library->getBookById(zim_id).getTitle();
const ParameterizedMessage bookInfoMsg("search-result-book-info",
{{"BOOK_TITLE", bookTitle}}
);
result.set("bookInfo", bookInfoMsg.getText(userlang)); // for HTML
result.set("bookTitle", bookTitle); // for XML
}
if (it.getWordCount() >= 0) {
result.set("wordCount", kiwix::beautifyInteger(it.getWordCount()));
const auto wordCountStr = kiwix::beautifyInteger(it.getWordCount());
const ParameterizedMessage wordCountMsg("word-count",
{{"COUNT", wordCountStr}}
);
result.set("wordCountInfo", wordCountMsg.getText(userlang)); // for HTML
result.set("wordCount", wordCountStr); // for XML
}

items.push_back(result);
}
kainjow::mustache::data results;
results.set("items", items);
results.set("count", kiwix::beautifyInteger(estimatedResultCount));
results.set("hasResults", estimatedResultCount != 0);
results.set("start", kiwix::beautifyInteger(resultStart));
results.set("end", kiwix::beautifyInteger(std::min(resultStart+pageLength-1, estimatedResultCount)));

Expand All @@ -198,12 +240,15 @@ std::string SearchRenderer::renderTemplate(const std::string& tmpl_str, const Na
searchBookQuery
);


kainjow::mustache::data allData;
allData.set("searchProtocolPrefix", searchProtocolPrefix);
allData.set("results", results);
allData.set("pagination", pagination);
allData.set("query", query);
const auto pageHeaderMsg = searchResultsPageHeaderMsg(searchPattern, results);
const kainjow::mustache::object allData{
{"PAGE_TITLE", searchResultsPageTitleMsg(searchPattern).getText(userlang)},
{"PAGE_HEADER", pageHeaderMsg.getText(userlang)},
{"searchProtocolPrefix", searchProtocolPrefix},
{"results", results},
{"pagination", pagination},
{"query", query},
};

kainjow::mustache::mustache tmpl(tmpl_str);

Expand Down
1 change: 1 addition & 0 deletions src/server/internalServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,7 @@ std::unique_ptr<Response> InternalServer::handle_search_request(const RequestCon
renderer.setProtocolPrefix(m_root + "/content/");
renderer.setSearchProtocolPrefix(m_root + "/search");
renderer.setPageLength(pageLength);
renderer.setUserLang(request.get_user_language());
if (request.get_requested_format() == "xml") {
return ContentResponse::build(
renderer.getXml(*mp_nameMapper, mp_library.get()),
Expand Down
5 changes: 5 additions & 0 deletions static/skin/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
, "500-page-text": "An internal server error occured. We are sorry about that :/"
, "fulltext-search-unavailable" : "Fulltext search unavailable"
, "no-search-results": "The fulltext search engine is not available for this content."
, "search-results-page-title": "Search: {{SEARCH_PATTERN}}"
, "search-results-page-header": "Results <b>{{START}}-{{END}}</b> of <b>{{COUNT}}</b> for <b>\"{{{SEARCH_PATTERN}}}\"</b>"
, "empty-search-results-page-header": "No results were found for <b>\"{{{SEARCH_PATTERN}}}\"</b>"
, "search-result-book-info": "from {{BOOK_TITLE}}"
, "word-count": "{{COUNT}} words"
, "library-button-text": "Go to welcome page"
, "home-button-text": "Go to the main page of '{{BOOK_TITLE}}'"
, "random-page-button-text": "Go to a randomly selected page"
Expand Down
5 changes: 5 additions & 0 deletions static/skin/i18n/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"500-page-text": "Text of the 500 error page",
"fulltext-search-unavailable": "Title of the error page returned when search is attempted in a book without fulltext search database",
"no-search-results": "Text of the error page returned when search is attempted in a book without fulltext search database",
"search-results-page-title": "Title of the search results page",
"search-results-page-header": "Header of the search results page",
"empty-search-results-page-header": "Header of the empty search results page",
"search-result-book-info": "Reference to the book where the search result belongs (this is displayed AFTER the search result)",
"word-count": "Word count information",
"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",
Expand Down
5 changes: 5 additions & 0 deletions static/skin/i18n/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@
, "preview-book": "[I18N] Preview [TESTING]"
, "no-query" : "[I18N TESTING] Kiwix can read your thoughts but it is against GDPR. Please provide your query explicitly."
, "invalid-request" : "[I18N TESTING] Invalid URL: \"{{{url}}}\""
, "search-results-page-title": "[I18N TESTING] Search: {{SEARCH_PATTERN}}"
, "search-results-page-header": "[I18N TESTING] Results <b>{{START}}-{{END}}</b> of <b>{{COUNT}}</b> for <b>\"{{{SEARCH_PATTERN}}}\"</b>"
, "empty-search-results-page-header": "[I18N TESTING] No results were found for <b>\"{{{SEARCH_PATTERN}}}\"</b>"
, "search-result-book-info": "from [I18N TESTING] {{BOOK_TITLE}}"
, "word-count": "{{COUNT}} [I18N TESTING] words"
}
2 changes: 1 addition & 1 deletion static/skin/languages.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const uiLanguages = [
{
"iso_code": "en",
"self_name": "English",
"translation_count": 53
"translation_count": 58
},
{
"iso_code": "es",
Expand Down
20 changes: 14 additions & 6 deletions static/skin/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ let viewerState = {
uiLanguage: 'en',
};

function dropUserLang(query) {
const q = new URLSearchParams(query);
q.delete('userlang');
const pre = (query.startsWith('?') && q.size != 0 ? '?' : '');
return pre + q.toString();
}

function userUrl2IframeUrl(url) {
if ( url == '' ) {
return blankPageUrl;
}

if ( url.startsWith('search?') ) {
return `${root}/${url}`;
const q = new URLSearchParams(url.slice("search?".length));
q.set('userlang', viewerState.uiLanguage);
return `${root}/search?${q.toString()}`;
}

return `${root}/content/${url}`;
Expand Down Expand Up @@ -73,7 +82,7 @@ function quasiUriEncode(s, specialSymbols) {
function performSearch() {
const searchbox = document.getElementById('kiwixsearchbox');
const q = encodeURIComponent(searchbox.value);
gotoUrl(`/search?books.name=${currentBook}&pattern=${q}`);
gotoUrl(`/search?books.name=${currentBook}&pattern=${q}&userlang=${viewerState.uiLanguage}`);
}

function makeJSLink(jsCodeString, linkText, linkAttr="") {
Expand Down Expand Up @@ -148,7 +157,7 @@ function iframeUrl2UserUrl(url, query) {
}

if ( url == `${root}/search` ) {
return `search${query}`;
return `search${dropUserLang(query)}`;
}

url = url.slice(root.length);
Expand Down Expand Up @@ -537,9 +546,8 @@ function setupViewer() {
const lang = getUserLanguage();
setUserLanguage(lang, finishViewerSetupOnceTranslationsAreLoaded);
viewerState.uiLanguage = lang;
const q = new URLSearchParams(window.location.search);
q.delete('userlang');
const rewrittenURL = makeURL(q.toString(), location.hash);
const cleanedUpQuery = dropUserLang(window.location.search);
const rewrittenURL = makeURL(cleanedUpQuery, location.hash);
history.replaceState(viewerState, null, rewrittenURL);

kiwixToolBarWrapper.style.display = 'block';
Expand Down
28 changes: 8 additions & 20 deletions static/templates/search_result.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,11 @@
}

</style>
<title>Search: {{query.pattern}}</title>
<title>{{PAGE_TITLE}}</title>
</head>
<body bgcolor="white">
<div class="header">
{{#results.hasResults}}
Results
<b>
{{results.start}}-{{results.end}}
</b> of <b>
{{results.count}}
</b> for <b>
"{{{query.pattern}}}"
</b>
{{/results.hasResults}}
{{^results.hasResults}}
No results were found for <b>"{{{query.pattern}}}"</b>
{{/results.hasResults}}
{{{PAGE_HEADER}}}
</div>

<div class="results">
Expand All @@ -131,12 +119,12 @@
{{#snippet}}
<cite>{{>snippet}}...</cite>
{{/snippet}}
{{#bookTitle}}
<div class="book-title">from {{bookTitle}}</div>
{{/bookTitle}}
{{#wordCount}}
<div class="informations">{{wordCount}} words</div>
{{/wordCount}}
{{#bookInfo}}
<div class="book-title">{{bookInfo}}</div>
{{/bookInfo}}
{{#wordCountInfo}}
<div class="informations">{{wordCountInfo}}</div>
{{/wordCountInfo}}
</li>
{{/results.items}}
</ul>
Expand Down
12 changes: 6 additions & 6 deletions test/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const ResourceCollection resources200Compressible{
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css?cacheid=e014a885" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/viewer.js" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=e9c025f2" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=5fc4badf" },
{ 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" },
Expand All @@ -84,7 +84,7 @@ const ResourceCollection resources200Compressible{
// 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=c41aae47" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/languages.js?cacheid=9ccd43fd" },

{ DYNAMIC_CONTENT, "/ROOT%23%3F/catalog/search" },

Expand Down Expand Up @@ -286,7 +286,7 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/kiwix.css?cacheid=2158fad9"
<link rel="shortcut icon" href="/ROOT%23%3F/skin/favicon/favicon.ico?cacheid=92663314">
<meta name="msapplication-config" content="/ROOT%23%3F/skin/favicon/browserconfig.xml?cacheid=f29a7c4a">
<script type="module" src="/ROOT%23%3F/skin/i18n.js?cacheid=071abc9a" defer></script>
<script type="text/javascript" src="/ROOT%23%3F/skin/languages.js?cacheid=c41aae47" defer></script>
<script type="text/javascript" src="/ROOT%23%3F/skin/languages.js?cacheid=9ccd43fd" defer></script>
<script src="/ROOT%23%3F/skin/isotope.pkgd.min.js?cacheid=2e48d392" defer></script>
<script src="/ROOT%23%3F/skin/iso6391To3.js?cacheid=ecde2bb3"></script>
<script type="text/javascript" src="/ROOT%23%3F/skin/index.js?cacheid=ce19da2a" defer></script>
Expand Down Expand Up @@ -319,8 +319,8 @@ R"EXPECTEDRESULT( <link type="text/css" href="./skin/kiwix.css?cacheid=2158fa
<link type="text/css" href="./skin/taskbar.css?cacheid=e014a885" rel="Stylesheet" />
<link type="text/css" href="./skin/autoComplete/css/autoComplete.css?cacheid=ef30cd42" rel="Stylesheet" />
<script type="module" src="./skin/i18n.js?cacheid=071abc9a" defer></script>
<script type="text/javascript" src="./skin/languages.js?cacheid=c41aae47" defer></script>
<script type="text/javascript" src="./skin/viewer.js?cacheid=e9c025f2" defer></script>
<script type="text/javascript" src="./skin/languages.js?cacheid=9ccd43fd" defer></script>
<script type="text/javascript" src="./skin/viewer.js?cacheid=5fc4badf" defer></script>
<script type="text/javascript" src="./skin/autoComplete/autoComplete.min.js?cacheid=1191aaaf"></script>
const blankPageUrl = root + "/skin/blank.html?cacheid=6b1fa032";
<label for="kiwix_button_show_toggle"><img src="./skin/caret.png?cacheid=22b942b4" alt=""></label>
Expand Down Expand Up @@ -1148,7 +1148,7 @@ R"EXPECTEDRESPONSE(const uiLanguages = [
{
"iso_code": "en",
"self_name": "English",
"translation_count": 53
"translation_count": 58
},
{
"iso_code": "es",
Expand Down
Loading
Loading