1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
#include "LocalisationProvider.h"
#include <fstream>
#include <stdexcept>
#include "itextstream.h"
#include "registry/registry.h"
#include "settings/SettingsManager.h"
#include "string/case_conv.h"
#include "os/path.h"
#include <wx/translation.h>
#include <wx/intl.h>
#include <wx/arrstr.h>
namespace settings
{
namespace
{
const char* const LANGUAGE_SETTING_FILE = "darkradiant.language";
const char* const DEFAULT_LANGUAGE = "en";
}
class UnknownLanguageException :
public std::runtime_error
{
public:
UnknownLanguageException(const std::string& what) :
std::runtime_error(what)
{}
};
const char* const LocalisationProvider::RKEY_LANGUAGE = "user/ui/language";
LocalisationProvider::LocalisationProvider(IApplicationContext& ctx)
{
// Point wxWidgets to the folder where the catalog files are stored
_i18nPath = os::standardPathWithSlash(ctx.getApplicationPath() + "i18n");
wxFileTranslationsLoader::AddCatalogLookupPathPrefix(_i18nPath);
// Load the persisted language setting
settings::SettingsManager manager(ctx);
_languageSettingFile = manager.getCurrentVersionSettingsFolder() + LANGUAGE_SETTING_FILE;
_curLanguage = loadLanguageSetting();
rMessage() << "Current language setting: " << _curLanguage << std::endl;
// Fill array of supported languages
loadSupportedLanguages();
// Fill array of available languages
findAvailableLanguages();
// Keep locale set to "C" for faster stricmp in Windows builds
_wxLocale.reset(new wxLocale(_curLanguage, _curLanguage, "C"));
_wxLocale->AddCatalog(GETTEXT_PACKAGE);
}
std::shared_ptr<LocalisationProvider>& LocalisationProvider::Instance()
{
static std::shared_ptr<LocalisationProvider> _instancePtr;
return _instancePtr;
}
void LocalisationProvider::Initialise(IApplicationContext& context)
{
Instance().reset(new LocalisationProvider(context));
}
void LocalisationProvider::Cleanup()
{
Instance().reset();
}
std::string LocalisationProvider::getLocalisedString(const char* stringToLocalise)
{
return wxGetTranslation(stringToLocalise).ToStdString();
}
std::string LocalisationProvider::loadLanguageSetting()
{
std::string language = DEFAULT_LANGUAGE;
// Check for an existing language setting file in the user settings folder
std::ifstream str(_languageSettingFile.c_str());
if (str.good())
{
str >> language;
}
str.close();
return language;
}
void LocalisationProvider::saveLanguageSetting(const std::string& language)
{
std::ofstream str(_languageSettingFile.c_str());
str << language;
str.flush();
str.close();
}
void LocalisationProvider::foreachAvailableLanguage(const std::function<void(const Language&)>& functor)
{
for (int code : _availableLanguages)
{
functor(_supportedLanguages[code]);
}
}
int LocalisationProvider::getCurrentLanguageIndex() const
{
// Set up the indices
int curLanguageIndex = 0; // english
try
{
int index = LocalisationProvider::Instance()->getLanguageIndex(_curLanguage);
// Get the offset into the array of available languages
auto found = std::find(_availableLanguages.begin(), _availableLanguages.end(), index);
if (found != _availableLanguages.end())
{
curLanguageIndex = static_cast<int>(std::distance(_availableLanguages.begin(), found));
}
}
catch (UnknownLanguageException&)
{
rWarning() << "Warning, unknown language found in " <<
LANGUAGE_SETTING_FILE << ", reverting to English" << std::endl;
}
return curLanguageIndex;
}
void LocalisationProvider::loadSupportedLanguages()
{
_supportedLanguages.clear();
int index = 0;
_supportedLanguages[index++] = Language("en", _("English"));
_supportedLanguages[index++] = Language("de", _("German"));
}
void LocalisationProvider::findAvailableLanguages()
{
// English (index 0) is always available
_availableLanguages.push_back(0);
wxFileTranslationsLoader loader;
wxArrayString translations = loader.GetAvailableTranslations(GETTEXT_PACKAGE);
for (const auto& lang : translations)
{
// Get the index (is this a known language?)
try
{
int index = getLanguageIndex(lang.ToStdString());
// Add this to the list (could use more extensive checking, but this is enough for now)
_availableLanguages.push_back(index);
}
catch (UnknownLanguageException&)
{
rWarning() << "Skipping unknown language: " << lang << std::endl;
}
}
rMessage() << "Found " << _availableLanguages.size() << " language folders." << std::endl;
}
int LocalisationProvider::getLanguageIndex(const std::string& languageCode)
{
std::string code = string::to_lower_copy(languageCode);
for (const auto& pair : _supportedLanguages)
{
if (pair.second.twoDigitCode == code)
{
return pair.first;
}
}
throw UnknownLanguageException("Unknown language: " + languageCode);
}
void LocalisationProvider::saveLanguageSetting()
{
// Get the language setting from the registry (this is an integer)
// and look up the language code (two digit)
int langNum = registry::getValue<int>(RKEY_LANGUAGE);
assert(langNum >= 0 && langNum < static_cast<int>(_availableLanguages.size()));
// Look up the language index in the list of available languages
int langIndex = _availableLanguages[langNum];
assert(_supportedLanguages.find(langIndex) != _supportedLanguages.end());
// Save the language code to the settings file
saveLanguageSetting(_supportedLanguages[langIndex].twoDigitCode);
}
}
|