intl.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,270 行 · 第 1/5 页

CPP
2,270
字号
        }
    }

#if wxUSE_WCHAR_T
    delete sourceConv;
    delete csConv;
#endif
}


// ----------------------------------------------------------------------------
// wxMsgCatalog class
// ----------------------------------------------------------------------------

bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName,
                        const wxChar *msgIdCharset, bool bConvertEncoding)
{
    wxMsgCatalogFile file;

    m_name = szName;

    if ( file.Load(szDirPrefix, szName, m_pluralFormsCalculator) )
    {
        file.FillHash(m_messages, msgIdCharset, bConvertEncoding);
        return true;
    }

    return false;
}

const wxChar *wxMsgCatalog::GetString(const wxChar *sz, size_t n) const
{
    int index = 0;
    if (n != size_t(-1))
    {
        index = m_pluralFormsCalculator->evaluate(n);
    }
    wxMessagesHash::const_iterator i;
    if (index != 0)
    {
        i = m_messages.find(wxString(sz) + wxChar(index));   // plural
    }
    else
    {
        i = m_messages.find(sz);
    }

    if ( i != m_messages.end() )
    {
        return i->second.c_str();
    }
    else
        return NULL;
}

// ----------------------------------------------------------------------------
// wxLocale
// ----------------------------------------------------------------------------

#include "wx/arrimpl.cpp"
WX_DECLARE_EXPORTED_OBJARRAY(wxLanguageInfo, wxLanguageInfoArray);
WX_DEFINE_OBJARRAY(wxLanguageInfoArray);

wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL;

/*static*/ void wxLocale::CreateLanguagesDB()
{
    if (ms_languagesDB == NULL)
    {
        ms_languagesDB = new wxLanguageInfoArray;
        InitLanguagesDB();
    }
}

/*static*/ void wxLocale::DestroyLanguagesDB()
{
    delete ms_languagesDB;
    ms_languagesDB = NULL;
}


void wxLocale::DoCommonInit()
{
  m_pszOldLocale = NULL;

  m_pOldLocale = wxSetLocale(this);

  m_pMsgCat = NULL;
  m_language = wxLANGUAGE_UNKNOWN;
  m_initialized = false;
}

// NB: this function has (desired) side effect of changing current locale
bool wxLocale::Init(const wxChar *szName,
                    const wxChar *szShort,
                    const wxChar *szLocale,
                    bool        bLoadDefault,
                    bool        bConvertEncoding)
{
  wxASSERT_MSG( !m_initialized,
                _T("you can't call wxLocale::Init more than once") );

  m_initialized = true;
  m_strLocale = szName;
  m_strShort = szShort;
  m_bConvertEncoding = bConvertEncoding;
  m_language = wxLANGUAGE_UNKNOWN;

  // change current locale (default: same as long name)
  if ( szLocale == NULL )
  {
    // the argument to setlocale()
    szLocale = szShort;

    wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") );
  }

#ifdef __WXWINCE__
  // FIXME: I'm guessing here
  wxChar localeName[256];
  int ret = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLANGUAGE, localeName,
      256);
  if (ret != 0)
  {
    m_pszOldLocale = wxStrdup(localeName);
  }
  else
    m_pszOldLocale = NULL;

  // TODO: how to find languageId
  // SetLocaleInfo(languageId, SORT_DEFAULT, localeName);
#else
  wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, szLocale);
  if ( oldLocale )
      m_pszOldLocale = wxStrdup(oldLocale);
  else
      m_pszOldLocale = NULL;
