File: TranslatableString.cpp

package info (click to toggle)
audacity 3.7.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 134,800 kB
  • sloc: cpp: 366,277; ansic: 198,323; lisp: 7,761; sh: 3,414; python: 1,501; xml: 1,385; perl: 854; makefile: 125
file content (152 lines) | stat: -rw-r--r-- 5,043 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**********************************************************************
 
 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") };