audacia/libraries/lib-strings/TranslatableString.cpp

153 lines
4.9 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
@file TranslatableString.cpp
Paul Licameli split from Internat.cpp
**********************************************************************/
#include "TranslatableString.h"
#include "Identifier.h"
#include <wx/translation.h>
const wxChar *const TranslatableString::NullContextName = wxT("*");
Identifier TranslatableString::MSGID() const
{
return Identifier{ mMsgid };
}
const TranslatableString::Formatter
TranslatableString::NullContextFormatter {
[](const wxString & str, TranslatableString::Request request) -> wxString {
switch ( request ) {
case Request::Context:
return NullContextName;
case Request::Format:
case Request::DebugFormat:
default:
return str;
}
}
};
bool TranslatableString::IsVerbatim() const
{
return DoGetContext( mFormatter ) == NullContextName;
}
TranslatableString &TranslatableString::Strip( unsigned codes ) &
{
auto prevFormatter = mFormatter;
mFormatter = [prevFormatter, codes]
( const wxString & str, TranslatableString::Request request ) -> wxString {
switch ( request ) {
case Request::Context:
return TranslatableString::DoGetContext( prevFormatter );
case Request::Format:
case Request::DebugFormat:
default: {
bool debug = request == Request::DebugFormat;
auto result =
TranslatableString::DoSubstitute(
prevFormatter,
str, TranslatableString::DoGetContext( prevFormatter ),
debug );
if ( codes & MenuCodes ) {
// Don't use this, it's in wxCore
// result = wxStripMenuCodes( result );
decltype( result ) temp;
temp.swap(result);
for ( auto iter = temp.begin(), end = temp.end();
iter != end; ++iter ) {
// Stop at trailing hot key name
if ( *iter == '\t' )
break;
// Strip & (unless escaped by another preceding &)
if ( *iter == '&' && ++iter == end )
break;
result.append( 1, *iter );
}
}
if ( codes & Ellipses ) {
if (result.EndsWith(wxT("...")))
result = result.Left( result.length() - 3 );
// Also check for the single-character Unicode ellipsis
else if (result.EndsWith(wxT("\u2026")))
result = result.Left( result.length() - 1 );
}
return result;
}
}
};
return *this;
}
wxString TranslatableString::DoGetContext( const Formatter &formatter )
{
return formatter ? formatter( {}, Request::Context ) : wxString{};
}
wxString TranslatableString::DoSubstitute( const Formatter &formatter,
const wxString &format, const wxString &context, bool debug )
{
return formatter
? formatter( format, debug ? Request::DebugFormat : Request::Format )
: // come here for most translatable strings, which have no formatting
( debug ? format : wxGetTranslation( format, wxString{}, context ) );
}
wxString TranslatableString::DoChooseFormat(
const Formatter &formatter,
const wxString &singular, const wxString &plural, unsigned nn, bool debug )
{
// come here for translatable strings that choose among forms by number;
// if not debugging, then two keys are passed to an overload of
// wxGetTranslation, and also a number.
// Some languages might choose among more or fewer than two forms
// (e.g. Arabic has duals and Russian has complicated declension rules)
wxString context;
return ( debug || NullContextName == (context = DoGetContext(formatter)) )
? ( nn == 1 ? singular : plural )
: wxGetTranslation(
singular, plural, nn
#if HAS_I18N_CONTEXTS
, wxString{} // domain
, context
#endif
);
}
TranslatableString &TranslatableString::Join(
const TranslatableString arg, const wxString &separator ) &
{
auto prevFormatter = mFormatter;
mFormatter =
[prevFormatter,
arg /* = std::move( arg ) */,
separator](const wxString &str, Request request)
-> wxString {
switch ( request ) {
case Request::Context:
return TranslatableString::DoGetContext( prevFormatter );
case Request::Format:
case Request::DebugFormat:
default: {
bool debug = request == Request::DebugFormat;
return
TranslatableString::DoSubstitute( prevFormatter,
str, TranslatableString::DoGetContext( prevFormatter ),
debug )
+ separator
+ arg.DoFormat( debug );
}
}
};
return *this;
}
const TranslatableString TranslatableString::Inaudible{ wxT("\a") };