#endif

  if ( m_pszOldLocale == NULL )
    wxLogError(_("locale '%s' can not be set."), szLocale);

  // the short name will be used to look for catalog files as well,
  // so we need something here
  if ( m_strShort.empty() ) {
    // FIXME I don't know how these 2 letter abbreviations are formed,
    //       this wild guess is surely wrong
    if ( szLocale && szLocale[0] )
    {
        m_strShort += (wxChar)wxTolower(szLocale[0]);
        if ( szLocale[1] )
            m_strShort += (wxChar)wxTolower(szLocale[1]);
    }
  }

  // load the default catalog with wxWidgets standard messages
  m_pMsgCat = NULL;
  bool bOk = true;
  if ( bLoadDefault )
  {
    bOk = AddCatalog(wxT("wxstd"));

    // there may be a catalog with toolkit specific overrides, it is not
    // an error if this does not exist
    if ( bOk && wxTheApp )
    {
      wxAppTraits *traits = wxTheApp->GetTraits();
      if (traits)
        AddCatalog(traits->GetToolkitInfo().name.BeforeFirst(wxT('/')).MakeLower());
    }
  }

  return bOk;
}


#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__)
static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc)
{
    wxMB2WXbuf l = wxSetlocale(c, lc);
    if ( !l && lc && lc[0] != 0 )
    {
        wxString buf(lc);
        wxString buf2;
        buf2 = buf + wxT(".UTF-8");
        l = wxSetlocale(c, buf2.c_str());
        if ( !l )
        {
            buf2 = buf + wxT(".utf-8");
            l = wxSetlocale(c, buf2.c_str());
        }
        if ( !l )
        {
            buf2 = buf + wxT(".UTF8");
            l = wxSetlocale(c, buf2.c_str());
        }
        if ( !l )
        {
            buf2 = buf + wxT(".utf8");
            l = wxSetlocale(c, buf2.c_str());
        }
    }
    return l;
}
#else
#define wxSetlocaleTryUTF(c, lc)  wxSetlocale(c, lc)
#endif

bool wxLocale::Init(int language, int flags)
{
    int lang = language;
    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;
    }

    const wxLanguageInfo *info = GetLanguageInfo(lang);

    // Unknown language:
    if (info == NULL)
    {
        wxLogError(wxT("Unknown language %i."), lang);
        return false;
    }

    wxString name = info->Description;
    wxString canonical = info->CanonicalName;
    wxString locale;

    // Set the locale:
#if defined(__UNIX__) && !defined(__WXMAC__)
    if (language == wxLANGUAGE_DEFAULT)
        locale = wxEmptyString;
    else
        locale = info->CanonicalName;

    wxMB2WXbuf retloc = wxSetlocaleTryUTF(LC_ALL, locale);

#ifdef __AIX__
    // at least in AIX 5.2 libc is buggy and the string returned from setlocale(LC_ALL)
    // can't be passed back to it because it returns 6 strings (one for each locale
    // category), i.e. for C locale we get back "C C C C C C"
    //
    // this contradicts IBM own docs but this is not of much help, so just work around
    // it in the crudest possible manner
    wxChar *p = wxStrchr((wxChar *)retloc, _T(' '));
    if ( p )
        *p = _T('\0');
#endif // __AIX__

    if ( !retloc )
    {
        // Some C libraries don't like xx_YY form and require xx only
        retloc = wxSetlocaleTryUTF(LC_ALL, locale.Mid(0,2));
    }
    if ( !retloc )
    {
        // Some C libraries (namely glibc) still use old ISO 639,
        // so will translate the abbrev for them
        wxString mid = locale.Mid(0,2);
        if (mid == wxT("he"))
            locale = wxT("iw") + locale.Mid(3);
        else if (mid == wxT("id"))
            locale = wxT("in") + locale.Mid(3);
        else if (mid == wxT("yi"))
            locale = wxT("ji") + locale.Mid(3);
        else if (mid == wxT("nb"))
            locale = wxT("no_NO");
        else if (mid == wxT("nn"))
            locale = wxT("no_NY");

        retloc = wxSetlocaleTryUTF(LC_ALL, locale);
    }
    if ( !retloc )
    {
        // (This time, we changed locale in previous if-branch, so try again.)
        // Some C libraries don't like xx_YY form and require xx only
        retloc = wxSetlocaleTryUTF(LC_ALL, locale.Mid(0,2));
    }
    if ( !retloc )
    {
        wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str());
        return false;
    }
