]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/translation.cpp
Supress SetFocus() warning in wxVListBoxComboPopup
[wxWidgets.git] / src / common / translation.cpp
index b34173f063614bc1c9fa29ae16e0c9c28ee72064..1e89106f9a1a3da03b5da416b3d7e8804f66470b 100644 (file)
@@ -45,7 +45,6 @@
 #include "wx/filename.h"
 #include "wx/tokenzr.h"
 #include "wx/fontmap.h"
-#include "wx/scopedptr.h"
 #include "wx/stdpaths.h"
 #include "wx/hashset.h"
 
@@ -65,29 +64,22 @@ const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495;
 
 #define TRACE_I18N wxS("i18n")
 
-// the constants describing the format of ll_CC locale string
-static const size_t LEN_LANG = 2;
-
-// ----------------------------------------------------------------------------
-// global functions
-// ----------------------------------------------------------------------------
+// ============================================================================
+// implementation
+// ============================================================================
 
 namespace
 {
 
-// get just the language part
-inline wxString ExtractLang(const wxString& langFull)
-{
-    return langFull.Left(LEN_LANG);
-}
+#if !wxUSE_UNICODE
+// We need to keep track of (char*) msgids in non-Unicode legacy builds. Instead
+// of making the public wxMsgCatalog and wxTranslationsLoader APIs ugly, we
+// store them in this global map.
+wxStringToStringHashMap gs_msgIdCharset;
+#endif
 
 } // anonymous namespace
 
-
-// ============================================================================
-// implementation
-// ============================================================================
-
 // ----------------------------------------------------------------------------
 // Plural forms parser
 // ----------------------------------------------------------------------------
@@ -433,7 +425,7 @@ private:
     wxPluralFormsNodePtr m_plural;
 };
 
-wxDEFINE_SCOPED_PTR_TYPE(wxPluralFormsCalculator)
+wxDEFINE_SCOPED_PTR(wxPluralFormsCalculator, wxPluralFormsCalculatorPtr)
 
 void wxPluralFormsCalculator::init(wxPluralFormsToken::Number nplurals,
                                 wxPluralFormsNode* plural)
@@ -804,12 +796,10 @@ wxPluralFormsCalculator* wxPluralFormsCalculator::make(const char* s)
 //       http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html
 // ----------------------------------------------------------------------------
 
-WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxString, wxMessagesHash);
-
 class wxMsgCatalogFile
 {
 public:
-    typedef wxScopedCharTypeBuffer<char> DataBuffer;
+    typedef wxScopedCharBuffer DataBuffer;
 
     // ctor & dtor
     wxMsgCatalogFile();
@@ -822,7 +812,7 @@ public:
                   wxPluralFormsCalculatorPtr& rPluralFormsCalculator);
 
     // fills the hash with string-translation pairs
-    bool FillHash(wxMessagesHash& hash, const wxString& msgIdCharset) const;
+    bool FillHash(wxStringToStringHashMap& hash, const wxString& domain) const;
 
     // return the charset of the strings in this catalog or empty string if
     // none/unknown
@@ -888,53 +878,6 @@ private:
     wxDECLARE_NO_COPY_CLASS(wxMsgCatalogFile);
 };
 
-
-// ----------------------------------------------------------------------------
-// wxMsgCatalog corresponds to one loaded message catalog.
-//
-// This is a "low-level" class and is used only by wxLocale (that's why
-// it's designed to be stored in a linked list)
-// ----------------------------------------------------------------------------
-
-class wxMsgCatalog
-{
-public:
-#if !wxUSE_UNICODE
-    wxMsgCatalog() { m_conv = NULL; }
-    ~wxMsgCatalog();
-#endif
-
-    // load the catalog from disk
-    bool LoadFile(const wxString& filename,
-                  const wxString& domain,
-                  const wxString& msgIdCharset);
-
-    bool LoadData(const wxScopedCharTypeBuffer<char>& data,
-                  const wxString& domain,
-                  const wxString& msgIdCharset);
-
-    // get name of the catalog
-    wxString GetDomain() const { return m_domain; }
-
-    // get the translated string: returns NULL if not found
-    const wxString *GetString(const wxString& sz, unsigned n = UINT_MAX) const;
-
-    // public variable pointing to the next element in a linked list (or NULL)
-    wxMsgCatalog *m_pNext;
-
-private:
-    wxMessagesHash  m_messages; // all messages in the catalog
-    wxString        m_domain;   // name of the domain
-
-#if !wxUSE_UNICODE
-    // the conversion corresponding to this catalog charset if we installed it
-    // as the global one
-    wxCSConv *m_conv;
-#endif
-
-    wxPluralFormsCalculatorPtr  m_pluralFormsCalculator;
-};
-
 // ----------------------------------------------------------------------------
 // wxMsgCatalogFile clas
 // ----------------------------------------------------------------------------
