#include "wx/hashset.h"
#include "wx/filesys.h"
-#if defined(__WXMAC__)
- #include "wx/mac/private.h" // includes mac headers
-#endif
-
#if defined(__DARWIN__)
- #include "wx/mac/corefoundation/cfref.h"
+ #include "wx/osx/core/cfref.h"
#include <CoreFoundation/CFLocale.h>
- #include "wx/mac/corefoundation/cfstring.h"
+ #include "wx/osx/core/cfstring.h"
#endif
// ----------------------------------------------------------------------------
const size_t32 MSGCATALOG_MAGIC = 0x950412de;
const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495;
-// the constants describing the format of lang_LANG locale string
+// the constants describing the format of ll_CC 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 '_'
static wxLocale *wxSetLocale(wxLocale *pLocale);
-// helper functions of GetSystemLanguage()
-#ifdef __UNIX__
+namespace
+{
// get just the language part
-static inline wxString ExtractLang(const wxString& langFull)
+inline wxString ExtractLang(const wxString& langFull)
{
return langFull.Left(LEN_LANG);
}
+// helper functions of GetSystemLanguage()
+#ifdef __UNIX__
+
// get everything else (including the leading '_')
-static inline wxString ExtractNotLang(const wxString& langFull)
+inline wxString ExtractNotLang(const wxString& langFull)
{
return langFull.Mid(LEN_LANG);
}
#endif // __UNIX__
+} // anonymous namespace
// ----------------------------------------------------------------------------
// Plural forms parser
bool wxPluralFormsScanner::nextToken()
{
wxPluralFormsToken::Type type = wxPluralFormsToken::T_ERROR;
- while (isspace(*m_s))
+ while (isspace((unsigned char) *m_s))
{
++m_s;
}
{
type = wxPluralFormsToken::T_EOF;
}
- else if (isdigit(*m_s))
+ else if (isdigit((unsigned char) *m_s))
{
wxPluralFormsToken::Number number = *m_s++ - '0';
- while (isdigit(*m_s))
+ while (isdigit((unsigned char) *m_s))
{
number = number * 10 + (*m_s++ - '0');
}
m_token.setNumber(number);
type = wxPluralFormsToken::T_NUMBER;
}
- else if (isalpha(*m_s))
+ else if (isalpha((unsigned char) *m_s))
{
const char* begin = m_s++;
- while (isalnum(*m_s))
+ while (isalnum((unsigned char) *m_s))
{
++m_s;
}
// facilitate doing pointer arithmetic with it
char *StringData() const
{
- return wx_static_cast(char *, m_data.GetData());
+ return static_cast<char *>(m_data.GetData());
}
const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const
// wxLanguageInfo
// ----------------------------------------------------------------------------
+#ifdef __WXMSW__
+
// helper used by wxLanguageInfo::GetLocaleName() and elsewhere to determine
// whether the locale is Unicode-only (it is if this function returns empty
// string)
return cp;
}
-#ifdef __WXMSW__
-
wxUint32 wxLanguageInfo::GetLCID() const
{
return MAKELCID(MAKELANGID(WinLang, WinSublang), SORT_DEFAULT);
bool wxMsgCatalogFile::Load(const wxString& szDirPrefix, const wxString& szName,
wxPluralFormsCalculatorPtr& rPluralFormsCalculator)
{
+ wxCHECK_MSG( szDirPrefix.length() >= LEN_LANG, false,
+ "invalid language specification" );
+
wxString searchPath;
#if wxUSE_FONTMAP
searchPath += GetFullSearchPath(szDirPrefix);
- size_t sublocaleIndex = szDirPrefix.find(wxS('_'));
- if ( sublocaleIndex != wxString::npos )
+ if ( szDirPrefix[LEN_LANG] == wxS('_') )
{
- // also add just base locale name: for things like "fr_BE" (belgium
- // french) we should use "fr" if no belgium specific message catalogs
- // exist
+ // also add just base locale name: for things like "fr_BE" (Belgium
+ // French) we should use fall back on plain "fr" if no Belgium-specific
+ // message catalogs exist
searchPath << wxPATH_SEP
- << GetFullSearchPath(szDirPrefix.Left(sublocaleIndex));
+ << GetFullSearchPath(ExtractLang(szDirPrefix));
}
// don't give translation errors here because the wxstd catalog might
// read the whole file in memory
if ( fileMsg.Read(m_data.GetWriteBuf(nSize), nSize) != lenFile )
return false;
+
+ m_data.UngetWriteBuf(nSize);
#endif // wxUSE_FILESYSTEM/!wxUSE_FILESYSTEM
const char *retloc = wxSetlocaleTryUTF8(LC_ALL, locale);
- const wxString langOnly = locale.Left(2);
+ const wxString langOnly = ExtractLang(locale);
if ( !retloc )
{
// Some C libraries don't like xx_YY form and require xx only
// so will translate the abbrev for them
wxString localeAlt;
if ( langOnly == wxS("he") )
- localeAlt = wxS("iw") + locale.Mid(3);
+ localeAlt = wxS("iw") + ExtractNotLang(locale);
else if ( langOnly == wxS("id") )
- localeAlt = wxS("in") + locale.Mid(3);
+ localeAlt = wxS("in") + ExtractNotLang(locale);
else if ( langOnly == wxS("yi") )
- localeAlt = wxS("ji") + locale.Mid(3);
+ localeAlt = wxS("ji") + ExtractNotLang(locale);
else if ( langOnly == wxS("nb") )
localeAlt = wxS("no_NO");
else if ( langOnly == wxS("nn") )
{
retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt);
if ( !retloc )
- retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt.Left(2));
+ retloc = wxSetlocaleTryUTF8(LC_ALL, ExtractLang(localeAlt));
}
}
}
else // language supported by Windows
{
- const wxUint32 lcid = info->GetLCID();
-
// Windows CE doesn't have SetThreadLocale() and there doesn't seem
// to be any equivalent
#ifndef __WXWINCE__
+ const wxUint32 lcid = info->GetLCID();
+
// change locale used by Windows functions
::SetThreadLocale(lcid);
#endif
if ( !retloc )
{
// Some C libraries don't like xx_YY form and require xx only
- retloc = wxSetlocale(LC_ALL, locale.Mid(0,2));
+ retloc = wxSetlocale(LC_ALL, ExtractLang(locale));
}
#else
wxUnusedVar(flags);
// for now we don't use the encoding, although we probably should (doing
// translations of the msg catalogs on the fly as required) (TODO)
//
- // we don't use the modifiers neither but we probably should translate
- // "euro" into iso885915
+ // we need the modified for languages like Valencian: ca_ES@valencia
+ // though, remember it
+ wxString modifier;
+ size_t posModifier = langFull.find_first_of(wxS("@"));
+ if ( posModifier != wxString::npos )
+ modifier = langFull.Mid(posModifier);
+
size_t posEndLang = langFull.find_first_of(wxS("@."));
if ( posEndLang != wxString::npos )
{
}
// 1. Try to find the language either as is:
- for ( i = 0; i < count; i++ )
+ // a) With modifier if set
+ if ( !modifier.empty() )
{
- if ( ms_languagesDB->Item(i).CanonicalName == langFull )
+ wxString langFullWithModifier = langFull + modifier;
+ for ( i = 0; i < count; i++ )
{
- break;
+ if ( ms_languagesDB->Item(i).CanonicalName == langFullWithModifier )
+ break;
+ }
+ }
+
+ // b) Without modifier
+ if ( modifier.empty() || i == count )
+ {
+ for ( i = 0; i < count; i++ )
+ {
+ if ( ms_languagesDB->Item(i).CanonicalName == langFull )
+ break;
}
}
return wxFONTENCODING_CP950;
}
#elif defined(__WXMAC__)
- TextEncoding encoding = 0 ;
+ CFStringEncoding encoding = 0 ;
encoding = CFStringGetSystemEncoding() ;
return wxMacGetFontEncFromSystemEnc( encoding ) ;
#elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP
if ( !tmp )
{
// Some C libraries don't like xx_YY form and require xx only
- tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName.Left(2));
+ tmp = wxSetlocaleTryUTF8(LC_ALL, ExtractLang(info->CanonicalName));
if ( !tmp )
return false;
}
const wxString& msgIdCharset)
{
- wxMsgCatalog *pMsgCat = new wxMsgCatalog;
-
- if ( pMsgCat->Load(m_strShort, szDomain, msgIdCharset, m_bConvertEncoding) ) {
- // add it to the head of the list so that in GetString it will
- // be searched before the catalogs added earlier
- pMsgCat->m_pNext = m_pMsgCat;
- m_pMsgCat = pMsgCat;
+ wxCHECK_MSG( IsOk(), false, "must initialize catalog first" );
- return true;
- }
- else {
- // don't add it because it couldn't be loaded anyway
- delete pMsgCat;
// It is OK to not load catalog if the msgid language and m_language match,
// in which case we can directly display the texts embedded in program's
// source code:
- if (m_language == msgIdLanguage)
+ if ( msgIdLanguage == m_language )
+ return true;
+
+
+ wxMsgCatalog *pMsgCat = new wxMsgCatalog;
+
+ if ( pMsgCat->Load(m_strShort, szDomain, msgIdCharset, m_bConvertEncoding) )
+ {
+ // add it to the head of the list so that in GetString it will
+ // be searched before the catalogs added earlier
+ pMsgCat->m_pNext = m_pMsgCat;
+ m_pMsgCat = pMsgCat;
+
return true;
+ }
+
+ // don't add it because it couldn't be loaded anyway
+ delete pMsgCat;
+
// If there's no exact match, we may still get partial match where the
// (basic) language is same, but the country differs. For example, it's
// permitted to use en_US strings from sources even if m_language is en_GB:
const wxLanguageInfo *msgIdLangInfo = GetLanguageInfo(msgIdLanguage);
if ( msgIdLangInfo &&
- msgIdLangInfo->CanonicalName.Mid(0, 2) == m_strShort.Mid(0, 2) )
+ ExtractLang(msgIdLangInfo->CanonicalName) == ExtractLang(m_strShort) )
{
return true;
}
return false;
- }
}
// ----------------------------------------------------------------------------
wxCFRef<CFLocaleRef> userLocaleRef(userLocaleRefRaw);
- CFTypeRef cfstr;
+ CFStringRef cfstr = 0;
switch ( index )
{
case wxLOCALE_THOUSANDS_SEP:
- cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
+ cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
break;
case wxLOCALE_DECIMAL_POINT:
- cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
+ cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
break;
default:
wxFAIL_MSG( "Unknown locale info" );
+ cfstr = CFSTR("");
+ break;
}
- wxCFStringRef
- str(CFStringCreateCopy(NULL, static_cast<CFStringRef>(cfstr)));
+ wxCFStringRef str(wxCFRetain(cfstr));
return str.AsString();
}
#ifndef LANG_RUSSIAN
#define LANG_RUSSIAN (0)
#endif
+#ifndef LANG_SAMI
+#define LANG_SAMI (0)
+#endif
#ifndef LANG_SANSKRIT
#define LANG_SANSKRIT (0)
#endif
LNG(wxLANGUAGE_FRENCH_SWISS, "fr_CH", LANG_FRENCH , SUBLANG_FRENCH_SWISS , wxLayout_LeftToRight, "French (Swiss)")
LNG(wxLANGUAGE_FRISIAN, "fy" , 0 , 0 , wxLayout_LeftToRight, "Frisian")
LNG(wxLANGUAGE_GALICIAN, "gl_ES", 0 , 0 , wxLayout_LeftToRight, "Galician")
- LNG(wxLANGUAGE_GEORGIAN, "ka" , LANG_GEORGIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Georgian")
+ LNG(wxLANGUAGE_GEORGIAN, "ka_GE", LANG_GEORGIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Georgian")
LNG(wxLANGUAGE_GERMAN, "de_DE", LANG_GERMAN , SUBLANG_GERMAN , wxLayout_LeftToRight, "German")
LNG(wxLANGUAGE_GERMAN_AUSTRIAN, "de_AT", LANG_GERMAN , SUBLANG_GERMAN_AUSTRIAN , wxLayout_LeftToRight, "German (Austrian)")
LNG(wxLANGUAGE_GERMAN_BELGIUM, "de_BE", 0 , 0 , wxLayout_LeftToRight, "German (Belgium)")
LNG(wxLANGUAGE_KIRUNDI, "rn" , 0 , 0 , wxLayout_LeftToRight, "Kirundi")
LNG(wxLANGUAGE_KONKANI, "" , LANG_KONKANI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Konkani")
LNG(wxLANGUAGE_KOREAN, "ko_KR", LANG_KOREAN , SUBLANG_KOREAN , wxLayout_LeftToRight, "Korean")
- LNG(wxLANGUAGE_KURDISH, "ku" , 0 , 0 , wxLayout_LeftToRight, "Kurdish")
+ LNG(wxLANGUAGE_KURDISH, "ku_TR", 0 , 0 , wxLayout_LeftToRight, "Kurdish")
LNG(wxLANGUAGE_LAOTHIAN, "lo" , 0 , 0 , wxLayout_LeftToRight, "Laothian")
LNG(wxLANGUAGE_LATIN, "la" , 0 , 0 , wxLayout_LeftToRight, "Latin")
LNG(wxLANGUAGE_LATVIAN, "lv_LV", LANG_LATVIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Latvian")
LNG(wxLANGUAGE_MOLDAVIAN, "mo" , 0 , 0 , wxLayout_LeftToRight, "Moldavian")
LNG(wxLANGUAGE_MONGOLIAN, "mn" , 0 , 0 , wxLayout_LeftToRight, "Mongolian")
LNG(wxLANGUAGE_NAURU, "na" , 0 , 0 , wxLayout_LeftToRight, "Nauru")
- LNG(wxLANGUAGE_NEPALI, "ne" , LANG_NEPALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Nepali")
+ LNG(wxLANGUAGE_NEPALI, "ne_NP", LANG_NEPALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Nepali")
LNG(wxLANGUAGE_NEPALI_INDIA, "ne_IN", LANG_NEPALI , SUBLANG_NEPALI_INDIA , wxLayout_LeftToRight, "Nepali (India)")
LNG(wxLANGUAGE_NORWEGIAN_BOKMAL, "nb_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_BOKMAL , wxLayout_LeftToRight, "Norwegian (Bokmal)")
LNG(wxLANGUAGE_NORWEGIAN_NYNORSK, "nn_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_NYNORSK , wxLayout_LeftToRight, "Norwegian (Nynorsk)")
LNG(wxLANGUAGE_ROMANIAN, "ro_RO", LANG_ROMANIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Romanian")
LNG(wxLANGUAGE_RUSSIAN, "ru_RU", LANG_RUSSIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Russian")
LNG(wxLANGUAGE_RUSSIAN_UKRAINE, "ru_UA", 0 , 0 , wxLayout_LeftToRight, "Russian (Ukraine)")
+ LNG(wxLANGUAGE_SAMI, "se_NO", LANG_SAMI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Northern Sami")
LNG(wxLANGUAGE_SAMOAN, "sm" , 0 , 0 , wxLayout_LeftToRight, "Samoan")
LNG(wxLANGUAGE_SANGHO, "sg" , 0 , 0 , wxLayout_LeftToRight, "Sangho")
LNG(wxLANGUAGE_SANSKRIT, "sa" , LANG_SANSKRIT , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Sanskrit")
LNG(wxLANGUAGE_SCOTS_GAELIC, "gd" , 0 , 0 , wxLayout_LeftToRight, "Scots Gaelic")
+ LNG(wxLANGUAGE_SERBIAN, "sr_RS", LANG_SERBIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Serbian")
+ LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_RS", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)")
+ LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_RS@latin", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)")
LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)")
- LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)")
+ LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_YU@latin", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)")
LNG(wxLANGUAGE_SERBO_CROATIAN, "sh" , 0 , 0 , wxLayout_LeftToRight, "Serbo-Croatian")
LNG(wxLANGUAGE_SESOTHO, "st" , 0 , 0 , wxLayout_LeftToRight, "Sesotho")
LNG(wxLANGUAGE_SETSWANA, "tn" , 0 , 0 , wxLayout_LeftToRight, "Setswana")
LNG(wxLANGUAGE_UZBEK, "uz" , LANG_UZBEK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Uzbek")
LNG(wxLANGUAGE_UZBEK_CYRILLIC, "uz" , LANG_UZBEK , SUBLANG_UZBEK_CYRILLIC , wxLayout_LeftToRight, "Uzbek (Cyrillic)")
LNG(wxLANGUAGE_UZBEK_LATIN, "uz" , LANG_UZBEK , SUBLANG_UZBEK_LATIN , wxLayout_LeftToRight, "Uzbek (Latin)")
+ LNG(wxLANGUAGE_VALENCIAN, "ca_ES@valencia", 0 , 0 , wxLayout_LeftToRight, "Valencian (Souternhern Catalan)")
LNG(wxLANGUAGE_VIETNAMESE, "vi_VN", LANG_VIETNAMESE, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Vietnamese")
LNG(wxLANGUAGE_VOLAPUK, "vo" , 0 , 0 , wxLayout_LeftToRight, "Volapuk")
LNG(wxLANGUAGE_WELSH, "cy" , 0 , 0 , wxLayout_LeftToRight, "Welsh")