From: Vadim Zeitlin Date: Wed, 21 Mar 2001 19:07:23 +0000 (+0000) Subject: minor fixes to wxLocale::GetSystemLanguage(), test code for it added to the console... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/ec37df5776f89de888cdef2ac1445896d283590a minor fixes to wxLocale::GetSystemLanguage(), test code for it added to the console sample git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9562 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/intl.h b/include/wx/intl.h index 5d18ea981f..a4468a948c 100644 --- a/include/wx/intl.h +++ b/include/wx/intl.h @@ -42,6 +42,7 @@ // ---------------------------------------------------------------------------- // forward decls // ---------------------------------------------------------------------------- + class WXDLLEXPORT wxLocale; class WXDLLEXPORT wxMsgCatalog; class WXDLLEXPORT wxLanguageInfoArray; @@ -50,7 +51,6 @@ class WXDLLEXPORT wxLanguageInfoArray; // locale support // ============================================================================ - // ---------------------------------------------------------------------------- // wxLanguage: defines all supported languages // ---------------------------------------------------------------------------- @@ -62,6 +62,7 @@ enum wxLanguage { // user's default/preffered language as got from OS: wxLANGUAGE_DEFAULT, + // unknown language, if wxLocale::GetSystemLanguage fails: wxLANGUAGE_UNKNOWN, @@ -313,9 +314,6 @@ struct WXDLLEXPORT wxLanguageInfo wxString Description; // human-readable name of the language }; - - - // ---------------------------------------------------------------------------- // wxLocale: encapsulates all language dependent settings, including current // message catalogs, date, time and currency formats (TODO) &c @@ -347,7 +345,7 @@ public: Init(szName, szShort, szLocale, bLoadDefault, bConvertEncoding); } - wxLocale(int language, // wxLanguage identifier + wxLocale(int language, // wxLanguage id or custom language int flags = wxLOCALE_LOAD_DEFAULT | wxLOCALE_CONV_ENCODING) { Init(language, flags); } @@ -358,14 +356,15 @@ public: bool bLoadDefault = TRUE, bool bConvertEncoding = FALSE); + // same as second ctor (returns TRUE on success) bool Init(int language = wxLANGUAGE_DEFAULT, int flags = wxLOCALE_LOAD_DEFAULT | wxLOCALE_CONV_ENCODING); + // restores old locale ~wxLocale(); // Try to get user's (or OS's) prefered language setting. - // Return wxLanguage value or wxLANGUAGE_UNKNOWN if language-guessing - // algorithm failed + // Return wxLANGUAGE_UNKNOWN if language-guessing algorithm failed int GetSystemLanguage() const; // return TRUE if the locale was set successfully diff --git a/samples/console/console.cpp b/samples/console/console.cpp index 702be27023..f8995d43d9 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -37,7 +37,7 @@ //#define TEST_ARRAYS //#define TEST_CMDLINE -#define TEST_DATETIME +//#define TEST_DATETIME //#define TEST_DIR //#define TEST_DLLLOADER //#define TEST_ENVIRON @@ -49,6 +49,7 @@ //#define TEST_HASH //#define TEST_INFO_FUNCTIONS //#define TEST_LIST +#define TEST_LOCALE //#define TEST_LOG //#define TEST_LONGLONG //#define TEST_MIME @@ -61,7 +62,7 @@ //#define TEST_TIMER //#define TEST_VCARD -- don't enable this (VZ) //#define TEST_WCHAR -#define TEST_ZIP +//#define TEST_ZIP //#define TEST_ZLIB @@ -808,6 +809,293 @@ static void TestListCtor() #endif // TEST_LIST +// ---------------------------------------------------------------------------- +// wxLocale +// ---------------------------------------------------------------------------- + +#ifdef TEST_LOCALE + +#include "wx/intl.h" +#include "wx/utils.h" // for wxSetEnv + +static wxLocale gs_localeDefault(wxLANGUAGE_ENGLISH); + +// find the name of the language from its value +static const char *GetLangName(int lang) +{ + static const char *languageNames[] = + { + "DEFAULT", + "UNKNOWN", + "ABKHAZIAN", + "AFAR", + "AFRIKAANS", + "ALBANIAN", + "AMHARIC", + "ARABIC", + "ARABIC_ALGERIA", + "ARABIC_BAHRAIN", + "ARABIC_EGYPT", + "ARABIC_IRAQ", + "ARABIC_JORDAN", + "ARABIC_KUWAIT", + "ARABIC_LEBANON", + "ARABIC_LIBYA", + "ARABIC_MOROCCO", + "ARABIC_OMAN", + "ARABIC_QATAR", + "ARABIC_SAUDI_ARABIA", + "ARABIC_SUDAN", + "ARABIC_SYRIA", + "ARABIC_TUNISIA", + "ARABIC_UAE", + "ARABIC_YEMEN", + "ARMENIAN", + "ASSAMESE", + "AYMARA", + "AZERI", + "AZERI_CYRILLIC", + "AZERI_LATIN", + "BASHKIR", + "BASQUE", + "BELARUSIAN", + "BENGALI", + "BHUTANI", + "BIHARI", + "BISLAMA", + "BRETON", + "BULGARIAN", + "BURMESE", + "CAMBODIAN", + "CATALAN", + "CHINESE", + "CHINESE_SIMPLIFIED", + "CHINESE_TRADITIONAL", + "CHINESE_HONGKONG", + "CHINESE_MACAU", + "CHINESE_SINGAPORE", + "CHINESE_TAIWAN", + "CORSICAN", + "CROATIAN", + "CZECH", + "DANISH", + "DUTCH", + "DUTCH_BELGIAN", + "ENGLISH", + "ENGLISH_UK", + "ENGLISH_US", + "ENGLISH_AUSTRALIA", + "ENGLISH_BELIZE", + "ENGLISH_BOTSWANA", + "ENGLISH_CANADA", + "ENGLISH_CARIBBEAN", + "ENGLISH_DENMARK", + "ENGLISH_EIRE", + "ENGLISH_JAMAICA", + "ENGLISH_NEW_ZEALAND", + "ENGLISH_PHILIPPINES", + "ENGLISH_SOUTH_AFRICA", + "ENGLISH_TRINIDAD", + "ENGLISH_ZIMBABWE", + "ESPERANTO", + "ESTONIAN", + "FAEROESE", + "FARSI", + "FIJI", + "FINNISH", + "FRENCH", + "FRENCH_BELGIAN", + "FRENCH_CANADIAN", + "FRENCH_LUXEMBOURG", + "FRENCH_MONACO", + "FRENCH_SWISS", + "FRISIAN", + "GALICIAN", + "GEORGIAN", + "GERMAN", + "GERMAN_AUSTRIAN", + "GERMAN_BELGIUM", + "GERMAN_LIECHTENSTEIN", + "GERMAN_LUXEMBOURG", + "GERMAN_SWISS", + "GREEK", + "GREENLANDIC", + "GUARANI", + "GUJARATI", + "HAUSA", + "HEBREW", + "HINDI", + "HUNGARIAN", + "ICELANDIC", + "INDONESIAN", + "INTERLINGUA", + "INTERLINGUE", + "INUKTITUT", + "INUPIAK", + "IRISH", + "ITALIAN", + "ITALIAN_SWISS", + "JAPANESE", + "JAVANESE", + "KANNADA", + "KASHMIRI", + "KASHMIRI_INDIA", + "KAZAKH", + "KERNEWEK", + "KINYARWANDA", + "KIRGHIZ", + "KIRUNDI", + "KONKANI", + "KOREAN", + "KURDISH", + "LAOTHIAN", + "LATIN", + "LATVIAN", + "LINGALA", + "LITHUANIAN", + "MACEDONIAN", + "MALAGASY", + "MALAY", + "MALAYALAM", + "MALAY_BRUNEI_DARUSSALAM", + "MALAY_MALAYSIA", + "MALTESE", + "MANIPURI", + "MAORI", + "MARATHI", + "MOLDAVIAN", + "MONGOLIAN", + "NAURU", + "NEPALI", + "NEPALI_INDIA", + "NORWEGIAN_BOKMAL", + "NORWEGIAN_NYNORSK", + "OCCITAN", + "ORIYA", + "OROMO", + "PASHTO", + "POLISH", + "PORTUGUESE", + "PORTUGUESE_BRAZILIAN", + "PUNJABI", + "QUECHUA", + "RHAETO_ROMANCE", + "ROMANIAN", + "RUSSIAN", + "RUSSIAN_UKRAINE", + "SAMOAN", + "SANGHO", + "SANSKRIT", + "SCOTS_GAELIC", + "SERBIAN", + "SERBIAN_CYRILLIC", + "SERBIAN_LATIN", + "SERBO_CROATIAN", + "SESOTHO", + "SETSWANA", + "SHONA", + "SINDHI", + "SINHALESE", + "SISWATI", + "SLOVAK", + "SLOVENIAN", + "SOMALI", + "SPANISH", + "SPANISH_ARGENTINA", + "SPANISH_BOLIVIA", + "SPANISH_CHILE", + "SPANISH_COLOMBIA", + "SPANISH_COSTA_RICA", + "SPANISH_DOMINICAN_REPUBLIC", + "SPANISH_ECUADOR", + "SPANISH_EL_SALVADOR", + "SPANISH_GUATEMALA", + "SPANISH_HONDURAS", + "SPANISH_MEXICAN", + "SPANISH_MODERN", + "SPANISH_NICARAGUA", + "SPANISH_PANAMA", + "SPANISH_PARAGUAY", + "SPANISH_PERU", + "SPANISH_PUERTO_RICO", + "SPANISH_URUGUAY", + "SPANISH_US", + "SPANISH_VENEZUELA", + "SUNDANESE", + "SWAHILI", + "SWEDISH", + "SWEDISH_FINLAND", + "TAGALOG", + "TAJIK", + "TAMIL", + "TATAR", + "TELUGU", + "THAI", + "TIBETAN", + "TIGRINYA", + "TONGA", + "TSONGA", + "TURKISH", + "TURKMEN", + "TWI", + "UIGHUR", + "UKRAINIAN", + "URDU", + "URDU_INDIA", + "URDU_PAKISTAN", + "UZBEK", + "UZBEK_CYRILLIC", + "UZBEK_LATIN", + "VIETNAMESE", + "VOLAPUK", + "WELSH", + "WOLOF", + "XHOSA", + "YIDDISH", + "YORUBA", + "ZHUANG", + "ZULU", + }; + + if ( (size_t)lang < WXSIZEOF(languageNames) ) + return languageNames[lang]; + else + return "INVALID"; +} + +static void TestDefaultLang() +{ + puts("*** Testing wxLocale::GetSystemLanguage ***"); + + static const wxChar *langStrings[] = + { + NULL, // system default + _T("C"), + _T("fr"), + _T("fr_FR"), + _T("en"), + _T("en_GB"), + _T("en_US"), + _T("de_DE.iso88591"), + _T("german"), + _T("?"), // invalid lang spec + _T("klingonese"), // I bet on some systems it does exist... + }; + + for ( size_t n = 0; n < WXSIZEOF(langStrings); n++ ) + { + const char *langStr = langStrings[n]; + if ( langStr ) + wxSetEnv(_T("LC_ALL"), langStr); + + int lang = gs_localeDefault.GetSystemLanguage(); + printf("Locale for '%s' is %s.\n", + langStr ? langStr : "system default", GetLangName(lang)); + } +} + +#endif // TEST_LOCALE + // ---------------------------------------------------------------------------- // MIME types // ---------------------------------------------------------------------------- @@ -4285,6 +4573,10 @@ int main(int argc, char **argv) TestListCtor(); #endif // TEST_LIST +#ifdef TEST_LOCALE + TestDefaultLang(); +#endif // TEST_LOCALE + #ifdef TEST_LOG wxString s; for ( size_t n = 0; n < 8000; n++ ) diff --git a/src/common/intl.cpp b/src/common/intl.cpp index e1dffe2952..d3cf3e156a 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -105,6 +105,11 @@ const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495; // extension of ".mo" files #define MSGCATALOG_EXTENSION _T(".mo") +// the constants describing the format of lang_LANG locale string +static const size_t LEN_LANG = 2; +static const size_t LEN_SUBLANG = 2; +static const size_t LEN_FULL = LEN_LANG + 1 + LEN_SUBLANG; // 1 for '_' + // ---------------------------------------------------------------------------- // global functions // ---------------------------------------------------------------------------- @@ -139,6 +144,23 @@ public: static wxLocale *wxSetLocale(wxLocale *pLocale); +// helper functions of GetSystemLanguage() +#ifdef __UNIX__ + +// get just the language part +static inline wxString ExtractLang(const wxString& langFull) +{ + return langFull.Left(LEN_LANG); +} + +// get everything else (including the leading '_') +static inline wxString ExtractNotLang(const wxString& langFull) +{ + return langFull.Mid(LEN_LANG); +} + +#endif // __UNIX__ + // ---------------------------------------------------------------------------- // wxMsgCatalog corresponds to one disk-file message catalog. // @@ -537,8 +559,6 @@ void wxMsgCatalog::ConvertEncoding() WX_DECLARE_EXPORTED_OBJARRAY(wxLanguageInfo, wxLanguageInfoArray); WX_DEFINE_OBJARRAY(wxLanguageInfoArray); - - wxLocale::wxLocale() { m_pszOldLocale = NULL; @@ -589,8 +609,6 @@ bool wxLocale::Init(const wxChar *szName, return bOk; } - - bool wxLocale::Init(int language, int flags) { wxLanguageInfo *info = NULL; @@ -602,8 +620,19 @@ bool wxLocale::Init(int language, int flags) InitLanguagesDB(); } - if (lang == wxLANGUAGE_DEFAULT) lang = GetSystemLanguage(); - if (lang != wxLANGUAGE_UNKNOWN) + if (lang == wxLANGUAGE_DEFAULT) + { + // auto detect the language + lang = GetSystemLanguage(); + } + + // We failed to detect system language, so we will use English: + if (lang == wxLANGUAGE_UNKNOWN) + { + return FALSE; + } + + if (lang != wxLANGUAGE_DEFAULT) { for (size_t i = 0; i < m_languagesDB->GetCount(); i++) { @@ -615,11 +644,6 @@ bool wxLocale::Init(int language, int flags) } } - // We failed to detect system language, so we will use English: - if (lang == wxLANGUAGE_UNKNOWN) - { - return FALSE; - } // Unknown language: if (info == NULL) { @@ -631,11 +655,13 @@ bool wxLocale::Init(int language, int flags) wxString canonical = info->CanonicalName; wxString locale; wxChar *retloc; - + // Set the locale: #ifdef __UNIX__ - if (language == wxLANGUAGE_DEFAULT) locale = wxEmptyString; - else locale = info->CanonicalName; + if (language == wxLANGUAGE_DEFAULT) + locale = wxEmptyString; + else + locale = info->CanonicalName; retloc = wxSetlocale(LC_ALL, locale); @@ -665,7 +691,6 @@ bool wxLocale::Init(int language, int flags) wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); return FALSE; } - #elif defined(__WIN32__) if (language != wxLANGUAGE_DEFAULT) { @@ -675,8 +700,8 @@ bool wxLocale::Init(int language, int flags) retloc = wxT("C"); } else - { - wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), + { + wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), SORT_DEFAULT); if (SetThreadLocale(lcid)) retloc = wxSetlocale(LC_ALL, wxEmptyString); @@ -713,11 +738,11 @@ bool wxLocale::Init(int language, int flags) wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); return FALSE; } - + #else return FALSE; #endif - + return Init(name, canonical, wxString(retloc), (flags & wxLOCALE_LOAD_DEFAULT) != 0, (flags & wxLOCALE_CONV_ENCODING) != 0); @@ -734,110 +759,152 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix) //else: already have it } - int wxLocale::GetSystemLanguage() const { - int wxlang = wxLANGUAGE_UNKNOWN; - size_t i; + wxCHECK_MSG( m_languagesDB != NULL, wxLANGUAGE_UNKNOWN, + _T("Languages DB not initialized, call wxLocale::Init!") ); + + // init i to avoid compiler warning + size_t i = 0, + count = m_languagesDB->GetCount(); - wxASSERT_MSG(m_languagesDB != NULL, "Languages DB not initialized, call wxLocale::Init!"); - #if defined(__UNIX__) - wxString lang; - if (!wxGetEnv(wxT("LC_ALL"), &lang) && - !wxGetEnv(wxT("LC_MESSAGES"), &lang) && - !wxGetEnv(wxT("LANG"), &lang)) + // first get the string identifying the language from the environment + wxString langFull; + if (!wxGetEnv(wxT("LC_ALL"), &langFull) && + !wxGetEnv(wxT("LC_MESSAGES"), &langFull) && + !wxGetEnv(wxT("LANG"), &langFull)) + { + // no language specified return wxLANGUAGE_UNKNOWN; + } - bool is_abbrev = lang.Len() == 2 || - (lang.Len() == 5 && lang[2] == wxT('_')); - - // 0. Make sure the abbrev is according to latest ISO 639 - // (this is neccessary because glibc uses iw and in instead - // of he and id respectively). - if (is_abbrev) + if ( langFull == _T("C") ) { - wxString mid = lang.Mid(0,2); - if (mid == wxT("iw")) lang = wxT("he") + lang.Mid(3); - else if (mid == wxT("in")) lang = wxT("id") + lang.Mid(3); - else if (mid == wxT("ji")) lang = wxT("yi") + lang.Mid(3); + // default C locale + return wxLANGUAGE_DEFAULT; } - // 1. Try to find the lang as is: - if (is_abbrev) + // the language string has the following form + // + // lang[_LANG[.encoding]] + // + // where lang is the primary language, LANG is a sublang + // + // for example, the following strings are valid: + // fr + // fr_FR + // de_DE.iso88591 + + // for now we don't use the encoding, although we probably should (doing + // translations of the msg catalogs on the fly as required) (TODO) + langFull = langFull.BeforeFirst(_T('.')); + + // in addition to the format above, we also can have full language names + // in LANG env var - for example, SuSE is known to use LANG="german" - so + // check for this + + // do we have just the language (or sublang too)? + bool justLang = langFull.Len() == LEN_LANG; + if ( justLang || + (langFull.Len() == LEN_FULL && langFull[LEN_LANG] == wxT('_')) ) { - for (i = 0; i < m_languagesDB->GetCount(); i++) + // 0. Make sure the lang is according to latest ISO 639 + // (this is neccessary because glibc uses iw and in instead + // of he and id respectively). + + // the language itself (second part is the dialect/sublang) + wxString langOrig = ExtractLang(langFull); + + wxString lang; + if ( langOrig == wxT("iw")) + lang = _T("he"); + else if ( langOrig == wxT("in") ) + lang = wxT("id"); + else if ( langOrig == wxT("ji") ) + lang = wxT("yi"); + else + lang = langOrig; + + // did we change it? + if ( lang != langOrig ) { - if (m_languagesDB->Item(i).CanonicalName == lang) + langFull = lang + ExtractNotLang(langFull); + } + + // 1. Try to find the language either as is: + for ( i = 0; i < count; i++ ) + { + if ( m_languagesDB->Item(i).CanonicalName == langFull ) { - wxlang = m_languagesDB->Item(i).Language; break; } } - } - // 2. If lang is of the form xx_YY, try to find xx: - if (wxlang == wxLANGUAGE_UNKNOWN && is_abbrev && lang.Len() == 5) - { - wxString lang2 = lang.Mid(0,2); - for (i = 0; i < m_languagesDB->GetCount(); i++) + // 2. If langFull is of the form xx_YY, try to find xx: + if ( i == count && !justLang ) { - if (m_languagesDB->Item(i).CanonicalName == lang2) + for ( i = 0; i < count; i++ ) { - wxlang = m_languagesDB->Item(i).Language; - break; + if ( m_languagesDB->Item(i).CanonicalName == lang ) + { + break; + } } } - } - // 3. If lang is of the form xx, try to find any xx_YY record: - if (wxlang == wxLANGUAGE_UNKNOWN && is_abbrev && lang.Len() == 2) - { - for (i = 0; i < m_languagesDB->GetCount(); i++) + // 3. If langFull is of the form xx, try to find any xx_YY record: + if ( i == count && justLang ) { - if (m_languagesDB->Item(i).CanonicalName.Mid(0,2) == lang) + for ( i = 0; i < count; i++ ) { - wxlang = m_languagesDB->Item(i).Language; - break; + if ( ExtractLang(m_languagesDB->Item(i).CanonicalName) + == langFull ) + { + break; + } } } } - - // 4. If everything failed, try to find the name in verbose description - // (SuSE is known to use LANG="german"): - if (wxlang == wxLANGUAGE_UNKNOWN && !is_abbrev) + else // not standard format { - for (i = 0; i < m_languagesDB->GetCount(); i++) + // try to find the name in verbose description + for ( i = 0; i < count; i++ ) { - if (m_languagesDB->Item(i).Description.CmpNoCase(lang) == 0) + if (m_languagesDB->Item(i).Description.CmpNoCase(langFull) == 0) { - wxlang = m_languagesDB->Item(i).Language; break; } } } - #elif defined(__WIN32__) LCID lcid = GetUserDefaultLCID(); - if (lcid == 0) return wxLANGUAGE_UNKNOWN; - wxUint32 lang = PRIMARYLANGID(LANGIDFROMLCID(lcid)); - wxUint32 sublang = SUBLANGID(LANGIDFROMLCID(lcid)); - - for (i = 0; i < m_languagesDB->GetCount(); i++) + if ( lcid != 0 ) { - if (m_languagesDB->Item(i).WinLang == lang && - m_languagesDB->Item(i).WinSublang == sublang) + wxUint32 lang = PRIMARYLANGID(LANGIDFROMLCID(lcid)); + wxUint32 sublang = SUBLANGID(LANGIDFROMLCID(lcid)); + + for ( i = 0; i < count; i++ ) { - wxlang = m_languagesDB->Item(i).Language; - break; + if (m_languagesDB->Item(i).WinLang == lang && + m_languagesDB->Item(i).WinSublang == sublang) + { + break; + } } } -#endif - - return wxlang; -} + //else: leave wxlang == wxLANGUAGE_UNKNOWN +#endif // Unix/Win32 + if ( i < count ) + { + // we did find a matching entry, use it + return m_languagesDB->Item(i).Language; + } + // no info about this language in the database + return wxLANGUAGE_UNKNOWN; +} void wxLocale::AddLanguage(const wxLanguageInfo& info) { @@ -845,15 +912,11 @@ void wxLocale::AddLanguage(const wxLanguageInfo& info) m_languagesDB->Add(info); } - - wxString wxLocale::GetSysName() const { return wxSetlocale(LC_ALL, NULL); } - - // clean up wxLocale::~wxLocale() { @@ -972,11 +1035,6 @@ bool wxLocale::AddCatalog(const wxChar *szDomain) } } - - - - - // ---------------------------------------------------------------------------- // global functions and variables // ---------------------------------------------------------------------------- @@ -999,9 +1057,6 @@ wxLocale *wxSetLocale(wxLocale *pLocale) return pOld; } - - - // ---------------------------------------------------------------------------- // default languages table & initialization // ---------------------------------------------------------------------------- @@ -1512,7 +1567,7 @@ void wxLocale::InitLanguagesDB() wxLanguageInfo info; wxStringTokenizer tkn; - LNG(wxLANGUAGE_ABKHAZIAN, "ab" , 0 , 0 , "Abkhazian") + LNG(wxLANGUAGE_ABKHAZIAN, "ab" , 0 , 0 , "Abkhazian") LNG(wxLANGUAGE_AFAR, "aa" , 0 , 0 , "Afar") LNG(wxLANGUAGE_AFRIKAANS, "af_ZA", LANG_AFRIKAANS , SUBLANG_DEFAULT , "Afrikaans") LNG(wxLANGUAGE_ALBANIAN, "sq_AL", LANG_ALBANIAN , SUBLANG_DEFAULT , "Albanian") @@ -1740,7 +1795,7 @@ void wxLocale::InitLanguagesDB() LNG(wxLANGUAGE_YORUBA, "yo" , 0 , 0 , "Yoruba") LNG(wxLANGUAGE_ZHUANG, "za" , 0 , 0 , "Zhuang") LNG(wxLANGUAGE_ZULU, "zu" , 0 , 0 , "Zulu") - + }; #undef LNG