@@ -1076,10 +1019,10 @@ bool wxMsgCatalogFile::LoadData(const DataBuffer& data,
     return true;
 }
 
-bool wxMsgCatalogFile::FillHash(wxMessagesHash& hash,
-                                const wxString& msgIdCharset) const
+bool wxMsgCatalogFile::FillHash(wxStringToStringHashMap& hash,
+                                const wxString& domain) const
 {
-    wxUnusedVar(msgIdCharset); // silence warning in Unicode build
+    wxUnusedVar(domain); // silence warning in Unicode build
 
     // conversion to use to convert catalog strings to the GUI encoding
     wxMBConv *inputConv = NULL;
@@ -1107,6 +1050,8 @@ bool wxMsgCatalogFile::FillHash(wxMessagesHash& hash,
     }
 
 #if !wxUSE_UNICODE
+    wxString msgIdCharset = gs_msgIdCharset[domain];
+
     // conversion to apply to msgid strings before looking them up: we only
     // need it if the msgids are neither in 7 bit ASCII nor in the same
     // encoding as the catalog
@@ -1198,38 +1143,38 @@ wxMsgCatalog::~wxMsgCatalog()
 }
 #endif // !wxUSE_UNICODE
 
-bool wxMsgCatalog::LoadFile(const wxString& filename,
-                            const wxString& domain,
-                            const wxString& msgIdCharset)
+/* static */
+wxMsgCatalog *wxMsgCatalog::CreateFromFile(const wxString& filename,
+                                           const wxString& domain)
 {
-    wxMsgCatalogFile file;
+    wxScopedPtr<wxMsgCatalog> cat(new wxMsgCatalog(domain));
 
-    m_domain = domain;
+    wxMsgCatalogFile file;
 
-    if ( !file.LoadFile(filename, m_pluralFormsCalculator) )
-        return false;
+    if ( !file.LoadFile(filename, cat->m_pluralFormsCalculator) )
+        return NULL;
 
-    if ( !file.FillHash(m_messages, msgIdCharset) )
-        return false;
+    if ( !file.FillHash(cat->m_messages, domain) )
+        return NULL;
 
-    return true;
+    return cat.release();
 }
 
-bool wxMsgCatalog::LoadData(const wxScopedCharTypeBuffer<char>& data,
-                            const wxString& domain,
-                            const wxString& msgIdCharset)
+/* static */
+wxMsgCatalog *wxMsgCatalog::CreateFromData(const wxScopedCharBuffer& data,
+                                           const wxString& domain)
 {
-    wxMsgCatalogFile file;
+    wxScopedPtr<wxMsgCatalog> cat(new wxMsgCatalog(domain));
 
-    m_domain = domain;
+    wxMsgCatalogFile file;
 
-    if ( !file.LoadData(data, m_pluralFormsCalculator) )
-        return false;
+    if ( !file.LoadData(data, cat->m_pluralFormsCalculator) )
+        return NULL;
 
-    if ( !file.FillHash(m_messages, msgIdCharset) )
-        return false;
+    if ( !file.FillHash(cat->m_messages, domain) )
+        return NULL;
 
-    return true;
+    return cat.release();
 }
 
 const wxString *wxMsgCatalog::GetString(const wxString& str, unsigned n) const
