diff options
Diffstat (limited to 'shared/localization.cpp')
-rw-r--r-- | shared/localization.cpp | 435 |
1 files changed, 0 insertions, 435 deletions
diff --git a/shared/localization.cpp b/shared/localization.cpp deleted file mode 100644 index 73aa5b72..00000000 --- a/shared/localization.cpp +++ /dev/null @@ -1,435 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** - -#include "localization.h" -#include <fstream> -#include <map> -#include <list> -#include <iterator> -#include <wx/ffile.h> -#include <wx/intl.h> -#include <wx/msgdlg.h> -#include "parse_plural.h" -#include "parse_lng.h" -#include "util.h" -#include "string_tools.h" -#include "file_traverser.h" -#include "standard_paths.h" -#include "string_conv.h" -#include "zenXml/zenxml_io.h" -#include "i18n.h" - -using namespace zen; - - -namespace -{ -//global objects -std::wstring THOUSANDS_SEPARATOR = L","; - - -class FFSLocale : public TranslationHandler -{ -public: - FFSLocale(const wxString& filename, wxLanguage languageId); //throw (lngfile::ParsingError, PluralForm::ParsingError) - - wxLanguage langId() const { return langId_; } - - virtual std::wstring thousandsSeparator() { return THOUSANDS_SEPARATOR; }; - - virtual std::wstring translate(const std::wstring& text) - { - //look for translation in buffer table - const Translation::const_iterator iter = transMapping.find(text); - if (iter != transMapping.end()) - return iter->second; - - return text; //fallback - } - - virtual std::wstring translate(const std::wstring& singular, const std::wstring& plural, int n) - { - TranslationPlural::const_iterator iter = transMappingPl.find(std::make_pair(singular, plural)); - if (iter != transMappingPl.end()) - { - const int formNo = pluralParser->getForm(n); - if (0 <= formNo && formNo < static_cast<int>(iter->second.size())) - return iter->second[formNo]; - } - - return n == 1 ? singular : plural; //fallback - } - -private: - typedef std::map<std::wstring, std::wstring> Translation; - typedef std::map<std::pair<std::wstring, std::wstring>, std::vector<std::wstring> > TranslationPlural; - - Translation transMapping; //map original text |-> translation - TranslationPlural transMappingPl; - std::unique_ptr<PluralForm> pluralParser; - wxLanguage langId_; -}; - - - -FFSLocale::FFSLocale(const wxString& filename, wxLanguage languageId) : langId_(languageId) //throw (lngfile::ParsingError, PluralForm::ParsingError) -{ - std::string inputStream; - try - { - inputStream = loadStream(filename);; //throw XmlFileError - } - catch (...) - { - throw lngfile::ParsingError(0, 0); - } - - lngfile::TransHeader header; - lngfile::TranslationMap transInput; - lngfile::TranslationPluralMap transPluralInput; - lngfile::parseLng(inputStream, header, transInput, transPluralInput); //throw ParsingError - - for (lngfile::TranslationMap::const_iterator i = transInput.begin(); i != transInput.end(); ++i) - { - const std::wstring original = utf8CvrtTo<std::wstring>(i->first); - const std::wstring translation = utf8CvrtTo<std::wstring>(i->second); - assert(!translation.empty()); - transMapping.insert(std::make_pair(original , translation)); - } - - for (lngfile::TranslationPluralMap::const_iterator i = transPluralInput.begin(); i != transPluralInput.end(); ++i) - { - const std::wstring singular = utf8CvrtTo<std::wstring>(i->first.first); - const std::wstring plural = utf8CvrtTo<std::wstring>(i->first.second); - const lngfile::PluralForms& plForms = i->second; - - std::vector<std::wstring> plFormsWide; - for (lngfile::PluralForms::const_iterator j = plForms.begin(); j != plForms.end(); ++j) - plFormsWide.push_back(utf8CvrtTo<std::wstring>(*j)); - - assert(!plFormsWide.empty()); - - transMappingPl.insert(std::make_pair(std::make_pair(singular, plural), plFormsWide)); - } - - pluralParser.reset(new PluralForm(header.pluralDefinition.c_str())); //throw PluralForm::ParsingError -} -} - - -class FindLngfiles : public zen::TraverseCallback -{ -public: - FindLngfiles(std::vector<Zstring>& lngFiles) : lngFiles_(lngFiles) {} - - virtual void onFile(const Zchar* shortName, const Zstring& fullName, const FileInfo& details) - { - if (endsWith(fullName, Zstr(".lng"))) - lngFiles_.push_back(fullName); - } - - virtual void onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) {} - virtual ReturnValDir onDir(const Zchar* shortName, const Zstring& fullName) { return Loki::Int2Type<ReturnValDir::TRAVERSING_DIR_IGNORE>(); } - virtual HandleError onError(const std::wstring& errorText) { return TRAV_ERROR_IGNORE; } //errors are not really critical in this context - -private: - std::vector<Zstring>& lngFiles_; -}; - - -struct LessTranslation : public std::binary_function<ExistingTranslations::Entry, ExistingTranslations::Entry, bool> -{ - bool operator()(const ExistingTranslations::Entry& lhs, const ExistingTranslations::Entry& rhs) const - { -#ifdef FFS_WIN - //use a more "natural" sort, that is ignore case and diacritics - const int rv = ::CompareString(LOCALE_USER_DEFAULT, //__in LCID Locale, - NORM_IGNORECASE, //__in DWORD dwCmpFlags, - lhs.languageName.c_str(), //__in LPCTSTR lpString1, - static_cast<int>(lhs.languageName.size()), //__in int cchCount1, - rhs.languageName.c_str(), //__in LPCTSTR lpString2, - static_cast<int>(rhs.languageName.size())); //__in int cchCount2 - if (rv == 0) - throw std::runtime_error("Error comparing strings!"); - else - return rv == CSTR_LESS_THAN; //convert to C-style string compare result -#else - return lhs.languageName < rhs.languageName; -#endif - } -}; - - -ExistingTranslations::ExistingTranslations() -{ - { - //default entry: - ExistingTranslations::Entry newEntry; - newEntry.languageID = wxLANGUAGE_ENGLISH_US; - newEntry.languageName = wxT("English (US)"); - newEntry.languageFile = wxT(""); - newEntry.translatorName = wxT("ZenJu"); - newEntry.languageFlag = wxT("usa.png"); - locMapping.push_back(newEntry); - } - - //search language files available - std::vector<Zstring> lngFiles; - FindLngfiles traverseCallback(lngFiles); - - traverseFolder(toZ(zen::getResourceDir() + wxT("Languages")), //throw(); - false, //don't follow symlinks - traverseCallback); - - for (auto i = lngFiles.begin(); i != lngFiles.end(); ++i) - { - try - { - std::string stream = loadStream(*i);; //throw XmlFileError - try - { - lngfile::TransHeader lngHeader; - lngfile::parseHeader(stream, lngHeader); //throw ParsingError - - const wxLanguageInfo* locInfo = wxLocale::FindLanguageInfo(utf8CvrtTo<wxString>(lngHeader.localeName)); - if (locInfo) - { - ExistingTranslations::Entry newEntry; - newEntry.languageID = locInfo->Language; - newEntry.languageName = utf8CvrtTo<wxString>(lngHeader.languageName); - newEntry.languageFile = toWx(*i); - newEntry.translatorName = utf8CvrtTo<wxString>(lngHeader.translatorName); - newEntry.languageFlag = utf8CvrtTo<wxString>(lngHeader.flagFile); - locMapping.push_back(newEntry); - } - } - catch (lngfile::ParsingError&) {} - } - catch (...) {} - } - - std::sort(locMapping.begin(), locMapping.end(), LessTranslation()); -} - - -namespace -{ -wxLanguage mapLanguageDialect(wxLanguage language) -{ - switch (static_cast<int>(language)) //map language dialects - { - //variants of wxLANGUAGE_GERMAN - case wxLANGUAGE_GERMAN_AUSTRIAN: - case wxLANGUAGE_GERMAN_BELGIUM: - case wxLANGUAGE_GERMAN_LIECHTENSTEIN: - case wxLANGUAGE_GERMAN_LUXEMBOURG: - case wxLANGUAGE_GERMAN_SWISS: - return wxLANGUAGE_GERMAN; - - //variants of wxLANGUAGE_FRENCH - case wxLANGUAGE_FRENCH_BELGIAN: - case wxLANGUAGE_FRENCH_CANADIAN: - case wxLANGUAGE_FRENCH_LUXEMBOURG: - case wxLANGUAGE_FRENCH_MONACO: - case wxLANGUAGE_FRENCH_SWISS: - return wxLANGUAGE_FRENCH; - - //variants of wxLANGUAGE_DUTCH - case wxLANGUAGE_DUTCH_BELGIAN: - return wxLANGUAGE_DUTCH; - - //variants of wxLANGUAGE_ITALIAN - case wxLANGUAGE_ITALIAN_SWISS: - return wxLANGUAGE_ITALIAN; - - //variants of wxLANGUAGE_CHINESE_SIMPLIFIED - case wxLANGUAGE_CHINESE: - case wxLANGUAGE_CHINESE_SINGAPORE: - return wxLANGUAGE_CHINESE_SIMPLIFIED; - - //variants of wxLANGUAGE_CHINESE_TRADITIONAL - case wxLANGUAGE_CHINESE_TAIWAN: - case wxLANGUAGE_CHINESE_HONGKONG: - case wxLANGUAGE_CHINESE_MACAU: - return wxLANGUAGE_CHINESE_TRADITIONAL; - - //variants of wxLANGUAGE_RUSSIAN - case wxLANGUAGE_RUSSIAN_UKRAINE: - return wxLANGUAGE_RUSSIAN; - - //variants of wxLANGUAGE_SPANISH - case wxLANGUAGE_SPANISH_ARGENTINA: - case wxLANGUAGE_SPANISH_BOLIVIA: - case wxLANGUAGE_SPANISH_CHILE: - case wxLANGUAGE_SPANISH_COLOMBIA: - case wxLANGUAGE_SPANISH_COSTA_RICA: - case wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC: - case wxLANGUAGE_SPANISH_ECUADOR: - case wxLANGUAGE_SPANISH_EL_SALVADOR: - case wxLANGUAGE_SPANISH_GUATEMALA: - case wxLANGUAGE_SPANISH_HONDURAS: - case wxLANGUAGE_SPANISH_MEXICAN: - case wxLANGUAGE_SPANISH_MODERN: - case wxLANGUAGE_SPANISH_NICARAGUA: - case wxLANGUAGE_SPANISH_PANAMA: - case wxLANGUAGE_SPANISH_PARAGUAY: - case wxLANGUAGE_SPANISH_PERU: - case wxLANGUAGE_SPANISH_PUERTO_RICO: - case wxLANGUAGE_SPANISH_URUGUAY: - case wxLANGUAGE_SPANISH_US: - case wxLANGUAGE_SPANISH_VENEZUELA: - return wxLANGUAGE_SPANISH; - - //variants of wxLANGUAGE_SWEDISH - case wxLANGUAGE_SWEDISH_FINLAND: - return wxLANGUAGE_SWEDISH; - - //case wxLANGUAGE_CZECH: - //case wxLANGUAGE_DANISH: - //case wxLANGUAGE_FINNISH: - //case wxLANGUAGE_GREEK: - //case wxLANGUAGE_JAPANESE: - //case wxLANGUAGE_POLISH: - //case wxLANGUAGE_SLOVENIAN: - //case wxLANGUAGE_HUNGARIAN: - //case wxLANGUAGE_PORTUGUESE: - //case wxLANGUAGE_PORTUGUESE_BRAZILIAN: - //case wxLANGUAGE_KOREAN: - //case wxLANGUAGE_UKRAINIAN: - - //variants of wxLANGUAGE_ARABIC - case wxLANGUAGE_ARABIC_ALGERIA: - case wxLANGUAGE_ARABIC_BAHRAIN: - case wxLANGUAGE_ARABIC_EGYPT: - case wxLANGUAGE_ARABIC_IRAQ: - case wxLANGUAGE_ARABIC_JORDAN: - case wxLANGUAGE_ARABIC_KUWAIT: - case wxLANGUAGE_ARABIC_LEBANON: - case wxLANGUAGE_ARABIC_LIBYA: - case wxLANGUAGE_ARABIC_MOROCCO: - case wxLANGUAGE_ARABIC_OMAN: - case wxLANGUAGE_ARABIC_QATAR: - case wxLANGUAGE_ARABIC_SAUDI_ARABIA: - case wxLANGUAGE_ARABIC_SUDAN: - case wxLANGUAGE_ARABIC_SYRIA: - case wxLANGUAGE_ARABIC_TUNISIA: - case wxLANGUAGE_ARABIC_UAE: - case wxLANGUAGE_ARABIC_YEMEN: - return wxLANGUAGE_ARABIC; - - //variants of wxLANGUAGE_ENGLISH_UK - case wxLANGUAGE_ENGLISH_AUSTRALIA: - case wxLANGUAGE_ENGLISH_NEW_ZEALAND: - case wxLANGUAGE_ENGLISH_TRINIDAD: - case wxLANGUAGE_ENGLISH_CARIBBEAN: - case wxLANGUAGE_ENGLISH_JAMAICA: - case wxLANGUAGE_ENGLISH_BELIZE: - case wxLANGUAGE_ENGLISH_EIRE: - case wxLANGUAGE_ENGLISH_SOUTH_AFRICA: - case wxLANGUAGE_ENGLISH_ZIMBABWE: - case wxLANGUAGE_ENGLISH_BOTSWANA: - case wxLANGUAGE_ENGLISH_DENMARK: - return wxLANGUAGE_ENGLISH_UK; - - default: - return language; - } -} -} - - -class CustomLocale -{ -public: - CustomLocale(int selectedLng) - { - const wxLanguageInfo* sysLngInfo = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage()); - const wxLanguageInfo* selLngInfo = wxLocale::GetLanguageInfo(selectedLng); - - bool sysLangIsRTL = sysLngInfo ? sysLngInfo->LayoutDirection == wxLayout_RightToLeft : false; - bool selectedLangIsRTL = selLngInfo ? selLngInfo->LayoutDirection == wxLayout_RightToLeft : false; - - if (sysLangIsRTL == selectedLangIsRTL) - loc.Init(wxLANGUAGE_DEFAULT); //use sys-lang to preserve sub-language specific rules (e.g. german swiss number punctation) - else - loc.Init(selectedLng); - - //::setlocale (LC_ALL, ""); -> implicitly called by wxLocale - const lconv* localInfo = ::localeconv(); - - //actually these two parameters are language dependent, but we take system setting to handle all kinds of language derivations - THOUSANDS_SEPARATOR = utf8CvrtTo<wxString>(localInfo->thousands_sep); - - // why not working? - // THOUSANDS_SEPARATOR = std::use_facet<std::numpunct<wchar_t> >(std::locale("")).thousands_sep(); - // DECIMAL_POINT = std::use_facet<std::numpunct<wchar_t> >(std::locale("")).decimal_point(); - } -private: - wxLocale loc; //required for RTL language support (and nothing else) -}; - - -void zen::setLanguage(int language) -{ - //(try to) retrieve language file - wxString languageFile; - for (std::vector<ExistingTranslations::Entry>::const_iterator i = ExistingTranslations::get().begin(); i != ExistingTranslations::get().end(); ++i) - if (i->languageID == language) - { - languageFile = i->languageFile; - break; - } - - - //handle RTL swapping: we need wxWidgets to do this - static std::unique_ptr<CustomLocale> dummy; - dummy.reset(); //avoid global locale lifetime overlap! wxWidgets cannot handle this and will crash! - dummy.reset(new CustomLocale(languageFile.empty() ? wxLANGUAGE_ENGLISH : language)); - - - //reset to english language; in case of error show error message just once - zen::setTranslator(); - - //load language file into buffer - if (!languageFile.empty()) //if languageFile is empty texts will be english per default - { - try - { - zen::setTranslator(new FFSLocale(languageFile, static_cast<wxLanguage>(language))); //throw (lngfile::ParsingError, PluralForm::ParsingError) - } - catch (lngfile::ParsingError& e) - { - wxMessageBox(wxString(_("Error reading file:")) + wxT(" \"") + languageFile + wxT("\"") + wxT("\n\n") + - wxT("Row: ") + zen::toStringSep(e.row) + wxT("\n") + - wxT("Column: ") + zen::toStringSep(e.col) + wxT("\n"), _("Error"), wxOK | wxICON_ERROR); - } - catch (PluralForm::ParsingError&) - { - wxMessageBox(wxT("Invalid Plural Form"), _("Error"), wxOK | wxICON_ERROR); - } - } -} - - - -int zen::getLanguage() -{ - FFSLocale* loc = dynamic_cast<FFSLocale*>(zen::getTranslator()); - return loc ? loc->langId() : wxLANGUAGE_ENGLISH_US; -} - - -int zen::retrieveSystemLanguage() -{ - return mapLanguageDialect(static_cast<wxLanguage>(wxLocale::GetSystemLanguage())); -} - - -const std::vector<ExistingTranslations::Entry>& ExistingTranslations::get() -{ - static ExistingTranslations instance; - return instance.locMapping; -} |