From 2535f210b3282d85f2f72bf800a39fc38fb0b51b Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Tue, 13 Aug 2024 18:04:17 +0400 Subject: [PATCH 1/3] Renamed src/server/{i18n -> i18n_utils}.h ... so that i18n.h can be introduced in include/ --- scripts/kiwix-compile-i18n | 2 +- src/html_dumper.cpp | 4 ++-- src/search_renderer.cpp | 2 +- src/server/i18n.cpp | 2 +- src/server/{i18n.h => i18n_utils.h} | 6 +++--- src/server/internalServer.cpp | 2 +- src/server/request_context.cpp | 2 +- src/server/response.h | 2 +- src/tools/otherTools.cpp | 2 +- test/i18n.cpp | 2 +- test/otherTools.cpp | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) rename src/server/{i18n.h => i18n_utils.h} (97%) diff --git a/scripts/kiwix-compile-i18n b/scripts/kiwix-compile-i18n index 90b01ed13..1519bb6ba 100755 --- a/scripts/kiwix-compile-i18n +++ b/scripts/kiwix-compile-i18n @@ -61,7 +61,7 @@ lang_table_entry_cxx_template = ''' cxxfile_template = '''// This file is automatically generated. Do not modify it. -#include "server/i18n.h" +#include "server/i18n_utils.h" namespace kiwix { namespace i18n { diff --git a/src/html_dumper.cpp b/src/html_dumper.cpp index 4896821bf..e0b7cdd70 100644 --- a/src/html_dumper.cpp +++ b/src/html_dumper.cpp @@ -3,7 +3,7 @@ #include "tools/otherTools.h" #include "tools.h" #include "tools/regexTools.h" -#include "server/i18n.h" +#include "server/i18n_utils.h" namespace kiwix { @@ -77,7 +77,7 @@ std::string HTMLDumper::dumpPlainHTML(kiwix::Filter filter) const const auto tags = bookObj.getTags(); const auto downloadAvailable = (bookObj.getUrl() != ""); std::string faviconAttr = "style=background-image:url(" + bookIconUrl + ")"; - + booksData.push_back(kainjow::mustache::object{ {"id", contentId}, {"title", bookTitle}, diff --git a/src/search_renderer.cpp b/src/search_renderer.cpp index e64eb5611..9a24e51e9 100644 --- a/src/search_renderer.cpp +++ b/src/search_renderer.cpp @@ -32,7 +32,7 @@ #include "libkiwix-resources.h" #include "tools/stringTools.h" -#include "server/i18n.h" +#include "server/i18n_utils.h" namespace kiwix { diff --git a/src/server/i18n.cpp b/src/server/i18n.cpp index 5b948f26e..11e0641b8 100644 --- a/src/server/i18n.cpp +++ b/src/server/i18n.cpp @@ -17,7 +17,7 @@ * MA 02110-1301, USA. */ -#include "i18n.h" +#include "i18n_utils.h" #include "tools/otherTools.h" diff --git a/src/server/i18n.h b/src/server/i18n_utils.h similarity index 97% rename from src/server/i18n.h rename to src/server/i18n_utils.h index 1e42cac68..5d20d489c 100644 --- a/src/server/i18n.h +++ b/src/server/i18n_utils.h @@ -17,8 +17,8 @@ * MA 02110-1301, USA. */ -#ifndef KIWIX_SERVER_I18N -#define KIWIX_SERVER_I18N +#ifndef KIWIX_SERVER_I18N_UTILS +#define KIWIX_SERVER_I18N_UTILS #include #include @@ -135,4 +135,4 @@ std::string selectMostSuitableLanguage(const UserLangPreferences& prefs); } // namespace kiwix -#endif // KIWIX_SERVER_I18N +#endif // KIWIX_SERVER_I18N_UTILS diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index ccc94a49b..d908a24e4 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -54,7 +54,7 @@ extern "C" { #include "search_renderer.h" #include "opds_dumper.h" #include "html_dumper.h" -#include "i18n.h" +#include "i18n_utils.h" #include #include diff --git a/src/server/request_context.cpp b/src/server/request_context.cpp index d879240cd..ff3ebbeba 100644 --- a/src/server/request_context.cpp +++ b/src/server/request_context.cpp @@ -28,7 +28,7 @@ #include #include "tools/stringTools.h" -#include "i18n.h" +#include "i18n_utils.h" namespace kiwix { diff --git a/src/server/response.h b/src/server/response.h index 11808f0da..b4c9925f7 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -27,7 +27,7 @@ #include #include "byte_range.h" #include "etag.h" -#include "i18n.h" +#include "i18n_utils.h" #include diff --git a/src/tools/otherTools.cpp b/src/tools/otherTools.cpp index 0c6eb36ca..e125c2df1 100644 --- a/src/tools/otherTools.cpp +++ b/src/tools/otherTools.cpp @@ -32,7 +32,7 @@ #endif #include "tools/stringTools.h" -#include "server/i18n.h" +#include "server/i18n_utils.h" #include "libkiwix-resources.h" #include diff --git a/test/i18n.cpp b/test/i18n.cpp index 4e891d6e9..0cfca7576 100644 --- a/test/i18n.cpp +++ b/test/i18n.cpp @@ -1,4 +1,4 @@ -#include "../src/server/i18n.h" +#include "../src/server/i18n_utils.h" #include "gtest/gtest.h" using namespace kiwix; diff --git a/test/otherTools.cpp b/test/otherTools.cpp index 1e38bbb1e..3ffca0456 100644 --- a/test/otherTools.cpp +++ b/test/otherTools.cpp @@ -20,7 +20,7 @@ #include "gtest/gtest.h" #include "../src/tools/otherTools.h" #include "zim/suggestion_iterator.h" -#include "../src/server/i18n.h" +#include "../src/server/i18n_utils.h" #include From 82ff88f5d8a8c045c096a1dc87fadd9fc8aa3199 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Tue, 13 Aug 2024 18:15:43 +0400 Subject: [PATCH 2/3] Made some i18n API public --- include/i18n.h | 90 +++++++++++++++++++++++++++++++++++++++++ include/meson.build | 3 +- src/server/i18n_utils.h | 57 +------------------------- 3 files changed, 93 insertions(+), 57 deletions(-) create mode 100644 include/i18n.h diff --git a/include/i18n.h b/include/i18n.h new file mode 100644 index 000000000..381232985 --- /dev/null +++ b/include/i18n.h @@ -0,0 +1,90 @@ +/* + * Copyright 2024 Veloman Yunkan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef KIWIX_I18N +#define KIWIX_I18N + +#include +#include + +namespace kiwix +{ + +std::string getTranslatedString(const std::string& lang, const std::string& key); + +namespace i18n +{ + +typedef std::map Parameters; + +std::string expandParameterizedString(const std::string& lang, + const std::string& key, + const Parameters& params); + +class GetTranslatedString +{ +public: + explicit GetTranslatedString(const std::string& lang) : m_lang(lang) {} + + std::string operator()(const std::string& key) const + { + return getTranslatedString(m_lang, key); + } + + std::string operator()(const std::string& key, const Parameters& params) const + { + return expandParameterizedString(m_lang, key, params); + } + +private: + const std::string m_lang; +}; + +} // namespace i18n + +class ParameterizedMessage +{ +public: // types + typedef i18n::Parameters Parameters; + +public: // functions + ParameterizedMessage(const std::string& msgId, const Parameters& params) + : msgId(msgId) + , params(params) + {} + + std::string getText(const std::string& lang) const; + + const std::string& getMsgId() const { return msgId; } + const Parameters& getParams() const { return params; } + +private: // data + const std::string msgId; + const Parameters params; +}; + +inline ParameterizedMessage nonParameterizedMessage(const std::string& msgId) +{ + const ParameterizedMessage::Parameters noParams; + return ParameterizedMessage(msgId, noParams); +} + +} // namespace kiwix + +#endif // KIWIX_I18N diff --git a/include/meson.build b/include/meson.build index 03e6f0465..4735c2226 100644 --- a/include/meson.build +++ b/include/meson.build @@ -10,7 +10,8 @@ headers = [ 'kiwixserve.h', 'name_mapper.h', 'tools.h', - 'version.h' + 'version.h', + 'i18n.h' ] install_headers(headers, subdir:'kiwix') diff --git a/src/server/i18n_utils.h b/src/server/i18n_utils.h index 5d20d489c..c9672501d 100644 --- a/src/server/i18n_utils.h +++ b/src/server/i18n_utils.h @@ -20,8 +20,7 @@ #ifndef KIWIX_SERVER_I18N_UTILS #define KIWIX_SERVER_I18N_UTILS -#include -#include +#include "i18n.h" #include namespace kiwix @@ -40,36 +39,9 @@ struct I18nStringTable { const char* get(const std::string& key) const; }; -std::string getTranslatedString(const std::string& lang, const std::string& key); - namespace i18n { -typedef std::map Parameters; - -std::string expandParameterizedString(const std::string& lang, - const std::string& key, - const Parameters& params); - -class GetTranslatedString -{ -public: - explicit GetTranslatedString(const std::string& lang) : m_lang(lang) {} - - std::string operator()(const std::string& key) const - { - return getTranslatedString(m_lang, key); - } - - std::string operator()(const std::string& key, const Parameters& params) const - { - return expandParameterizedString(m_lang, key, params); - } - -private: - const std::string m_lang; -}; - class GetTranslatedStringWithMsgId { typedef kainjow::mustache::basic_data MustacheString; @@ -94,33 +66,6 @@ private: } // namespace i18n -class ParameterizedMessage -{ -public: // types - typedef i18n::Parameters Parameters; - -public: // functions - ParameterizedMessage(const std::string& msgId, const Parameters& params) - : msgId(msgId) - , params(params) - {} - - std::string getText(const std::string& lang) const; - - const std::string& getMsgId() const { return msgId; } - const Parameters& getParams() const { return params; } - -private: // data - const std::string msgId; - const Parameters params; -}; - -inline ParameterizedMessage nonParameterizedMessage(const std::string& msgId) -{ - const ParameterizedMessage::Parameters noParams; - return ParameterizedMessage(msgId, noParams); -} - struct LangPreference { const std::string lang; From 8d480c8b6d645882cfc83f87d7729f337b4c166d Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Tue, 13 Aug 2024 18:39:29 +0400 Subject: [PATCH 3/3] Introduced translateBookCategory() --- include/i18n.h | 2 ++ src/server/i18n.cpp | 9 +++++++++ static/skin/i18n/en.json | 18 ++++++++++++++++++ static/skin/i18n/qqq.json | 20 +++++++++++++++++++- static/skin/i18n/test.json | 18 ++++++++++++++++++ test/i18n.cpp | 14 ++++++++++++++ 6 files changed, 80 insertions(+), 1 deletion(-) diff --git a/include/i18n.h b/include/i18n.h index 381232985..0b15729e0 100644 --- a/include/i18n.h +++ b/include/i18n.h @@ -85,6 +85,8 @@ inline ParameterizedMessage nonParameterizedMessage(const std::string& msgId) return ParameterizedMessage(msgId, noParams); } +std::string translateBookCategory(const std::string& lang, const std::string& category); + } // namespace kiwix #endif // KIWIX_I18N diff --git a/src/server/i18n.cpp b/src/server/i18n.cpp index 11e0641b8..f1975f405 100644 --- a/src/server/i18n.cpp +++ b/src/server/i18n.cpp @@ -193,4 +193,13 @@ std::string selectMostSuitableLanguage(const UserLangPreferences& prefs) return bestLangSoFar; } +std::string translateBookCategory(const std::string& lang, const std::string& category) +{ + try { + return getTranslatedString(lang, "book-category." + category); + } catch (...) { + return category; + } +} + } // namespace kiwix diff --git a/static/skin/i18n/en.json b/static/skin/i18n/en.json index 3c7aa39eb..9345a1cb5 100644 --- a/static/skin/i18n/en.json +++ b/static/skin/i18n/en.json @@ -60,4 +60,22 @@ , "preview-book": "Preview" , "non-translated-text": "{{MSG}}" , "unknown-error": "Unknown error" + , "book-category.gutenberg": "Gutenberg" + , "book-category.iFixit": "iFixit" + , "book-category.mooc": "MOOC" + , "book-category.phet": "Phet" + , "book-category.stack_exchange": "Stack Exchange" + , "book-category.ted": "Ted" + , "book-category.vikidia": "Vikidia" + , "book-category.wikibooks": "Wikibooks" + , "book-category.wikihow": "wikiHow" + , "book-category.wikinews": "Wikinews" + , "book-category.wikipedia": "Wikipedia" + , "book-category.wikiquote": "Wikiquote" + , "book-category.wikisource": "Wikisource" + , "book-category.wikispecies": "Wikispecies" + , "book-category.wikiversity": "Wikiversity" + , "book-category.wikivoyage": "Wikivoyage" + , "book-category.wiktionary": "Wiktionary" + , "book-category.other": "Other" } diff --git a/static/skin/i18n/qqq.json b/static/skin/i18n/qqq.json index 9a8c5c144..f41c5d7ad 100644 --- a/static/skin/i18n/qqq.json +++ b/static/skin/i18n/qqq.json @@ -62,5 +62,23 @@ "download-links-title": "Title for no-js download page", "preview-book": "Tooltip of book-tile leading to the book", "non-translated-text": "{{ignored}}\nUsed to display text that is generated at runtime and cannot be translated. Nothing to translate about this one.", - "unknown-error": "Unknown error" + "unknown-error": "Unknown error", + "book-category.gutenberg": "Name for the category of books from the Gutenberg project", + "book-category.iFixit": "Name for the category of iFixit books", + "book-category.mooc": "Name for the category of MOOC books", + "book-category.phet": "Name for the category of Phet books", + "book-category.stack_exchange": "Name for the category of books from the Stack Exchange network books", + "book-category.ted": "Name for the category of Ted books", + "book-category.vikidia": "Name for the category of Vikidia books", + "book-category.wikibooks": "Name for the category of Wikibooks books books", + "book-category.wikihow": "Name for the category of wikiHow books", + "book-category.wikinews": "Name for the category of Wikinews books", + "book-category.wikipedia": "Name for the category of Wikipedia books", + "book-category.wikiquote": "Name for the category of Wikiquote books", + "book-category.wikisource": "Name for the category of Wikisource books", + "book-category.wikispecies": "Name for the category of Wikispecies books", + "book-category.wikiversity": "Name for the category of Wikiversity books", + "book-category.wikivoyage": "Name for the category of Wikivoyage books", + "book-category.wiktionary": "Name for the category of Wiktionary books", + "book-category.other": "Books not belonging to any special category are listed under this one" } diff --git a/static/skin/i18n/test.json b/static/skin/i18n/test.json index 29c2e9613..f997ef5e0 100644 --- a/static/skin/i18n/test.json +++ b/static/skin/i18n/test.json @@ -47,4 +47,22 @@ , "empty-search-results-page-header": "[I18N TESTING] No results were found for \"{{{SEARCH_PATTERN}}}\"" , "search-result-book-info": "from [I18N TESTING] {{BOOK_TITLE}}" , "word-count": "{{COUNT}} [I18N TESTING] words" + , "book-category.gutenberg": "[I18N] Gutenberg [TESTING]" + , "book-category.iFixit": "[I18N] iFixit [TESTING]" + , "book-category.mooc": "[I18N] MOOC [TESTING]" + , "book-category.phet": "[I18N] Phet [TESTING]" + , "book-category.stack_exchange": "[I18N] Stack Exchange [TESTING]" + , "book-category.ted": "[I18N] Ted [TESTING]" + , "book-category.vikidia": "[I18N] Vikidia [TESTING]" + , "book-category.wikibooks": "[I18N] Wikibooks [TESTING]" + , "book-category.wikihow": "[I18N] wikiHow [TESTING]" + , "book-category.wikinews": "[I18N] Wikinews [TESTING]" + , "book-category.wikipedia": "[I18N] Wikipedia [TESTING]" + , "book-category.wikiquote": "[I18N] Wikiquote [TESTING]" + , "book-category.wikisource": "[I18N] Wikisource [TESTING]" + , "book-category.wikispecies": "[I18N] Wikispecies [TESTING]" + , "book-category.wikiversity": "[I18N] Wikiversity [TESTING]" + , "book-category.wikivoyage": "[I18N] Wikivoyage [TESTING]" + , "book-category.wiktionary": "[I18N] Wiktionary [TESTING]" + , "book-category.other": "[I18N] Other [TESTING]" } diff --git a/test/i18n.cpp b/test/i18n.cpp index 0cfca7576..a40e01ebf 100644 --- a/test/i18n.cpp +++ b/test/i18n.cpp @@ -48,3 +48,17 @@ TEST(ParameterizedMessage, messagesWithParameters) EXPECT_EQ(msg.getText("test"), "Filter [I18N] by [TESTING] tag \"\""); } } + +TEST(I18n, translateBookCategory) +{ + + EXPECT_EQ(translateBookCategory("en", "ted"), "Ted"); + EXPECT_EQ(translateBookCategory("test", "ted"), "[I18N] Ted [TESTING]"); + + EXPECT_EQ(translateBookCategory("en", "stack_exchange"), "Stack Exchange"); + EXPECT_EQ(translateBookCategory("test", "stack_exchange"), "[I18N] Stack Exchange [TESTING]"); + + // unknown categories are simply not translated + EXPECT_EQ(translateBookCategory("en", "Qwerty"), "Qwerty"); + EXPECT_EQ(translateBookCategory("test", "Qwerty"), "Qwerty"); +}