@@ -1239,7 +1184,7 @@ const wxString *wxMsgCatalog::GetString(const wxString& str, unsigned n) const
     {
         index = m_pluralFormsCalculator->evaluate(n);
     }
-    wxMessagesHash::const_iterator i;
+    wxStringToStringHashMap::const_iterator i;
     if (index != 0)
     {
         i = m_messages.find(wxString(str) + wxChar(index));   // plural
@@ -1368,7 +1313,7 @@ bool wxTranslations::AddCatalog(const wxString& domain,
                                 wxLanguage msgIdLanguage,
                                 const wxString& msgIdCharset)
 {
-    m_msgIdCharset[domain] = msgIdCharset;
+    gs_msgIdCharset[domain] = msgIdCharset;
     return AddCatalog(domain, msgIdLanguage);
 }
 #endif // !wxUSE_UNICODE
@@ -1405,6 +1350,8 @@ bool wxTranslations::LoadCatalog(const wxString& domain, const wxString& lang)
 {
     wxCHECK_MSG( m_loader, false, "loader can't be NULL" );
 
+    wxMsgCatalog *cat = NULL;
+
 #if wxUSE_FONTMAP
     // first look for the catalog for this language and the current locale:
     // notice that we don't use the system name for the locale as this would
@@ -1416,92 +1363,49 @@ bool wxTranslations::LoadCatalog(const wxString& domain, const wxString& lang)
         wxString fullname(lang);
         fullname << wxS('.') << wxFontMapperBase::GetEncodingName(encSys);
 
-        if ( m_loader->LoadCatalog(this, domain, fullname) )
-            return true;
+        cat = m_loader->LoadCatalog(domain, fullname);
     }
 #endif // wxUSE_FONTMAP
 
-    // Next try: use the provided name language name:
-    if ( m_loader->LoadCatalog(this, domain, lang) )
-        return true;
-
-    // Also try 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
-    if ( lang.length() > LEN_LANG && lang[LEN_LANG] == wxS('_') )
+    if ( !cat )
     {
-        if ( m_loader->LoadCatalog(this, domain, ExtractLang(lang)) )
-            return true;
+        // Next try: use the provided name language name:
+        cat = m_loader->LoadCatalog(domain, lang);
     }
 
-    // Nothing worked, the catalog just isn't there
-    wxLogTrace(TRACE_I18N,
-               "Catalog \"%s.mo\" not found for language \"%s\".",
-               domain, lang);
-    return false;
-}
-
-
-// check if the given catalog is loaded
-bool wxTranslations::IsLoaded(const wxString& domain) const
-{
-    return FindCatalog(domain) != NULL;
-}
-
-
-bool wxTranslations::LoadCatalogFile(const wxString& filename,
-                                     const wxString& domain)
-{
-    wxMsgCatalog *pMsgCat = new wxMsgCatalog;
-
-#if wxUSE_UNICODE
-    const bool ok = pMsgCat->LoadFile(filename, domain, wxEmptyString/*unused*/);
-#else
-    const bool ok = pMsgCat->LoadFile(filename, domain,
-                                      m_msgIdCharset[domain]);
-#endif
-
-    if ( !ok )
+    if ( !cat )
     {
-        // don't add it because it couldn't be loaded anyway
-        delete pMsgCat;
-        return false;
+        // Also try 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
+        wxString baselang = lang.BeforeFirst('_');
+        if ( lang != baselang )
+            cat = m_loader->LoadCatalog(domain, baselang);
     }
 
-    // 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;
-}
-
-
-bool wxTranslations::LoadCatalogData(const wxScopedCharTypeBuffer<char>& data,
-                                     const wxString& domain)
-{
-    wxMsgCatalog *pMsgCat = new wxMsgCatalog;
-
-#if wxUSE_UNICODE
-    const bool ok = pMsgCat->LoadData(data, domain, wxEmptyString/*unused*/);
-#else
-    const bool ok = pMsgCat->LoadData(data, domain,
-                                      m_msgIdCharset[domain]);
-#endif
+    if ( cat )
+    {
+        // add it to the head of the list so that in GetString it will
+        // be searched before the catalogs added earlier
+        cat->m_pNext = m_pMsgCat;
+        m_pMsgCat = cat;
 
-    if ( !ok )
+        return true;
+    }
+    else
     {
-        // don't add it because it couldn't be loaded anyway
-        delete pMsgCat;
+        // Nothing worked, the catalog just isn't there
+        wxLogTrace(TRACE_I18N,
+                   "Catalog \"%s.mo\" not found for language \"%s\".",
+                   domain, lang);
         return false;
     }
+}
 
