diff --git a/src/meson.build b/src/meson.build index 545d1bc99..9a5d4ff56 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,6 +28,7 @@ kiwix_sources = [ 'server/response.cpp', 'server/internalServer.cpp', 'server/internalServer_catalog_v2.cpp', + 'server/i18n.cpp', 'opds_catalog.cpp', 'version.cpp' ] diff --git a/src/server/i18n.cpp b/src/server/i18n.cpp new file mode 100644 index 000000000..2e59ea60e --- /dev/null +++ b/src/server/i18n.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2022 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. + */ + +#include "i18n.h" + +#include +#include + +namespace kiwix +{ + +const char* I18nStringTable::get(const std::string& key) const +{ + const I18nString* const begin = entries; + const I18nString* const end = begin + entryCount; + const I18nString* found = std::lower_bound(begin, end, key, + [](const I18nString& a, const std::string& k) { + return a.key < k; + }); + return (found == end || found->key != key) ? nullptr : found->value; +} + +namespace +{ + +const I18nString enStrings[] = { + // must be sorted by key + { "suggest-full-text-search", "containing '{{{SEARCH_TERMS}}}'..."} +}; + +#define ARRAY_ELEMENT_COUNT(a) (sizeof(a)/sizeof(a[0])) + +const I18nStringTable i18nStringTables[] = { + { "en", ARRAY_ELEMENT_COUNT(enStrings), enStrings } +}; + +class I18nStringDB +{ +public: // functions + I18nStringDB() { + for ( size_t i = 0; i < ARRAY_ELEMENT_COUNT(i18nStringTables); ++i ) { + const auto& t = i18nStringTables[i]; + lang2TableMap[t.lang] = &t; + } + enStrings = lang2TableMap.at("en"); + }; + + std::string get(const std::string& lang, const std::string& key) const { + const char* s = getStringsFor(lang)->get(key); + if ( s == nullptr ) { + s = enStrings->get(key); + if ( s == nullptr ) { + throw std::runtime_error("Invalid message id"); + } + } + return s; + } + +private: // functions + const I18nStringTable* getStringsFor(const std::string& lang) const { + try { + return lang2TableMap.at(lang); + } catch(const std::out_of_range&) { + return enStrings; + } + } + +private: // data + std::map lang2TableMap; + const I18nStringTable* enStrings; +}; + +} // unnamed namespace + +std::string getTranslatedString(const std::string& lang, const std::string& key) +{ + static const I18nStringDB stringDb; + + return stringDb.get(lang, key); +} + +} // namespace kiwix diff --git a/src/server/i18n.h b/src/server/i18n.h new file mode 100644 index 000000000..ffc2341e5 --- /dev/null +++ b/src/server/i18n.h @@ -0,0 +1,45 @@ +/* + * Copyright 2022 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_SERVER_I18N +#define KIWIX_SERVER_I18N + +#include + +namespace kiwix +{ + +struct I18nString { + const char* const key; + const char* const value; +}; + +struct I18nStringTable { + const char* const lang; + const size_t entryCount; + const I18nString* const entries; + + const char* get(const std::string& key) const; +}; + +std::string getTranslatedString(const std::string& lang, const std::string& key); + +} // namespace kiwix + +#endif // KIWIX_SERVER_I18N diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 3dda112bd..81c7f8a73 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -55,6 +55,7 @@ extern "C" { #include "searcher.h" #include "search_renderer.h" #include "opds_dumper.h" +#include "i18n.h" #include #include @@ -446,10 +447,7 @@ std::string makeFulltextSearchSuggestion(const std::string& queryString) { MustacheData data; data.set("SEARCH_TERMS", queryString); - // NOTE: Search terms are **not** HTML-escaped at this point. - // NOTE: HTML-escaping is performed when the result of this function - // NOTE: is expanded into the suggestions.json template - const std::string tmpl("containing '{{{SEARCH_TERMS}}}'..."); + const std::string tmpl = getTranslatedString("en", "suggest-full-text-search"); return render_template(tmpl, data); }