plugins: add support for preference translations

The plugins add translations files to theirs resources,
so now daemon can get the preferences values accordingly
to the system language. In the future we might add a way
to follow the client-qt language which can differ from the
system.

Change-Id: I4caf49b45261a256e422c2f772ea37f1f2e9548c
This commit is contained in:
agsantos
2022-03-02 17:51:46 -05:00
committed by Aline Gondim Santos
parent 8de5f33d79
commit 13ceecdac4
3 changed files with 78 additions and 1 deletions

View File

@ -24,6 +24,8 @@
#include <msgpack.hpp>
#include <sstream>
#include <fstream>
#include <fmt/core.h>
#include "logger.h"
#include "fileutils.h"
@ -58,6 +60,51 @@ PluginPreferencesUtils::getAllowDenyListsPath()
+ "allowdeny.msgpack";
}
std::map<std::string, std::string>
PluginPreferencesUtils::processLocaleFile(const std::string& preferenceLocaleFilePath)
{
if (!fileutils::isFile(preferenceLocaleFilePath)) {
return {};
}
std::ifstream file(preferenceLocaleFilePath);
Json::Value root;
Json::CharReaderBuilder rbuilder;
rbuilder["collectComments"] = false;
std::string errs;
std::map<std::string, std::string> locales {};
if (file) {
// Read the file to a json format
if (Json::parseFromStream(rbuilder, file, &root, &errs)) {
auto keys = root.getMemberNames();
for (const auto& key : keys) {
locales[key] = root.get(key, "").asString();
}
}
}
return locales;
}
std::map<std::string, std::string>
PluginPreferencesUtils::getLocales(const std::string& rootPath, const std::string& lang)
{
auto pluginName = rootPath.substr(rootPath.find_last_of(DIR_SEPARATOR_CH) + 1);
auto basePath = fmt::format("{}/data/locale/{}", rootPath, pluginName + "_");
std::map<std::string, std::string> locales = {};
// Get language translations
if (!lang.empty()) {
locales = processLocaleFile(basePath + lang + ".json");
}
// Get default english values if no translations were found
if (locales.empty()) {
locales = processLocaleFile(basePath + "en.json");
}
return locales;
}
std::string
PluginPreferencesUtils::convertArrayToString(const Json::Value& jsonArray)
{
@ -111,6 +158,10 @@ PluginPreferencesUtils::getPreferences(const std::string& rootPath, const std::s
std::set<std::string> keys;
std::vector<std::map<std::string, std::string>> preferences;
if (file) {
// Get preferences locale
std::string lang = std::locale("").name();
auto locales = getLocales(rootPath, std::string(string_remove_suffix(lang, '.')));
// Read the file to a json format
bool ok = Json::parseFromStream(rbuilder, file, &root, &errs);
if (ok && root.isArray()) {
@ -136,6 +187,13 @@ PluginPreferencesUtils::getPreferences(const std::string& rootPath, const std::s
}
if (!preferenceAttributes.empty()) {
for (const auto& locale : locales) {
for (auto& pair : preferenceAttributes) {
string_replace(pair.second,
"{{" + locale.first + "}}",
locale.second);
}
}
preferences.push_back(std::move(preferenceAttributes));
keys.insert(key);
}

View File

@ -41,6 +41,7 @@ public:
* @brief Given a plugin installation path, returns the path to the
* preference.json of this plugin.
* @param rootPath
* @param accountId
* @return preference.json file path.
*/
static std::string getPreferencesConfigFilePath(const std::string& rootPath,
@ -66,6 +67,24 @@ public:
*/
static std::string getAllowDenyListsPath();
/**
* @brief Returns the available keys and translations for a given file.
* If the locale is not available, return empty map.
* @param localeFilePath
* @return locales map
*/
static std::map<std::string, std::string> processLocaleFile(const std::string& localeFilePath);
/**
* @brief Returns the available keys and translations for a given plugin.
* If the locale is not available, return the english default.
* @param rootPath
* @param lang
* @return locales map
*/
static std::map<std::string, std::string> getLocales(const std::string& rootPath,
const std::string& lang);
/**
* @brief Returns a colon separated string with values from a json::Value containing an array.
* @param jsonArray

View File

@ -45,8 +45,8 @@ struct StreamData
: id {std::move(callId)}
, direction {isReceived}
, type {mediaType}
, conversation {std::move(conversationId)}
, source {std::move(accountId)}
, conversation {std::move(conversationId)}
{}
// callId
const std::string id;