#elif defined(__WIN32__)

    #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__))
        // NB: setlocale() from msvcrt.dll (used by VC++ and Mingw)
        //     can't set locale to language that can only be written using
        //     Unicode.  Therefore wxSetlocale call failed, but we don't want
        //     to report it as an error -- so that at least message catalogs
        //     can be used. Watch for code marked with
        //     #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS bellow.
        #define SETLOCALE_FAILS_ON_UNICODE_LANGS
    #endif

#if !wxUSE_UNICODE
    const
#endif
    wxMB2WXbuf retloc = wxT("C");
    if (language != wxLANGUAGE_DEFAULT)
    {
        if (info->WinLang == 0)
        {
            wxLogWarning(wxT("Locale '%s' not supported by OS."), name.c_str());
            // retloc already set to "C"
        }
        else
        {
            int codepage
                         #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
                         = -1
                         #endif
                         ;
            wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang),
                                     SORT_DEFAULT);
            // FIXME
#ifndef __WXWINCE__
            SetThreadLocale(lcid);
#endif
            // NB: we must translate LCID to CRT's setlocale string ourselves,
            //     because SetThreadLocale does not modify change the
            //     interpretation of setlocale(LC_ALL, "") call:
            wxChar buffer[256];
            buffer[0] = wxT('\0');
            GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, 256);
            locale << buffer;
            if (GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, buffer, 256) > 0)
                locale << wxT("_") << buffer;
            if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buffer, 256) > 0)
            {
                codepage = wxAtoi(buffer);
                if (codepage != 0)
                    locale << wxT(".") << buffer;
            }
            if (locale.empty())
            {
                wxLogLastError(wxT("SetThreadLocale"));
                wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
                return false;
            }
            else
            {
            // FIXME
#ifndef __WXWINCE__
                retloc = wxSetlocale(LC_ALL, locale);
#endif
#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
                if (codepage == 0 && (const wxChar*)retloc == NULL)
                {
                    retloc = wxT("C");
                }
#endif
            }
        }
    }
    else
    {
            // FIXME
#ifndef __WXWINCE__
        retloc = wxSetlocale(LC_ALL, wxEmptyString);
#else
        retloc = NULL;
#endif
#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
        if ((const wxChar*)retloc == NULL)
        {
            wxChar buffer[16];
            if (GetLocaleInfo(LOCALE_USER_DEFAULT,
                              LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 &&
                 wxStrcmp(buffer, wxT("0")) == 0)
            {
                retloc = wxT("C");
            }
        }
#endif
    }

    if ( !retloc )
    {
        wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
        return false;
    }
#elif defined(__WXMAC__)
    if (lang == wxLANGUAGE_DEFAULT)
        locale = wxEmptyString;
    else
        locale = info->CanonicalName;

    wxMB2WXbuf retloc = wxSetlocale(LC_ALL, locale);

    if ( !retloc )
    {
        // Some C libraries don't like xx_YY form and require xx only
        retloc = wxSetlocale(LC_ALL, locale.Mid(0,2));
    }
    if ( !retloc )
    {
        wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str());
        return false;
    }
#elif defined(__WXPM__)
    wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString);
#else
    return false;
    #define WX_NO_LOCALE_SUPPORT
#endif

#ifndef WX_NO_LOCALE_SUPPORT
    wxChar *szLocale = retloc ? wxStrdup(retloc) : NULL;
    bool ret = Init(name, canonical, szLocale,
                    (flags & wxLOCALE_LOAD_DEFAULT) != 0,
                    (flags & wxLOCALE_CONV_ENCODING) != 0);
    free(szLocale);

    if (IsOk()) // setlocale() succeeded
        m_language = lang;

    return ret;
#endif
}



void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
{
    if ( s_searchPrefixes.Index(prefix) == wxNOT_FOUND )
    {
        s_searchPrefixes.Add(prefix);
    }
    //else: already have it
}

/*static*/ int wxLocale::GetSystemLanguage()
{
    CreateLanguagesDB();

    // init i to avoid compiler warning
    size_t i = 0,
           count = ms_languagesDB->GetCount();

#if defined(__UNIX__) && !defined(__WXMAC__)
    // 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))

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?