summaryrefslogtreecommitdiff
path: root/shared/i18n.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shared/i18n.cpp')
-rw-r--r--shared/i18n.cpp1070
1 files changed, 7 insertions, 1063 deletions
diff --git a/shared/i18n.cpp b/shared/i18n.cpp
index 8e0bc22c..8c0e900c 100644
--- a/shared/i18n.cpp
+++ b/shared/i18n.cpp
@@ -1,1076 +1,20 @@
-// **************************************************************************
-// * 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 "i18n.h"
-#include <fstream>
-#include <map>
-#include <wx/ffile.h>
-#include <wx/intl.h>
-#include <wx/msgdlg.h>
-#include "../shared/standard_paths.h"
-#include "../shared/string_conv.h"
-#include "system_constants.h"
-#include <boost/any.hpp>
-#include <boost/shared_ptr.hpp>
-#include <list>
-#include <iterator>
-
-using ffs3::LocalizationInfo;
-
-
-namespace
-{
-//will receive their proper value in CustomLocale::CustomLocale()
-wxString THOUSANDS_SEPARATOR = wxT(",");
-wxString DECIMAL_POINT = wxT(".");
-
-typedef std::map<wxString, wxString> Translation;
-Translation activeTranslation; //map original text |-> translation
-
-int activeLanguage = wxLANGUAGE_ENGLISH;
-}
-
-
-wxString ffs3::getThousandsSeparator()
-{
- return THOUSANDS_SEPARATOR;
-}
-
-
-wxString ffs3::getDecimalPoint()
-{
- return DECIMAL_POINT;
-}
-
-
-const std::vector<ffs3::LocInfoLine>& LocalizationInfo::get()
-{
- static LocalizationInfo instance;
- return instance.locMapping;
-}
-
-
-LocalizationInfo::LocalizationInfo()
-{
- ffs3::LocInfoLine newEntry;
-
- newEntry.languageID = wxLANGUAGE_CZECH;
- newEntry.languageName = wxT("Čeština");
- newEntry.languageFile = wxT("czech.lng");
- newEntry.translatorName = wxT("ViCi");
- newEntry.languageFlag = wxT("czechRep.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_GERMAN;
- newEntry.languageName = wxT("Deutsch");
- newEntry.languageFile = wxT("german.lng");
- newEntry.translatorName = wxT("ZenJu");
- newEntry.languageFlag = wxT("germany.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_ENGLISH_UK;
- newEntry.languageName = wxT("English (UK)");
- newEntry.languageFile = wxT("english_uk.lng");
- newEntry.translatorName = wxT("Robert Readman");
- newEntry.languageFlag = wxT("england.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_ENGLISH;
- newEntry.languageName = wxT("English (US)");
- newEntry.languageFile = wxT("");
- newEntry.translatorName = wxT("ZenJu");
- newEntry.languageFlag = wxT("usa.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_SPANISH;
- newEntry.languageName = wxT("Español");
- newEntry.languageFile = wxT("spanish.lng");
- newEntry.translatorName = wxT("Alexis Martínez");
- newEntry.languageFlag = wxT("spain.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_GREEK;
- newEntry.languageName = wxT("Ελληνικά");
- newEntry.languageFile = wxT("greek.lng");
- newEntry.translatorName = wxT("Γιώργος Γιαγλής");
- newEntry.languageFlag = wxT("greece.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_FRENCH;
- newEntry.languageName = wxT("Français");
- newEntry.languageFile = wxT("french.lng");
- newEntry.translatorName = wxT("Jean-François Hartmann");
- newEntry.languageFlag = wxT("france.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_ITALIAN;
- newEntry.languageName = wxT("Italiano");
- newEntry.languageFile = wxT("italian.lng");
- newEntry.translatorName = wxT("Emmo");
- newEntry.languageFlag = wxT("italy.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_HUNGARIAN;
- newEntry.languageName = wxT("Magyar");
- newEntry.languageFile = wxT("hungarian.lng");
- newEntry.translatorName = wxT("Demon");
- newEntry.languageFlag = wxT("hungary.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_DUTCH;
- newEntry.languageName = wxT("Nederlands");
- newEntry.languageFile = wxT("dutch.lng");
- newEntry.translatorName = wxT("Dion van Lieshout");
- newEntry.languageFlag = wxT("holland.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_POLISH;
- newEntry.languageName = wxT("Polski");
- newEntry.languageFile = wxT("polish.lng");
- newEntry.translatorName = wxT("Wojtek Pietruszewski");
- newEntry.languageFlag = wxT("poland.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_PORTUGUESE;
- newEntry.languageName = wxT("Português");
- newEntry.languageFile = wxT("portuguese.lng");
- newEntry.translatorName = wxT("QuestMark");
- newEntry.languageFlag = wxT("portugal.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_PORTUGUESE_BRAZILIAN;
- newEntry.languageName = wxT("Português do Brasil");
- newEntry.languageFile = wxT("portuguese_br.lng");
- newEntry.translatorName = wxT("Edison Aranha");
- newEntry.languageFlag = wxT("brazil.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_RUSSIAN;
- newEntry.languageName = wxT("Pусский");
- newEntry.languageFile = wxT("russian.lng");
- newEntry.translatorName = wxT("Fayzullin T.N. aka Svobodniy");
- newEntry.languageFlag = wxT("russia.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_ROMANIAN;
- newEntry.languageName = wxT("Română");
- newEntry.languageFile = wxT("romanian.lng");
- newEntry.translatorName = wxT("Alexandru Bogdan Munteanu");
- newEntry.languageFlag = wxT("romania.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_SLOVENIAN;
- newEntry.languageName = wxT("Slovenščina");
- newEntry.languageFile = wxT("slovenian.lng");
- newEntry.translatorName = wxT("Matej Badalic");
- newEntry.languageFlag = wxT("slovakia.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_FINNISH;
- newEntry.languageName = wxT("Suomi");
- newEntry.languageFile = wxT("finnish.lng");
- newEntry.translatorName = wxT("Nalle Juslén");
- newEntry.languageFlag = wxT("finland.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_SWEDISH;
- newEntry.languageName = wxT("Svenska");
- newEntry.languageFile = wxT("swedish.lng");
- newEntry.translatorName = wxT("Åke Engelbrektson");
- newEntry.languageFlag = wxT("sweden.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_TURKISH;
- newEntry.languageName = wxT("Türkçe");
- newEntry.languageFile = wxT("turkish.lng");
- newEntry.translatorName = wxT("Kaya Zeren");
- newEntry.languageFlag = wxT("turkey.png");
- locMapping.push_back(newEntry);
-
- // newEntry.languageID = wxLANGUAGE_HEBREW;
- // newEntry.languageName = wxT("עִבְרִית");
- // newEntry.languageFile = wxT("hebrew.lng");
- // newEntry.translatorName = wxT("Moshe Olshevsky");
- // newEntry.languageFlag = wxT("isreal.png");
- // locMapping.push_back(newEntry);
-
- // newEntry.languageID = wxLANGUAGE_ARABIC;
- // newEntry.languageName = wxT("العربية");
- // newEntry.languageFile = wxT("arabic.lng");
- // newEntry.translatorName = wxT("Yousef Shamshoum");
- // newEntry.languageFlag = wxT("arabic-language.png");
- // locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_JAPANESE;
- newEntry.languageName = wxT("日本語");
- newEntry.languageFile = wxT("japanese.lng");
- newEntry.translatorName = wxT("Tilt");
- newEntry.languageFlag = wxT("japan.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_CHINESE_TRADITIONAL;
- newEntry.languageName = wxT("正體中文");
- newEntry.languageFile = wxT("chinese_traditional.lng");
- newEntry.translatorName = wxT("Carlos");
- newEntry.languageFlag = wxT("taiwan.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_CHINESE_SIMPLIFIED;
- newEntry.languageName = wxT("简体中文");
- newEntry.languageFile = wxT("chinese_simple.lng");
- newEntry.translatorName = wxT("CyberCowBoy");
- newEntry.languageFlag = wxT("china.png");
- locMapping.push_back(newEntry);
-
- newEntry.languageID = wxLANGUAGE_KOREAN;
- newEntry.languageName = wxT("한국어");
- newEntry.languageFile = wxT("korean.lng");
- newEntry.translatorName = wxT("Simon Park");
- newEntry.languageFlag = wxT("south_korea.png");
- locMapping.push_back(newEntry);
-}
+#include <memory>
+using namespace zen;
namespace
{
-int mapLanguageDialect(int language)
-{
- switch (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_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:
-
- //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;
- }
-}
-
-
-inline
-void exchangeEscapeChars(wxString& data)
-{
- wxString output;
-
- const wxChar* input = data.c_str();
-
- wxChar value;
- while ((value = *input) != wxChar(0))
- {
- //read backslash
- if (value == wxChar('\\'))
- {
- //read next character
- ++input;
- if ((value = *input) == wxChar(0))
- break;
-
- switch (value)
- {
- case wxChar('\\'):
- output += wxChar('\\');
- break;
- case wxChar('n'):
- output += wxChar('\n');
- break;
- case wxChar('t'):
- output += wxChar('\t');
- break;
- case wxChar('\"'):
- output += wxChar('\"');
- break;
- default:
- output += value;
- }
- }
- else
- output += value;
-
- ++input;
- }
- data = output;
-}
-
-
-//workaround to get a FILE* from a unicode filename in a portable way
-class UnicodeFileReader
-{
-public:
- UnicodeFileReader(const wxString& filename) :
- inputFile(NULL)
- {
- wxFFile dummyFile(filename, wxT("rb"));
- if (dummyFile.IsOpened())
- {
- inputFile = dummyFile.fp();
- dummyFile.Detach();
- }
- }
-
- ~UnicodeFileReader()
- {
- if (inputFile != NULL)
- fclose(inputFile);
- }
-
- bool isOkay()
- {
- return inputFile != NULL;
- }
-
- bool getNextLine(wxString& line)
- {
- std::string output;
-
- while (true)
- {
- const int c = fgetc(inputFile);
- if (c == EOF)
- return false;
- else if (c == 0xD)
- {
- //Delimiter:
- //----------
- //Linux: 0xA \n
- //Mac: 0xD \r
- //Win: 0xD 0xA \r\n <- language files are in Windows format
-
- fgetc(inputFile); //discard the 0xA character
-
- line = wxString::FromUTF8(output.c_str(), output.length());
- return true;
- }
- output += static_cast<char>(c);
- }
- }
-
-private:
- FILE* inputFile;
-};
-
-
-void loadTranslation(const wxString& filename, Translation& trans) //empty translation on error
-{
- trans.clear();
-
- UnicodeFileReader langFile(ffs3::getResourceDir() + wxT("Languages") + ffs3::zToWx(common::FILE_NAME_SEPARATOR) + filename);
- if (langFile.isOkay())
- {
- int rowNumber = 0;
- wxString original;
- wxString tmpString;
- while (langFile.getNextLine(tmpString))
- {
- exchangeEscapeChars(tmpString);
-
- if (rowNumber++ % 2 == 0)
- original = tmpString;
- else
- {
- const wxString& translation = tmpString;
-
- if (!original.empty() && !translation.empty())
- trans.insert(std::make_pair(original, translation));
- }
- }
- }
-}
-}
-
-
-void ffs3::setLanguage(int language)
-{
- static class StaticInit
- {
- public:
- StaticInit() : loc(wxLANGUAGE_DEFAULT) //wxLocale: we need deferred initialization, sigh...
- {
- //::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 = wxString::FromUTF8(localInfo->thousands_sep);
- DECIMAL_POINT = wxString::FromUTF8(localInfo->decimal_point);
-
- // 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)
- } dummy;
-
- activeLanguage = language;
-
- //default: english
- wxString languageFile;
-
- //(try to) retrieve language filename
- const int mappedLanguage = mapLanguageDialect(language);
- for (std::vector<LocInfoLine>::const_iterator i = LocalizationInfo::get().begin(); i != LocalizationInfo::get().end(); ++i)
- if (i->languageID == mappedLanguage)
- {
- languageFile = i->languageFile;
- break;
- }
-
- //load language file into buffer
- activeTranslation.clear();
- if (!languageFile.empty())
- {
- loadTranslation(languageFile, activeTranslation); //empty translation on error
- if (activeTranslation.empty())
- {
- wxMessageBox(wxString(_("Error reading file:")) + wxT(" \"") + languageFile + wxT("\""), _("Error"), wxOK | wxICON_ERROR);
- activeLanguage = wxLANGUAGE_ENGLISH; //reset to english language to show this error just once
- }
- }
- else
- ; //if languageFile is empty texts will be english per default
+std::auto_ptr<TranslationHandler> globalHandler;
}
-
-int ffs3::getLanguage()
+void zen::setTranslator(TranslationHandler* newHandler)
{
- return activeLanguage;
+ globalHandler.reset(newHandler);
}
-int ffs3::retrieveSystemLanguage()
+TranslationHandler* zen::getTranslator()
{
- return wxLocale::GetSystemLanguage();
-}
-
-
-
-//http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html
-//http://translate.sourceforge.net/wiki/l10n/pluralforms
-/*
-Plural forms parser: Grammar
-----------------------------
-expression:
- conditional-expression
-
-conditional-expression:
- logical-or-expression
- logical-or-expression ? expression : expression
-
-logical-or-expression:
- logical-and-expression
- logical-or-expression || logical-and-expression
-
-logical-and-expression:
- equality-expression
- logical-and-expression && equality-expression
-
-equality-expression:
- relational-expression
- relational-expression == relational-expression
- relational-expression != relational-expression
-
-relational-expression:
- multiplicative-expression
- multiplicative-expression > multiplicative-expression
- multiplicative-expression < multiplicative-expression
- multiplicative-expression >= multiplicative-expression
- multiplicative-expression <= multiplicative-expression
-
-multiplicative-expression:
- pm-expression
- multiplicative-expression % pm-expression
-
-pm-expression:
- N
- Number
- ( Expression )
-*/
-
-
-
-//expression interface
-struct Expression { virtual ~Expression() {} };
-
-template <class T>
-struct Expr : public Expression
-{
- typedef T ValueType;
- virtual ValueType eval() const = 0;
-};
-
-//specific binary expression based on STL function objects
-template <class StlOp>
-struct BinaryExp : public Expr<typename StlOp::result_type>
-{
- typedef const Expr<typename StlOp::first_argument_type> SourceExp;
-
- BinaryExp(const SourceExp& lhs, const SourceExp& rhs, StlOp biop) : lhs_(lhs), rhs_(rhs), biop_(biop) {}
- virtual typename StlOp::result_type eval() const { return biop_(lhs_.eval(), rhs_.eval()); }
- const SourceExp& lhs_;
- const SourceExp& rhs_;
- StlOp biop_;
-};
-
-template <class StlOp>
-inline
-BinaryExp<StlOp> makeBiExp(const Expression& lhs, const Expression& rhs, StlOp biop) //throw (std::bad_cast)
-{
- return BinaryExp<StlOp>(dynamic_cast<const Expr<typename StlOp::first_argument_type >&>(lhs),
- dynamic_cast<const Expr<typename StlOp::second_argument_type>&>(rhs), biop);
-}
-
-template <class Out>
-struct TernaryExp : public Out
-{
- TernaryExp(const Expr<bool>& ifExp, const Out& thenExp, const Out& elseExp) : ifExp_(ifExp), thenExp_(thenExp), elseExp_(elseExp) {}
- virtual typename Out::ValueType eval() const { return ifExp_.eval() ? thenExp_.eval() : elseExp_.eval(); }
- const Expr<bool>& ifExp_;
- const Out& thenExp_;
- const Out& elseExp_;
-};
-
-struct LiteralNumberEx : public Expr<int>
-{
- LiteralNumberEx(int n) : n_(n) {}
- virtual int eval() const { return n_; }
- int n_;
-};
-
-struct NumberN : public Expr<int>
-{
- NumberN(int& n) : n_(n) {}
- virtual int eval() const { return n_; }
- int& n_;
-};
-
-
-typedef Zbase<wchar_t> Wstring;
-
-
-class PluralForm
-{
-public:
- struct ParsingError {};
-
- PluralForm(const Wstring& phrase) : n_(0) //.po format,e.g.: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)
- {
- Parser(phrase, //in
- expr, //out
- n_, //
- count, //
- dump); //
- }
-
- int formCount() const { return count; }
-
- int getForm(int n) const { n_ = n ; return expr->eval(); }
-
-private:
- typedef std::list<boost::shared_ptr<Expression> > DumpList;
-
- struct Token
- {
- enum Type
- {
- TK_FORM_COUNT,
- TK_PHRASE_BEGIN,
- TK_ASSIGN,
- TK_SEMICOLON,
- TK_TERNARY_QUEST,
- TK_TERNARY_COLON,
- TK_OR,
- TK_AND,
- TK_EQUAL,
- TK_NOT_EQUAL,
- TK_LESS,
- TK_LESS_EQUAL,
- TK_GREATER,
- TK_GREATER_EQUAL,
- TK_MODULUS,
- TK_N,
- TK_NUMBER,
- TK_BRACKET_LEFT,
- TK_BRACKET_RIGHT,
- TK_END
- };
-
- Token(Type t) : type(t), number(0) {}
-
- Type type;
- int number; //if type == TK_NUMBER
- };
-
- class Scanner
- {
- public:
- Scanner(const Wstring& phrase) : phrase_(phrase)
- {
- tokens.push_back(std::make_pair(L"nplurals", Token::TK_FORM_COUNT));
- tokens.push_back(std::make_pair(L"plural" , Token::TK_PHRASE_BEGIN));
- tokens.push_back(std::make_pair(L";" , Token::TK_SEMICOLON ));
- tokens.push_back(std::make_pair(L"?" , Token::TK_TERNARY_QUEST));
- tokens.push_back(std::make_pair(L":" , Token::TK_TERNARY_COLON));
- tokens.push_back(std::make_pair(L"||", Token::TK_OR ));
- tokens.push_back(std::make_pair(L"&&", Token::TK_AND ));
- tokens.push_back(std::make_pair(L"==", Token::TK_EQUAL ));
- tokens.push_back(std::make_pair(L"=" , Token::TK_ASSIGN ));
- tokens.push_back(std::make_pair(L"!=", Token::TK_NOT_EQUAL ));
- tokens.push_back(std::make_pair(L"<=", Token::TK_LESS_EQUAL ));
- tokens.push_back(std::make_pair(L"<" , Token::TK_LESS ));
- tokens.push_back(std::make_pair(L">=", Token::TK_GREATER_EQUAL));
- tokens.push_back(std::make_pair(L">" , Token::TK_GREATER ));
- tokens.push_back(std::make_pair(L"%" , Token::TK_MODULUS ));
- tokens.push_back(std::make_pair(L"n" , Token::TK_N ));
- tokens.push_back(std::make_pair(L"N" , Token::TK_N ));
- tokens.push_back(std::make_pair(L"(" , Token::TK_BRACKET_LEFT ));
- tokens.push_back(std::make_pair(L")" , Token::TK_BRACKET_RIGHT));
- }
-
- Token nextToken()
- {
- phrase_.Trim(true, false); //remove whitespace
-
- if (phrase_.empty()) return Token(Token::TK_END);
-
- for (TokenList::const_iterator i = tokens.begin(); i != tokens.end(); ++i)
- if (phrase_.StartsWith(i->first))
- {
- phrase_ = phrase_.substr(i->first.size());
- return Token(i->second);
- }
-
- Wstring::iterator digitEnd = std::find_if(phrase_.begin(), phrase_.end(), std::not1(std::ptr_fun(std::iswdigit)));
- int digitCount = digitEnd - phrase_.begin();
- if (digitCount != 0)
- {
- Token out(Token::TK_NUMBER);
- out.number = Wstring(phrase_.c_str(), digitCount).toNumber<int>();
- phrase_ = phrase_.substr(digitCount);
- return out;
- }
-
- throw ParsingError(); //unknown token
- }
-
- private:
- typedef std::vector<std::pair<Wstring, Token::Type> > TokenList;
- TokenList tokens;
- Wstring phrase_;
- };
-
-
- class Parser
- {
- public:
- Parser(const Wstring& phrase, //in
- const Expr<int>*& expr, int& n, int& count, PluralForm::DumpList& dump) ://out
- scn(phrase),
- tk(scn.nextToken()),
- n_(n),
- dump_(dump)
- {
- consumeToken(Token::TK_FORM_COUNT);
- consumeToken(Token::TK_ASSIGN);
-
- count = token().number;
- consumeToken(Token::TK_NUMBER);
-
- consumeToken(Token::TK_SEMICOLON);
- consumeToken(Token::TK_PHRASE_BEGIN);
- consumeToken(Token::TK_ASSIGN);
-
- try
- {
- const Expression& e = parse();
- expr = &dynamic_cast<const Expr<int>&>(e);
- }
- catch(std::bad_cast&) { throw ParsingError(); }
-
- consumeToken(Token::TK_END);
- }
-
- private:
- void nextToken() { tk = scn.nextToken(); }
- const Token& token() const { return tk; }
-
- void consumeToken(Token::Type t)
- {
- if (token().type != t)
- throw ParsingError();
- nextToken();
- }
-
- const Expression& parse() { return parseConditional(); };
-
- const Expression& parseConditional()
- {
- const Expression& e = parseLogicalOr();
-
- if (token().type == Token::TK_TERNARY_QUEST)
- {
- nextToken();
- const Expression& thenEx = parse(); //associativity: <-
- consumeToken(Token::TK_TERNARY_COLON);
- const Expression& elseEx = parse(); //
-
- return manageObj(TernaryExp<Expr<int> >(dynamic_cast<const Expr<bool>&>(e),
- dynamic_cast<const Expr<int>&>(thenEx),
- dynamic_cast<const Expr<int>&>(elseEx)));
- }
- return e;
- }
-
- const Expression& parseLogicalOr()
- {
- const Expression* e = &parseLogicalAnd();
- for (;;) //associativity: ->
- if (token().type == Token::TK_OR)
- {
- nextToken();
- const Expression& rhs = parseLogicalAnd();
- e = &manageObj(makeBiExp(*e, rhs, std::logical_or<bool>()));
- }
- else break;
- return *e;
- }
-
- const Expression& parseLogicalAnd()
- {
- const Expression* e = &parseEquality();
- for (;;) //associativity: ->
- if (token().type == Token::TK_AND)
- {
- nextToken();
- const Expression& rhs = parseEquality();
-
- e = &manageObj(makeBiExp(*e, rhs, std::logical_and<bool>()));
- }
- else break;
- return *e;
- }
-
- const Expression& parseEquality()
- {
- const Expression& e = parseRelational();
-
- Token::Type t = token().type;
- if (t == Token::TK_EQUAL || t == Token::TK_NOT_EQUAL) //associativity: n/a
- {
- nextToken();
- const Expression& rhs = parseRelational();
-
- if (t == Token::TK_EQUAL)
- return manageObj(makeBiExp(e, rhs, std::equal_to<int>()));
- else
- return manageObj(makeBiExp(e, rhs, std::not_equal_to<int>()));
- }
- return e;
- }
-
- const Expression& parseRelational()
- {
- const Expression& e = parseMultiplicative();
-
- Token::Type t = token().type;
- if (t == Token::TK_LESS || //associativity: n/a
- t == Token::TK_LESS_EQUAL||
- t == Token::TK_GREATER ||
- t == Token::TK_GREATER_EQUAL)
- {
- nextToken();
- const Expression& rhs = parseMultiplicative();
-
- if (t == Token::TK_LESS) return manageObj(makeBiExp(e, rhs, std::less <int>()));
- if (t == Token::TK_LESS_EQUAL) return manageObj(makeBiExp(e, rhs, std::less_equal <int>()));
- if (t == Token::TK_GREATER) return manageObj(makeBiExp(e, rhs, std::greater <int>()));
- if (t == Token::TK_GREATER_EQUAL) return manageObj(makeBiExp(e, rhs, std::greater_equal<int>()));
- }
- return e;
- }
-
- const Expression& parseMultiplicative()
- {
- const Expression* e = &parsePrimary();
-
- for (;;) //associativity: ->
- if (token().type == Token::TK_MODULUS)
- {
- nextToken();
- const Expression& rhs = parsePrimary();
-
- //"compile-time" check: n % 0
- const LiteralNumberEx* literal = dynamic_cast<const LiteralNumberEx*>(&rhs);
- if (literal && literal->eval() == 0)
- throw ParsingError();
-
- e = &manageObj(makeBiExp(*e, rhs, std::modulus<int>()));
- }
- else break;
- return *e;
- }
-
- const Expression& parsePrimary()
- {
- if (token().type == Token::TK_N)
- {
- nextToken();
- return manageObj(NumberN(n_));
- }
- else if (token().type == Token::TK_NUMBER)
- {
- const int number = token().number;
- nextToken();
- return manageObj(LiteralNumberEx(number));
- }
- else if (token().type == Token::TK_BRACKET_LEFT)
- {
- nextToken();
- const Expression& e = parse();
-
- consumeToken(Token::TK_BRACKET_RIGHT);
- return e;
- }
- else
- throw ParsingError();
- }
-
- template <class T>
- const T& manageObj(const T& obj)
- {
- boost::shared_ptr<Expression> newEntry(new T(obj));
- dump_.push_back(newEntry);
- return static_cast<T&>(*dump_.back());
- }
-
- Scanner scn;
- Token tk;
-
- int& n_;
- DumpList& dump_; //manage polymorphc object lifetimes
- };
-
- const Expr<int>* expr;
- mutable int n_;
- int count;
-
- PluralForm::DumpList dump; //manage polymorphc object lifetimes
-};
-
-
-const wchar_t formPol[] = L"nplurals=3; plural=n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 > 20) ? 1 : 2";
-int tstPol(int n)
-{
- return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 > 20) ? 1 : 2;
-}
-
-const wchar_t formRu[] = L"nplurals= 3; plural=n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 > 20) ? 1 : 2";
-int tstRu(int n)
-{
- return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 > 20) ? 1 : 2 ;
-}
-
-const wchar_t formLit[] = L"nplurals =3; plural=n% 10 == 1&& n % 100 != 11 ? 0 : n % 100 != 12&& n % 10 == 2 ? 1 : 0";
-int tstLit(int n)
-{
- return n % 10 == 1&& n % 100 != 11 ? 0 : n % 100 != 12&& n % 10 == 2 ? 1 : 0;
-}
-
-const wchar_t formArab[] = L"nplurals = 6; plural = n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : (n % 100 >= 3 && n % 100 <= 10) ? 3 : (n % 100 >= 11 && n % 100 <= 99) || (n % 100 == 1) || (n % 100 ==2) ? 4 : 5";
-int tstArab(int n)
-{
- return n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : (n % 100 >= 3 && n % 100 <= 10) ? 3 : (n % 100 >= 11 && n % 100 <= 99) || (n % 100 == 1) || (n % 100 ==2) ? 4 : 5;
-}
-
-const wchar_t formGerm[] = L"nplurals=2; plural= n == 1 ? 0 : 1";
-int tstGerm(int n)
-{
- return n == 1 ? 0 : 1;
-}
-
-const wchar_t formFren[] = L"nplurals=2; plural= n <= 1 ? 0 : 1";
-int tstFren(int n)
-{
- return n <= 1 ? 0 : 1;
-}
-
-const wchar_t formJap[] = L"nplurals=1; plural=0";
-int tstJap(int n)
-{
- return 0;
-}
-
-const wchar_t formRom[] = L"nplurals=3; plural= n == 1 ? 0 : n == 0 || (n % 100 >= 1 && n % 100 <= 20) ? 1 : 2 ";
-int tstRom(int n)
-{
- return n == 1 ? 0 : n == 0 || (n % 100 >= 1 && n % 100 <= 20) ? 1 : 2 ;
-}
-
-const wchar_t formCze[] = L" nplurals=3; plural= n % 100 == 1 ? 0 : n % 100 >= 2 && n % 100 <= 4 ? 1 : 2";
-int tstCze(int n)
-{
- return n % 100 == 1 ? 0 : n % 100 >= 2 && n % 100 <= 4 ? 1 : 2;
-}
-
-const wchar_t formSlov[] = L" nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3 ";
-int tstSlov(int n)
-{
- return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3;
-}
-
-void unitTest()
-{
- typedef int (*TestFun)(int);
- typedef std::vector<std::pair<const wchar_t*, TestFun> > PhraseFunList;
- PhraseFunList phrases;
- phrases.push_back(std::make_pair(formPol, &tstPol));
- phrases.push_back(std::make_pair(formRu, &tstRu));
- phrases.push_back(std::make_pair(formLit, &tstLit));
- phrases.push_back(std::make_pair(formArab, &tstArab));
- phrases.push_back(std::make_pair(formGerm, &tstGerm));
- phrases.push_back(std::make_pair(formFren, &tstFren));
- phrases.push_back(std::make_pair(formJap, &tstJap));
- phrases.push_back(std::make_pair(formRom, &tstRom));
- phrases.push_back(std::make_pair(formCze, &tstCze));
- phrases.push_back(std::make_pair(formSlov, &tstSlov));
-
- for (PhraseFunList::const_iterator i = phrases.begin(); i != phrases.end(); ++i)
- {
- PluralForm pf(i->first);
- for (int j = 0; j < 10000000; ++j)
- assert((i->second)(j) == pf.getForm(j));
- }
-}
-
-
-wxString ffs3::translate(const wxString& original) //translate into currently selected language
-{
- /*
- int ba = 3;
-
- unitTest();
-
-#ifndef _MSC_VER
-#warning 3434
-#endif
-
- */
-
-
-
- //look for translation in buffer table
- const Translation::const_iterator i = activeTranslation.find(original);
- if (i != activeTranslation.end())
- return i->second.c_str();
-
- //fallback
- return original;
+ return globalHandler.get();
}
bgstack15