Merge branch 'i18n-context'

Closes https://github.com/wxWidgets/wxWidgets/pull/530
This commit is contained in:
Vadim Zeitlin 2017-08-09 20:47:41 +02:00
commit 7e80ff4ed8
7 changed files with 150 additions and 27 deletions

View File

@ -76,6 +76,7 @@ All:
- Add wxSecretStore for storing passwords using the OS-provided facilities.
- Add support for compiling application code with wxNO_UNSAFE_WXSTRING_CONV.
- Add support for translating strings in different contexts (RickS).
- Add support for the micro version (third component) to OS and toolkit version
functions. See wxGetOsVersion(), wxPlatformInfo, and wxAppTraits.
- wxLogInfo() now logs messages if the log level is high enough, even without

View File

@ -39,6 +39,15 @@
#define wxPLURAL(sing, plur, n) wxGetTranslation((sing), (plur), n)
#endif
// wx-specific macro for translating strings in the given context: if you use
// them, you need to also add
// --keyword="wxGETTEXT_IN_CONTEXT:1c,2" --keyword="wxGETTEXT_IN_CONTEXT_PLURAL:1c,2,3"
// options to xgettext invocation.
#define wxGETTEXT_IN_CONTEXT(c, s) \
wxGetTranslation((s), wxString(), c)
#define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n) \
wxGetTranslation((sing), (plur), n, wxString(), c)
// another one which just marks the strings for extraction, but doesn't
// perform the translation (use -kwxTRANSLATE with xgettext!)
#define wxTRANSLATE(str) str
@ -79,7 +88,7 @@ public:
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;
const wxString *GetString(const wxString& sz, unsigned n = UINT_MAX, const wxString& ct = wxEmptyString) const;
protected:
wxMsgCatalog(const wxString& domain)
@ -154,10 +163,12 @@ public:
// access to translations
const wxString *GetTranslatedString(const wxString& origString,
const wxString& domain = wxEmptyString) const;
const wxString& domain = wxEmptyString,
const wxString& context = wxEmptyString) const;
const wxString *GetTranslatedString(const wxString& origString,
unsigned n,
const wxString& domain = wxEmptyString) const;
const wxString& domain = wxEmptyString,
const wxString& context = wxEmptyString) const;
wxString GetHeaderValue(const wxString& header,
const wxString& domain = wxEmptyString) const;
@ -247,10 +258,11 @@ protected:
// get the translation of the string in the current locale
inline const wxString& wxGetTranslation(const wxString& str,
const wxString& domain = wxString())
const wxString& domain = wxString(),
const wxString& context = wxString())
{
wxTranslations *trans = wxTranslations::Get();
const wxString *transStr = trans ? trans->GetTranslatedString(str, domain)
const wxString *transStr = trans ? trans->GetTranslatedString(str, domain, context)
: NULL;
if ( transStr )
return *transStr;
@ -263,10 +275,11 @@ inline const wxString& wxGetTranslation(const wxString& str,
inline const wxString& wxGetTranslation(const wxString& str1,
const wxString& str2,
unsigned n,
const wxString& domain = wxString())
const wxString& domain = wxString(),
const wxString& context = wxString())
{
wxTranslations *trans = wxTranslations::Get();
const wxString *transStr = trans ? trans->GetTranslatedString(str1, n, domain)
const wxString *transStr = trans ? trans->GetTranslatedString(str1, n, domain, context)
: NULL;
if ( transStr )
return *transStr;
@ -287,6 +300,8 @@ inline const wxString& wxGetTranslation(const wxString& str1,
#define _(s) (s)
#endif
#define wxPLURAL(sing, plur, n) ((n) == 1 ? (sing) : (plur))
#define wxGETTEXT_IN_CONTEXT(c, s) (s)
#define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n) wxPLURAL(sing, plur, n)
#endif
#define wxTRANSLATE(str) str
@ -304,6 +319,10 @@ template<typename TString, typename TDomain>
inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain))
{ return str; }
template<typename TString, typename TDomain, typename TContext>
inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain), TContext WXUNUSED(context))
{ return str; }
template<typename TString, typename TDomain>
inline TString wxGetTranslation(TString str1, TString str2, size_t n)
{ return n == 1 ? str1 : str2; }
@ -313,6 +332,12 @@ inline TString wxGetTranslation(TString str1, TString str2, size_t n,
TDomain WXUNUSED(domain))
{ return n == 1 ? str1 : str2; }
template<typename TString, typename TDomain, typename TContext>
inline TString wxGetTranslation(TString str1, TString str2, size_t n,
TDomain WXUNUSED(domain),
TContext WXUNUSED(context))
{ return n == 1 ? str1 : str2; }
#endif // wxUSE_INTL/!wxUSE_INTL
// define this one just in case it occurs somewhere (instead of preferred

