Add wxTranslations::GetAvailableTranslations().
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64597 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -446,6 +446,7 @@ All:
|
|||||||
- Added IEC and SI units support to GetHumanReadableSize() (Julien Weinzorn).
|
- Added IEC and SI units support to GetHumanReadableSize() (Julien Weinzorn).
|
||||||
- Add convenient wxString::ToStd{String,Wstring}() helpers.
|
- Add convenient wxString::ToStd{String,Wstring}() helpers.
|
||||||
- Added wxTranslations class to allow localization without changing locale.
|
- Added wxTranslations class to allow localization without changing locale.
|
||||||
|
It provides more flexible languages enumeration API as well.
|
||||||
- Added wxResourceTranslationsLoader for loading translations from Windows
|
- Added wxResourceTranslationsLoader for loading translations from Windows
|
||||||
resources.
|
resources.
|
||||||
- Added wxMessageQueue::Clear().
|
- Added wxMessageQueue::Clear().
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
// forward decls
|
// forward decls
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_FWD_BASE wxArrayString;
|
||||||
class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader;
|
class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader;
|
||||||
class WXDLLIMPEXP_FWD_BASE wxLocale;
|
class WXDLLIMPEXP_FWD_BASE wxLocale;
|
||||||
|
|
||||||
@@ -128,6 +129,9 @@ public:
|
|||||||
void SetLanguage(wxLanguage lang);
|
void SetLanguage(wxLanguage lang);
|
||||||
void SetLanguage(const wxString& lang);
|
void SetLanguage(const wxString& lang);
|
||||||
|
|
||||||
|
// get languages available for this app
|
||||||
|
wxArrayString GetAvailableTranslations(const wxString& domain) const;
|
||||||
|
|
||||||
// add standard wxWidgets catalog ("wxstd")
|
// add standard wxWidgets catalog ("wxstd")
|
||||||
bool AddStdCatalog();
|
bool AddStdCatalog();
|
||||||
|
|
||||||
@@ -192,6 +196,8 @@ public:
|
|||||||
|
|
||||||
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
||||||
const wxString& lang) = 0;
|
const wxString& lang) = 0;
|
||||||
|
|
||||||
|
virtual wxArrayString GetAvailableTranslations(const wxString& domain) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -204,6 +210,8 @@ public:
|
|||||||
|
|
||||||
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
||||||
const wxString& lang);
|
const wxString& lang);
|
||||||
|
|
||||||
|
virtual wxArrayString GetAvailableTranslations(const wxString& domain) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -216,6 +224,8 @@ public:
|
|||||||
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
||||||
const wxString& lang);
|
const wxString& lang);
|
||||||
|
|
||||||
|
virtual wxArrayString GetAvailableTranslations(const wxString& domain) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// returns resource type to use for translations
|
// returns resource type to use for translations
|
||||||
virtual wxString GetResourceType() const { return "MOFILE"; }
|
virtual wxString GetResourceType() const { return "MOFILE"; }
|
||||||
|
@@ -79,6 +79,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SetLanguage(const wxString& lang);
|
void SetLanguage(const wxString& lang);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns list of all translations of @a domain that were found.
|
||||||
|
|
||||||
|
This method can be used e.g. to populate list of application's
|
||||||
|
translations offered to the user. To do this, pass the app's main
|
||||||
|
catalog as @a domain.
|
||||||
|
*/
|
||||||
|
wxArrayString GetAvailableTranslations(const wxString& domain) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Add standard wxWidgets catalogs ("wxstd" and possible port-specific
|
Add standard wxWidgets catalogs ("wxstd" and possible port-specific
|
||||||
catalogs).
|
catalogs).
|
||||||
@@ -265,6 +274,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
|
||||||
const wxString& lang) = 0;
|
const wxString& lang) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implements wxTranslations::GetAvailableTranslations().
|
||||||
|
*/
|
||||||
|
virtual wxArrayString GetAvailableTranslations(const wxString& domain) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -41,6 +41,8 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "wx/arrstr.h"
|
||||||
|
#include "wx/dir.h"
|
||||||
#include "wx/file.h"
|
#include "wx/file.h"
|
||||||
#include "wx/filename.h"
|
#include "wx/filename.h"
|
||||||
#include "wx/tokenzr.h"
|
#include "wx/tokenzr.h"
|
||||||
@@ -48,6 +50,10 @@
|
|||||||
#include "wx/stdpaths.h"
|
#include "wx/stdpaths.h"
|
||||||
#include "wx/hashset.h"
|
#include "wx/hashset.h"
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
#include "wx/msw/wrapwin.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// simple types
|
// simple types
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -1286,6 +1292,14 @@ void wxTranslations::SetLanguage(const wxString& lang)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxArrayString wxTranslations::GetAvailableTranslations(const wxString& domain) const
|
||||||
|
{
|
||||||
|
wxCHECK_MSG( m_loader, false, "loader can't be NULL" );
|
||||||
|
|
||||||
|
return m_loader->GetAvailableTranslations(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool wxTranslations::AddStdCatalog()
|
bool wxTranslations::AddStdCatalog()
|
||||||
{
|
{
|
||||||
if ( !AddCatalog(wxS("wxstd")) )
|
if ( !AddCatalog(wxS("wxstd")) )
|
||||||
@@ -1348,6 +1362,7 @@ bool wxTranslations::AddCatalog(const wxString& domain,
|
|||||||
|
|
||||||
bool wxTranslations::LoadCatalog(const wxString& domain, const wxString& lang)
|
bool wxTranslations::LoadCatalog(const wxString& domain, const wxString& lang)
|
||||||
{
|
{
|
||||||
|
m_loader->GetAvailableTranslations(domain);
|
||||||
wxCHECK_MSG( m_loader, false, "loader can't be NULL" );
|
wxCHECK_MSG( m_loader, false, "loader can't be NULL" );
|
||||||
|
|
||||||
wxMsgCatalog *cat = NULL;
|
wxMsgCatalog *cat = NULL;
|
||||||
@@ -1599,25 +1614,33 @@ wxString GetMsgCatalogSubdirs(const wxString& prefix, const wxString& lang)
|
|||||||
return searchPath;
|
return searchPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct the search path for the given language
|
bool HasMsgCatalogInDir(const wxString& dir, const wxString& domain)
|
||||||
static wxString GetFullSearchPath(const wxString& lang)
|
|
||||||
{
|
{
|
||||||
// first take the entries explicitly added by the program
|
return wxFileName(dir, domain, "mo").FileExists() ||
|
||||||
wxArrayString paths;
|
wxFileName(dir + wxFILE_SEP_PATH + "LC_MESSAGES", domain, "mo").FileExists();
|
||||||
paths.reserve(gs_searchPrefixes.size() + 1);
|
}
|
||||||
size_t n,
|
|
||||||
count = gs_searchPrefixes.size();
|
|
||||||
for ( n = 0; n < count; n++ )
|
|
||||||
{
|
|
||||||
paths.Add(GetMsgCatalogSubdirs(gs_searchPrefixes[n], lang));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// get prefixes to locale directories; if lang is empty, don't point to
|
||||||
|
// OSX's .lproj bundles
|
||||||
|
wxArrayString GetSearchPrefixes(const wxString& lang = wxString())
|
||||||
|
{
|
||||||
|
wxArrayString paths;
|
||||||
|
|
||||||
|
// first take the entries explicitly added by the program
|
||||||
|
paths = gs_searchPrefixes;
|
||||||
|
|
||||||
#if wxUSE_STDPATHS
|
#if wxUSE_STDPATHS
|
||||||
// then look in the standard location
|
// then look in the standard location
|
||||||
const wxString stdp = wxStandardPaths::Get().
|
wxString stdp;
|
||||||
GetLocalizedResourcesDir(lang, wxStandardPaths::ResourceCat_Messages);
|
if ( lang.empty() )
|
||||||
|
{
|
||||||
|
stdp = wxStandardPaths::Get().GetResourcesDir();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stdp = wxStandardPaths::Get().
|
||||||
|
GetLocalizedResourcesDir(lang, wxStandardPaths::ResourceCat_Messages);
|
||||||
|
}
|
||||||
if ( paths.Index(stdp) == wxNOT_FOUND )
|
if ( paths.Index(stdp) == wxNOT_FOUND )
|
||||||
paths.Add(stdp);
|
paths.Add(stdp);
|
||||||
#endif // wxUSE_STDPATHS
|
#endif // wxUSE_STDPATHS
|
||||||
@@ -1629,7 +1652,7 @@ static wxString GetFullSearchPath(const wxString& lang)
|
|||||||
const char *pszLcPath = wxGetenv("LC_PATH");
|
const char *pszLcPath = wxGetenv("LC_PATH");
|
||||||
if ( pszLcPath )
|
if ( pszLcPath )
|
||||||
{
|
{
|
||||||
const wxString lcp = GetMsgCatalogSubdirs(pszLcPath, lang);
|
const wxString lcp = pszLcPath;
|
||||||
if ( paths.Index(lcp) == wxNOT_FOUND )
|
if ( paths.Index(lcp) == wxNOT_FOUND )
|
||||||
paths.Add(lcp);
|
paths.Add(lcp);
|
||||||
}
|
}
|
||||||
@@ -1638,22 +1661,32 @@ static wxString GetFullSearchPath(const wxString& lang)
|
|||||||
wxString wxp = wxGetInstallPrefix();
|
wxString wxp = wxGetInstallPrefix();
|
||||||
if ( !wxp.empty() )
|
if ( !wxp.empty() )
|
||||||
{
|
{
|
||||||
wxp = GetMsgCatalogSubdirs(wxp + wxS("/share/locale"), lang);
|
wxp += wxS("/share/locale");
|
||||||
if ( paths.Index(wxp) == wxNOT_FOUND )
|
if ( paths.Index(wxp) == wxNOT_FOUND )
|
||||||
paths.Add(wxp);
|
paths.Add(wxp);
|
||||||
}
|
}
|
||||||
#endif // __UNIX__
|
#endif // __UNIX__
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
// finally construct the full search path
|
// construct the search path for the given language
|
||||||
|
wxString GetFullSearchPath(const wxString& lang)
|
||||||
|
{
|
||||||
wxString searchPath;
|
wxString searchPath;
|
||||||
searchPath.reserve(500);
|
searchPath.reserve(500);
|
||||||
count = paths.size();
|
|
||||||
for ( n = 0; n < count; n++ )
|
const wxArrayString prefixes = GetSearchPrefixes(lang);
|
||||||
|
|
||||||
|
for ( wxArrayString::const_iterator i = prefixes.begin();
|
||||||
|
i != prefixes.end();
|
||||||
|
++i )
|
||||||
{
|
{
|
||||||
searchPath += paths[n];
|
const wxString p = GetMsgCatalogSubdirs(*i, lang);
|
||||||
if ( n != count - 1 )
|
|
||||||
|
if ( !searchPath.empty() )
|
||||||
searchPath += wxPATH_SEP;
|
searchPath += wxPATH_SEP;
|
||||||
|
searchPath += p;
|
||||||
}
|
}
|
||||||
|
|
||||||
return searchPath;
|
return searchPath;
|
||||||
@@ -1695,15 +1728,57 @@ wxMsgCatalog *wxFileTranslationsLoader::LoadCatalog(const wxString& domain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxArrayString wxFileTranslationsLoader::GetAvailableTranslations(const wxString& domain) const
|
||||||
|
{
|
||||||
|
wxArrayString langs;
|
||||||
|
const wxArrayString prefixes = GetSearchPrefixes();
|
||||||
|
|
||||||
|
wxLogTrace(TRACE_I18N,
|
||||||
|
"looking for available translations of \"%s\" in search path \"%s\"",
|
||||||
|
domain, wxJoin(prefixes, wxPATH_SEP[0]));
|
||||||
|
|
||||||
|
for ( wxArrayString::const_iterator i = prefixes.begin();
|
||||||
|
i != prefixes.end();
|
||||||
|
++i )
|
||||||
|
{
|
||||||
|
wxDir dir;
|
||||||
|
if ( !dir.Open(*i) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wxString lang;
|
||||||
|
for ( bool ok = dir.GetFirst(&lang, "", wxDIR_DIRS);
|
||||||
|
ok;
|
||||||
|
ok = dir.GetNext(&lang) )
|
||||||
|
{
|
||||||
|
const wxString langdir = *i + wxFILE_SEP_PATH + lang;
|
||||||
|
if ( HasMsgCatalogInDir(langdir, domain) )
|
||||||
|
{
|
||||||
|
#ifdef __WXOSX__
|
||||||
|
wxString rest;
|
||||||
|
if ( lang.EndsWith(".lproj", &rest) )
|
||||||
|
lang = rest;
|
||||||
|
#endif // __WXOSX__
|
||||||
|
|
||||||
|
wxLogTrace(TRACE_I18N,
|
||||||
|
"found %s translation of \"%s\"", lang, domain);
|
||||||
|
langs.push_back(lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return langs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxResourceTranslationsLoader
|
// wxResourceTranslationsLoader
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
|
||||||
wxMsgCatalog *wxResourceTranslationsLoader::LoadCatalog(const wxString& domain,
|
wxMsgCatalog *wxResourceTranslationsLoader::LoadCatalog(const wxString& domain,
|
||||||
const wxString& lang)
|
const wxString& lang)
|
||||||
{
|
{
|
||||||
|
|
||||||
const void *mo_data = NULL;
|
const void *mo_data = NULL;
|
||||||
size_t mo_size = 0;
|
size_t mo_size = 0;
|
||||||
|
|
||||||
@@ -1727,6 +1802,55 @@ wxMsgCatalog *wxResourceTranslationsLoader::LoadCatalog(const wxString& domain,
|
|||||||
|
|
||||||
return cat;
|
return cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct EnumCallbackData
|
||||||
|
{
|
||||||
|
wxString prefix;
|
||||||
|
wxArrayString langs;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL CALLBACK EnumTranslations(HMODULE WXUNUSED(hModule),
|
||||||
|
LPCTSTR WXUNUSED(lpszType),
|
||||||
|
LPTSTR lpszName,
|
||||||
|
LONG_PTR lParam)
|
||||||
|
{
|
||||||
|
wxString name(lpszName);
|
||||||
|
name.MakeLower(); // resource names are case insensitive
|
||||||
|
|
||||||
|
EnumCallbackData *data = reinterpret_cast<EnumCallbackData*>(lParam);
|
||||||
|
|
||||||
|
wxString lang;
|
||||||
|
if ( name.StartsWith(data->prefix, &lang) && !lang.empty() )
|
||||||
|
data->langs.push_back(lang);
|
||||||
|
|
||||||
|
return TRUE; // continue enumeration
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
|
wxArrayString wxResourceTranslationsLoader::GetAvailableTranslations(const wxString& domain) const
|
||||||
|
{
|
||||||
|
EnumCallbackData data;
|
||||||
|
data.prefix = domain + "_";
|
||||||
|
data.prefix.MakeLower(); // resource names are case insensitive
|
||||||
|
|
||||||
|
if ( !EnumResourceNames(GetModule(),
|
||||||
|
GetResourceType(),
|
||||||
|
EnumTranslations,
|
||||||
|
reinterpret_cast<LONG_PTR>(&data)) )
|
||||||
|
{
|
||||||
|
const DWORD err = GetLastError();
|
||||||
|
if ( err != NO_ERROR && err != ERROR_RESOURCE_TYPE_NOT_FOUND )
|
||||||
|
wxLogSysError(_("Couldn't enumerate translations"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.langs;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __WINDOWS__
|
#endif // __WINDOWS__
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user