-    // 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;
+// check if the given catalog is loaded
+bool wxTranslations::IsLoaded(const wxString& domain) const
+{
+    return FindCatalog(domain) != NULL;
 }
 
 
@@ -1581,7 +1485,7 @@ const wxString& wxTranslations::GetString(const wxString& origString,
             TRACE_I18N,
             "string \"%s\"%s not found in %slocale '%s'.",
             origString,
-            ((long)n) != -1 ? wxString::Format("[%ld]", (long)n) : wxString(),
+            n != UINT_MAX ? wxString::Format("[%ld]", (long)n) : wxString(),
             !domain.empty() ? wxString::Format("domain '%s' ", domain) : wxString(),
             m_lang
         );
@@ -1768,13 +1672,9 @@ void wxFileTranslationsLoader::AddCatalogLookupPathPrefix(const wxString& prefix
 }
 
 
-bool wxFileTranslationsLoader::LoadCatalog(wxTranslations *translations,
-                                           const wxString& domain,
-                                           const wxString& lang)
+wxMsgCatalog *wxFileTranslationsLoader::LoadCatalog(const wxString& domain,
+                                                    const wxString& lang)
 {
-    wxCHECK_MSG( lang.length() >= LEN_LANG, false,
-                 "invalid language specification" );
-
     wxString searchPath = GetFullSearchPath(lang);
 
     wxLogTrace(TRACE_I18N, wxS("Looking for \"%s.mo\" in search path \"%s\""),
@@ -1785,13 +1685,13 @@ bool wxFileTranslationsLoader::LoadCatalog(wxTranslations *translations,
 
     wxString strFullName;
     if ( !wxFindFileInPath(&strFullName, searchPath, fn.GetFullPath()) )
-        return false;
+        return NULL;
 
     // open file and read its data
     wxLogVerbose(_("using catalog '%s' from '%s'."), domain, strFullName.c_str());
     wxLogTrace(TRACE_I18N, wxS("Using catalog \"%s\"."), strFullName.c_str());
 
-    return translations->LoadCatalogFile(strFullName, domain);
+    return wxMsgCatalog::CreateFromFile(strFullName, domain);
 }
 
 
@@ -1800,9 +1700,8 @@ bool wxFileTranslationsLoader::LoadCatalog(wxTranslations *translations,
 // ----------------------------------------------------------------------------
 
 #ifdef __WINDOWS__
-bool wxResourceTranslationsLoader::LoadCatalog(wxTranslations *translations,
-                                               const wxString& domain,
-                                               const wxString& lang)
+wxMsgCatalog *wxResourceTranslationsLoader::LoadCatalog(const wxString& domain,
+                                                        const wxString& lang)
 {
 
     const void *mo_data = NULL;
@@ -1819,12 +1718,14 @@ bool wxResourceTranslationsLoader::LoadCatalog(wxTranslations *translations,
     wxLogTrace(TRACE_I18N,
                "Using catalog from Windows resource \"%s\".", resname);
 
-    const bool ok = translations->LoadCatalogData(
-        wxCharBuffer::CreateNonOwned(static_cast<const char*>(mo_data), mo_size));
-    if ( !ok )
+    wxMsgCatalog *cat = wxMsgCatalog::CreateFromData(
+        wxCharBuffer::CreateNonOwned(static_cast<const char*>(mo_data), mo_size),
+        domain);
+
+    if ( !cat )
         wxLogWarning(_("Resource '%s' is not a valid message catalog."), resname);
 
-    return ok;
+    return cat;
 }
 #endif // __WINDOWS__