Refactor wxTranslationsLoader API.

Instead of calling back into wxTranslations to actually load the data,
return wxMsgCatalog instance from
wxTranslationsLoader::LoadCatalog(). This requires making wxMsgCatalog
public.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64223 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2010-05-06 12:12:53 +00:00
parent ba5619e076
commit 611bed3511
3 changed files with 190 additions and 207 deletions

View 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"
@@ -69,6 +68,18 @@ const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495;
// implementation
// ============================================================================
namespace
{
#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
// ----------------------------------------------------------------------------
// Plural forms parser
// ----------------------------------------------------------------------------
@@ -414,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)
@@ -785,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();
@@ -803,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
@@ -869,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
// ----------------------------------------------------------------------------
@@ -1057,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;
@@ -1088,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
@@ -1179,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)
{
wxScopedPtr<wxMsgCatalog> cat(new wxMsgCatalog(domain));
wxMsgCatalogFile file;
m_domain = domain;
if ( !file.LoadFile(filename, cat->m_pluralFormsCalculator) )
return NULL;
if ( !file.LoadFile(filename, m_pluralFormsCalculator) )
return false;
if ( !file.FillHash(cat->m_messages, domain) )
return NULL;
if ( !file.FillHash(m_messages, msgIdCharset) )
return false;
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)
{
wxScopedPtr<wxMsgCatalog> cat(new wxMsgCatalog(domain));
wxMsgCatalogFile file;
m_domain = domain;
if ( !file.LoadData(data, cat->m_pluralFormsCalculator) )
return NULL;
if ( !file.LoadData(data, m_pluralFormsCalculator) )
return false;
if ( !file.FillHash(cat->m_messages, domain) )
return NULL;
if ( !file.FillHash(m_messages, msgIdCharset) )
return false;
return true;
return cat.release();
}
const wxString *wxMsgCatalog::GetString(const wxString& str, unsigned n) const
@@ -1220,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
@@ -1349,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
@@ -1386,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
@@ -1397,32 +1363,44 @@ 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
wxString baselang = lang.BeforeFirst('_');
if ( lang != baselang )
if ( !cat )
{
if ( m_loader->LoadCatalog(this, domain, baselang) )
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;
}
if ( !cat )
{
// 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);
}
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;
return true;
}
else
{
// 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
@@ -1431,62 +1409,6 @@ bool wxTranslations::IsLoaded(const wxString& domain) const
}
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 )
{
// don't add it because it couldn't be loaded anyway
delete pMsgCat;
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;
}
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 ( !ok )
{
// don't add it because it couldn't be loaded anyway
delete pMsgCat;
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;
}
wxString wxTranslations::ChooseLanguageForDomain(const wxString& WXUNUSED(domain),
const wxString& WXUNUSED(msgIdLang))
{
@@ -1750,9 +1672,8 @@ 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)
{
wxString searchPath = GetFullSearchPath(lang);
@@ -1764,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);
}
@@ -1779,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;
@@ -1798,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__