View File

@ -454,6 +454,28 @@ public:
*/
#define wxPLURAL(string, plural, n)
/**
Similar to _() but translates the string in the given context.
See the description of @c context argument of wxGetTranslation().
@see wxGETTEXT_IN_CONTEXT_PLURAL()
@since 3.1.1
*/
#define wxGETTEXT_IN_CONTEXT(context, string)
/**
Similar to wxPLURAL() but translates the string in the given context.
See the description of @c context argument of wxGetTranslation().
@see wxGETTEXT_IN_CONTEXT()
@since 3.1.1
*/
#define wxGETTEXT_IN_CONTEXT_PLURAL(context, string, plural, n)
/**
This macro doesn't do anything in the program code -- it simply expands to
the value of its argument.
@ -515,6 +537,16 @@ public:
also common in Unix world) syntax is provided: the _() macro is defined to
do the same thing as wxGetTranslation().
If @a context is not empty (notice that this argument is only available
starting from wxWidgets 3.1.1), item translation is looked up in the
specified context. This allows to have different translations for the same
string appearing in different contexts, e.g. it may be necessary to
translate the same English "Open" verb differently depending on the object
it applies to. To do this, you need to use @c msgctxt in the source message
catalog and specify different contexts for the different occurrences of the
string and then use the same contexts in the calls to this function (or
wxGETTEXT_IN_CONTEXT() or wxGETTEXT_IN_CONTEXT_PLURAL() macros).
This function is thread-safe.
@note This function is not suitable for literal strings using wxT() macro
@ -527,7 +559,8 @@ public:
@header{wx/intl.h}
*/
const wxString& wxGetTranslation(const wxString& string,
const wxString& domain = wxEmptyString);
const wxString& domain = wxEmptyString,
const wxString& context = wxEmptyString);
/**
This is an overloaded version of
@ -553,7 +586,8 @@ const wxString& wxGetTranslation(const wxString& string,
*/
const wxString& wxGetTranslation(const wxString& string,
const wxString& plural, unsigned n,
const wxString& domain = wxEmptyString);
const wxString& domain = wxEmptyString,
const wxString& context = wxEmptyString);
/**
Macro to be used around all literal strings that should be translated.

Binary file not shown.

View File

@ -2,17 +2,47 @@
# Copyright (C) 1999 wxWindows development team
# Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
#
#: internat.cpp:146
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: wxWindows 2.0 i18n sample\n"
"POT-Creation-Date: 1999-01-13 18:19+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2016-09-20 19:38+0200\n"
"Last-Translator: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language-Team: \n"
"Language: fr\n"
"X-Generator: Poedit 1.8.7\n"
msgid "item"
msgstr "Item without context"
msgctxt "context_1"
msgid "item"
msgstr "Item in context 1"
msgctxt "context_2"
msgid "item"
msgstr "Item in context 2"
msgid "sing"
msgid_plural "plur"
msgstr[0] "Singular form without context"
msgstr[1] "Plural form without context"
msgctxt "context_1"
msgid "sing"
msgid_plural "plur"
msgstr[0] "Singular form in context 1"
msgstr[1] "Plural form in context 1"
msgctxt "context_2"
msgid "sing"
msgid_plural "plur"
msgstr[0] "Singular form in context 2"
msgstr[1] "Plural form in context 2"
#: internat.cpp:98
msgid "International wxWindows App"
@ -43,9 +73,11 @@ msgid "&Test"
msgstr "&Test"
#: internat.cpp:138
msgid "I18n sample\n"
msgid ""
"I18n sample\n"
"© 1998, 1999 Vadim Zeitlin and Julian Smart"
msgstr "Exemple d'i18n\n"
msgstr ""
"Exemple d'i18n\n"
"© 1998, 1999 Vadim Zeitlin et Julian Smart"
#: internat.cpp:139

View File

@ -94,7 +94,16 @@ enum
INTERNAT_TEST_1,
INTERNAT_TEST_2,
INTERNAT_TEST_3,
INTERNAT_TEST_MSGBOX
INTERNAT_TEST_MSGBOX,
INTERNAT_MACRO_1,
INTERNAT_MACRO_2,
INTERNAT_MACRO_3,
INTERNAT_MACRO_4,
INTERNAT_MACRO_5,
INTERNAT_MACRO_6,
INTERNAT_MACRO_7,
INTERNAT_MACRO_8,
INTERNAT_MACRO_9
};
// language data
@ -308,9 +317,23 @@ MyFrame::MyFrame(wxLocale& locale)
test_menu->Append(INTERNAT_TEST_MSGBOX, _("&Message box test"),
_("Tests message box buttons labels translation"));
// Note that all these strings are currently "translated" only in French
// catalog, so you need to use French locale to see them in action.
wxMenu *macro_menu = new wxMenu;
macro_menu->Append(INTERNAT_MACRO_1, _("item"));
macro_menu->Append(INTERNAT_MACRO_2, wxGETTEXT_IN_CONTEXT("context_1", "item"));
macro_menu->Append(INTERNAT_MACRO_3, wxGETTEXT_IN_CONTEXT("context_2", "item"));
macro_menu->Append(INTERNAT_MACRO_4, wxPLURAL("sing", "plur", 1));
macro_menu->Append(INTERNAT_MACRO_5, wxPLURAL("sing", "plur", 2));
macro_menu->Append(INTERNAT_MACRO_6, wxGETTEXT_IN_CONTEXT_PLURAL("context_1", "sing", "plur", 1));
macro_menu->Append(INTERNAT_MACRO_7, wxGETTEXT_IN_CONTEXT_PLURAL("context_1", "sing", "plur", 2));
macro_menu->Append(INTERNAT_MACRO_8, wxGETTEXT_IN_CONTEXT_PLURAL("context_2", "sing", "plur", 1));
macro_menu->Append(INTERNAT_MACRO_9, wxGETTEXT_IN_CONTEXT_PLURAL("context_2", "sing", "plur", 2));
wxMenuBar *menu_bar = new wxMenuBar;
menu_bar->Append(file_menu, _("&File"));
menu_bar->Append(test_menu, _("&Test"));
menu_bar->Append(macro_menu, _("&Macro"));
SetMenuBar(menu_bar);
// this demonstrates RTL support in wxStatusBar:

View File

@ -1352,7 +1352,7 @@ wxMsgCatalog *wxMsgCatalog::CreateFromData(const wxScopedCharBuffer& data,
return cat.release();
}
const wxString *wxMsgCatalog::GetString(const wxString& str, unsigned n) const
const wxString *wxMsgCatalog::GetString(const wxString& str, unsigned n, const wxString& context) const
{
int index = 0;
if (n != UINT_MAX)
@ -1362,11 +1362,17 @@ const wxString *wxMsgCatalog::GetString(const wxString& str, unsigned n) const
wxStringToStringHashMap::const_iterator i;
if (index != 0)
{
i = m_messages.find(wxString(str) + wxChar(index)); // plural
if (context.IsEmpty())
i = m_messages.find(wxString(str) + wxChar(index)); // plural, no context
else
i = m_messages.find(wxString(context) + wxString('\x04') + wxString(str) + wxChar(index)); // plural, context
}
else
{
i = m_messages.find(str);
if (context.IsEmpty())
i = m_messages.find(str); // no context
else
i = m_messages.find(wxString(context) + wxString('\x04') + wxString(str)); // context
}
if ( i != m_messages.end() )
@ -1631,14 +1637,16 @@ const wxString& wxTranslations::GetUntranslatedString(const wxString& str)
const wxString *wxTranslations::GetTranslatedString(const wxString& origString,
const wxString& domain) const
const wxString& domain,
const wxString& context) const
{
return GetTranslatedString(origString, UINT_MAX, domain);
return GetTranslatedString(origString, UINT_MAX, domain, context);
}
const wxString *wxTranslations::GetTranslatedString(const wxString& origString,
unsigned n,
const wxString& domain) const
const wxString& domain,
const wxString& context) const
{
if ( origString.empty() )
return NULL;
@ -1652,14 +1660,14 @@ const wxString *wxTranslations::GetTranslatedString(const wxString& origString,
// does the catalog exist?
if ( pMsgCat != NULL )
trans = pMsgCat->GetString(origString, n);
trans = pMsgCat->GetString(origString, n, context);
}
else
{
// search in all domains
for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext )
{
trans = pMsgCat->GetString(origString, n);
trans = pMsgCat->GetString(origString, n, context);
if ( trans != NULL ) // take the first found
break;
}
@ -1670,10 +1678,11 @@ const wxString *wxTranslations::GetTranslatedString(const wxString& origString,
wxLogTrace
(
TRACE_I18N,
"string \"%s\"%s not found in %slocale '%s'.",
"string \"%s\"%s not found in %s%slocale '%s'.",
origString,
(n != UINT_MAX ? wxString::Format("[%ld]", (long)n) : wxString()),
(!domain.empty() ? wxString::Format("domain '%s' ", domain) : wxString()),
(!context.empty() ? wxString::Format("context '%s' ", context) : wxString()),
m_lang
);
}
@ -1681,7 +1690,6 @@ const wxString *wxTranslations::GetTranslatedString(const wxString& origString,
return trans;
}
wxString wxTranslations::GetHeaderValue(const wxString& header,
const wxString& domain) const
{