@@ -20,6 +20,8 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <glib.h>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <winnls.h>
|
||||
@@ -28,6 +30,8 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
#include "../rtengine/settings.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -162,6 +166,25 @@ void setGtkLanguage(const Glib::ustring &language)
|
||||
|
||||
}
|
||||
|
||||
TranslationMetadata::TranslationMetadata(std::map<std::string, std::string> &&metadata) :
|
||||
metadata(std::move(metadata))
|
||||
{
|
||||
}
|
||||
|
||||
std::string TranslationMetadata::get(const std::string &key, const std::string &default_value) const
|
||||
{
|
||||
const auto found_entry = metadata.find(key);
|
||||
if (found_entry == metadata.end()) {
|
||||
return default_value;
|
||||
}
|
||||
return found_entry->second;
|
||||
}
|
||||
|
||||
std::string TranslationMetadata::getLanguageName(const std::string &default_name) const
|
||||
{
|
||||
return get("LANGUAGE_DISPLAY_NAME", default_name);
|
||||
}
|
||||
|
||||
MultiLangMgr langMgr;
|
||||
|
||||
MultiLangMgr::MultiLangMgr ()
|
||||
@@ -219,6 +242,77 @@ Glib::ustring MultiLangMgr::getStr (const std::string& key) const
|
||||
return key;
|
||||
}
|
||||
|
||||
const TranslationMetadata *MultiLangMgr::getMetadata(const Glib::ustring &fname) const
|
||||
{
|
||||
static const char comment_symbol = '#';
|
||||
static const char *space_chars = " \t";
|
||||
static const char var_symbol = '@';
|
||||
static const char key_value_separator = '=';
|
||||
|
||||
// Look for the metadata in the cache.
|
||||
const auto &found_metadata = lang_files_metadata.find(fname);
|
||||
if (found_metadata != lang_files_metadata.end()) {
|
||||
return &found_metadata->second;
|
||||
}
|
||||
|
||||
std::ifstream file(fname.c_str());
|
||||
if (!file.is_open()) {
|
||||
if (rtengine::settings->verbose) {
|
||||
std::cerr << "Unable to open language file " << fname << " to get metadata." << std::endl;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (rtengine::settings->verbose) {
|
||||
std::cout << "Reading metadata from language file " << fname << std::endl;
|
||||
}
|
||||
std::map<std::string, std::string> raw_metadata;
|
||||
const auto read_key_value = [&raw_metadata](const std::string &meta_line) {
|
||||
// One metadata key-value pair per line. The format is as follows:
|
||||
// #001 @KEY=VALUE
|
||||
// The line must begin with the comment symbol (#). After the first
|
||||
// sequence of whitespace characters, the metadata variable symbol (@)
|
||||
// must appear. It is followed immediately with the key name. The end of
|
||||
// the key name is marked with the equal sign (=). All remaining
|
||||
// characters until the end of the line make up the metadata value.
|
||||
if (meta_line.empty() || meta_line.front() != comment_symbol) {
|
||||
return;
|
||||
}
|
||||
const auto first_space = meta_line.find_first_of(space_chars, 1);
|
||||
if (first_space == std::string::npos) {
|
||||
return;
|
||||
}
|
||||
const auto definition_start = meta_line.find_first_not_of(space_chars, first_space + 1);
|
||||
if (definition_start == std::string::npos || meta_line[definition_start] != var_symbol) {
|
||||
return;
|
||||
}
|
||||
const auto separator_pos = meta_line.find(key_value_separator, definition_start + 1);
|
||||
if (separator_pos == std::string::npos) {
|
||||
return;
|
||||
}
|
||||
std::string key = meta_line.substr(definition_start + 1, separator_pos - definition_start - 1);
|
||||
std::string value = meta_line.substr(separator_pos + 1);
|
||||
if (rtengine::settings->verbose) {
|
||||
std::cout << "Found metadata key " << key << " with value " << value << std::endl;
|
||||
}
|
||||
raw_metadata.emplace(std::move(key), std::move(value));
|
||||
};
|
||||
|
||||
// Read lines in order. Metadata only appear in the first section of each
|
||||
// file.
|
||||
for (
|
||||
std::string line;
|
||||
std::getline(file, line) && (line.empty() ||
|
||||
line.front() == comment_symbol ||
|
||||
line.find_first_not_of(space_chars) == std::string::npos);) {
|
||||
read_key_value(line);
|
||||
}
|
||||
|
||||
// Add metadata to cache and return.
|
||||
lang_files_metadata[fname] = TranslationMetadata(std::move(raw_metadata));
|
||||
return &lang_files_metadata[fname];
|
||||
}
|
||||
|
||||
bool MultiLangMgr::isOSLanguageDetectSupported ()
|
||||
{
|
||||
#if defined (WIN32) || defined (__linux__) || defined (__APPLE__)
|
||||
|
@@ -24,6 +24,25 @@
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
class TranslationMetadata
|
||||
{
|
||||
public:
|
||||
TranslationMetadata() = default;
|
||||
~TranslationMetadata() = default;
|
||||
TranslationMetadata(const TranslationMetadata &other) = delete;
|
||||
TranslationMetadata(TranslationMetadata &&other) = delete;
|
||||
explicit TranslationMetadata(std::map<std::string, std::string> &&metadata);
|
||||
|
||||
TranslationMetadata &operator =(const TranslationMetadata &other) = delete;
|
||||
TranslationMetadata &operator =(TranslationMetadata &&other) noexcept = default;
|
||||
|
||||
std::string get(const std::string &key, const std::string &default_value) const;
|
||||
std::string getLanguageName(const std::string &default_name) const;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> metadata;
|
||||
};
|
||||
|
||||
class MultiLangMgr
|
||||
{
|
||||
public:
|
||||
@@ -31,11 +50,13 @@ public:
|
||||
|
||||
void load(const Glib::ustring &language, const std::vector<Glib::ustring> &fnames);
|
||||
Glib::ustring getStr(const std::string& key) const;
|
||||
const TranslationMetadata *getMetadata(const Glib::ustring &fname) const;
|
||||
static bool isOSLanguageDetectSupported();
|
||||
static Glib::ustring getOSUserLanguage();
|
||||
|
||||
private:
|
||||
std::map<std::string, Glib::ustring> translations;
|
||||
mutable std::map<Glib::ustring, TranslationMetadata> lang_files_metadata;
|
||||
};
|
||||
|
||||
extern MultiLangMgr langMgr;
|
||||
|
@@ -16,21 +16,27 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <sstream>
|
||||
|
||||
#include <glibmm/miscutils.h>
|
||||
#include <glibmm/ustring.h>
|
||||
#include <sigc++/slot.h>
|
||||
#include "externaleditorpreferences.h"
|
||||
#include "preferences.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "splash.h"
|
||||
#include "cachemanager.h"
|
||||
|
||||
#include "addsetids.h"
|
||||
#include "cachemanager.h"
|
||||
#include "externaleditorpreferences.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "preferences.h"
|
||||
#include "rtimage.h"
|
||||
#include "rtwindow.h"
|
||||
#include "splash.h"
|
||||
#include "toollocationpref.h"
|
||||
|
||||
#include "../rtengine/dfmanager.h"
|
||||
#include "../rtengine/ffmanager.h"
|
||||
#include "../rtengine/iccstore.h"
|
||||
#include "../rtengine/procparams.h"
|
||||
#include <sstream>
|
||||
#include "rtimage.h"
|
||||
#include "rtwindow.h"
|
||||
#include "toollocationpref.h"
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
@@ -1112,9 +1118,14 @@ Gtk::Widget* Preferences::getGeneralPanel()
|
||||
std::vector<Glib::ustring> langs;
|
||||
parseDir(argv0 + "/languages", langs, "");
|
||||
|
||||
for (size_t i = 0; i < langs.size(); i++) {
|
||||
if ("default" != langs[i] && "README" != langs[i] && "LICENSE" != langs[i]) {
|
||||
languages->append(langs[i]);
|
||||
for (const auto &lang : langs) {
|
||||
if ("default" != lang && "README" != lang && "LICENSE" != lang) {
|
||||
auto lang_metadata = langMgr.getMetadata(Glib::build_filename(argv0 + "/languages", lang));
|
||||
const auto &display_name =
|
||||
lang_metadata != nullptr
|
||||
? Glib::ustring(lang_metadata->getLanguageName(lang))
|
||||
: lang;
|
||||
languages->append(lang, display_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1738,7 +1749,7 @@ void Preferences::storePreferences()
|
||||
moptions.menuGroupExtProg = ckbmenuGroupExtProg->get_active();
|
||||
moptions.highlightThreshold = (int)hlThresh->get_value();
|
||||
moptions.shadowThreshold = (int)shThresh->get_value();
|
||||
moptions.language = languages->get_active_text();
|
||||
moptions.language = languages->get_active_id();
|
||||
moptions.languageAutoDetect = ckbLangAutoDetect->get_active();
|
||||
moptions.theme = themeFNames.at (themeCBT->get_active_row_number ()).longFName;
|
||||
|
||||
@@ -2021,7 +2032,7 @@ void Preferences::fillPreferences()
|
||||
}
|
||||
|
||||
cprevdemo->set_active (moptions.prevdemo);
|
||||
languages->set_active_text(moptions.language);
|
||||
languages->set_active_id(moptions.language);
|
||||
ckbLangAutoDetect->set_active(moptions.languageAutoDetect);
|
||||
int themeNbr = getThemeRowNumber(moptions.theme);
|
||||
themeCBT->set_active (themeNbr == -1 ? 0 : themeNbr);
|
||||
|
Reference in New Issue
Block a user