Audacity  3.0.3
TranslatableString.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  @file TranslatableString.h
6 
7  Paul Licameli split from Types.h
8 
9  **********************************************************************/
10 
11 #ifndef __AUDACITY_TRANSLATABLE_STRING__
12 #define __AUDACITY_TRANSLATABLE_STRING__
13 
14 #include <stddef.h> // for size_t
15 #include <functional>
16 #include <wx/string.h>
17 
18 class Identifier;
19 
20 #include <vector>
21 
23 
32 class STRINGS_API TranslatableString {
33  enum class Request;
34  template< size_t N > struct PluralTemp;
35 
36 public:
39 
41 
45  using Formatter = std::function< wxString(const wxString &, Request) >;
46 
48 
51  explicit TranslatableString( wxString str, Formatter formatter )
52  : mFormatter{ std::move(formatter) }
53  {
54  mMsgid.swap( str );
55  }
56 
57  // copy and move
58  TranslatableString( const TranslatableString & ) = default;
61  : mFormatter( std::move( str.mFormatter ) )
62  {
63  mMsgid.swap( str.mMsgid );
64  }
66  {
67  mFormatter = std::move( str.mFormatter );
68  mMsgid.swap( str.mMsgid );
69  return *this;
70  }
71 
72  bool empty() const { return mMsgid.empty(); }
73 
75 
77  Identifier MSGID() const;
78 
79  wxString Translation() const { return DoFormat( false ); }
80 
82  wxString Debug() const { return DoFormat( true ); }
83 
85 
86  friend bool operator == (
87  const TranslatableString &x, const TranslatableString &y)
88  { return x.mMsgid == y.mMsgid; }
89 
90  friend bool operator != (
91  const TranslatableString &x, const TranslatableString &y)
92  { return !(x == y); }
93 
95  bool IsVerbatim() const;
96 
98 
102  template< typename... Args >
103  TranslatableString &Format( Args &&...args ) &
104  {
105  auto prevFormatter = mFormatter;
106  this->mFormatter = [prevFormatter, args...]
107  (const wxString &str, Request request) -> wxString {
108  switch ( request ) {
109  case Request::Context:
110  return TranslatableString::DoGetContext( prevFormatter );
111  case Request::Format:
112  case Request::DebugFormat:
113  default: {
114  bool debug = request == Request::DebugFormat;
115  return wxString::Format(
117  prevFormatter,
118  str, TranslatableString::DoGetContext( prevFormatter ),
119  debug ),
120  TranslatableString::TranslateArgument( args, debug )...
121  );
122  }
123  }
124  };
125  return *this;
126  }
127  template< typename... Args >
128  TranslatableString &&Format( Args &&...args ) &&
129  {
130  return std::move( Format( std::forward<Args>(args)... ) );
131  }
132 
134 
137  TranslatableString &Context( const wxString &context ) &
138  {
139  this->mFormatter = [context]
140  (const wxString &str, Request request) -> wxString {
141  switch ( request ) {
142  case Request::Context:
143  return context;
144  case Request::DebugFormat:
145  return DoSubstitute( {}, str, context, true );
146  case Request::Format:
147  default:
148  return DoSubstitute( {}, str, context, false );
149  }
150  };
151  return *this;
152  }
153  TranslatableString &&Context( const wxString &context ) &&
154  {
155  return std::move( Context( context ) );
156  }
157 
159 
162  TranslatableString &Join(
163  TranslatableString arg, const wxString &separator = {} ) &;
165  TranslatableString arg, const wxString &separator = {} ) &&
166  { return std::move( Join( std::move(arg), separator ) ); }
167 
169  {
170  Join( std::move( arg ) );
171  return *this;
172  }
173 
175 
179  template< size_t N >
180  PluralTemp< N > Plural( const wxString &pluralStr ) &&
181  {
182  return PluralTemp< N >{ *this, pluralStr };
183  }
184 
188  enum StripOptions : unsigned {
189  // Values to be combined with bitwise OR
190  MenuCodes = 0x1,
191  Ellipses = 0x2,
192  };
193  TranslatableString &Strip( unsigned options = MenuCodes ) &;
194  TranslatableString &&Strip( unsigned options = MenuCodes ) &&
195  { return std::move( Strip( options ) ); }
196 
198  TranslatableString Stripped( unsigned options = MenuCodes ) const
199  { return TranslatableString{ *this }.Strip( options ); }
200 
201  wxString StrippedTranslation() const { return Stripped().Translation(); }
202 
203 private:
205 
207  explicit TranslatableString( wxString str )
208  : mFormatter{ NullContextFormatter }
209  {
210  mMsgid.swap( str );
211  }
212 
213  friend TranslatableString Verbatim( wxString str );
214 
215  enum class Request {
216  Context,
217  Format,
218  DebugFormat,
219  };
220 
221  static const wxChar *const NullContextName;
223 
224  static wxString DoGetContext( const Formatter &formatter );
225  static wxString DoSubstitute(
226  const Formatter &formatter,
227  const wxString &format, const wxString &context, bool debug );
228  wxString DoFormat( bool debug ) const
229  { return DoSubstitute(
230  mFormatter, mMsgid, DoGetContext(mFormatter), debug ); }
231 
232  static wxString DoChooseFormat(
233  const Formatter &formatter,
234  const wxString &singular, const wxString &plural, unsigned nn, bool debug );
235 
236  template< typename T > static const T &TranslateArgument( const T &arg, bool )
237  { return arg; }
239 
240  template< typename T > static auto TranslateArgument(
241  const std::reference_wrapper<T> &arg, bool debug )
242  -> decltype(
243  TranslatableString::TranslateArgument( arg.get(), debug ) )
244  { return TranslatableString::TranslateArgument( arg.get(), debug ); }
245  static wxString TranslateArgument( const TranslatableString &arg, bool debug )
246  { return arg.DoFormat( debug ); }
247 
248  template< size_t N > struct PluralTemp{
250  const wxString &pluralStr;
251  template< typename... Args >
252  TranslatableString &&operator()( Args&&... args )
253  {
254  // Pick from the pack the argument that specifies number
255  auto selector =
256  std::template get< N >( std::forward_as_tuple( args... ) );
257  // We need an unsigned value. Guard against negative values.
258  auto nn = static_cast<unsigned>(
259  std::max<unsigned long long>( 0, selector )
260  );
261  auto plural = this->pluralStr;
262  auto prevFormatter = this->ts.mFormatter;
263  this->ts.mFormatter = [prevFormatter, plural, nn, args...]
264  (const wxString &str, Request request) -> wxString {
265  switch ( request ) {
266  case Request::Context:
267  return TranslatableString::DoGetContext( prevFormatter );
268  case Request::Format:
269  case Request::DebugFormat:
270  default:
271  {
272  bool debug = request == Request::DebugFormat;
273  return wxString::Format(
275  prevFormatter, str, plural, nn, debug ),
276  TranslatableString::TranslateArgument( args, debug )...
277  );
278  }
279  }
280  };
281  return std::move(ts);
282  }
283  };
284 
285  wxString mMsgid;
287 };
288 
291 {
292  return std::move(x += std::move(y));
293 }
294 
295 using TranslatableStrings = std::vector<TranslatableString>;
296 
298 
299 namespace std
300 {
301  template<> struct hash< TranslatableString > {
302  size_t operator () (const TranslatableString &str) const // noexcept
303  {
304  const wxString &stdstr = str.mMsgid.ToStdWstring(); // no allocations, a cheap fetch
305  using Hasher = hash< wxString >;
306  return Hasher{}( stdstr );
307  }
308  };
309 }
310 
312 template< typename Sink >
313 inline Sink &operator <<( Sink &sink, const TranslatableString &str )
314 {
315  return sink << str.Translation();
316 }
317 
319 
321 inline TranslatableString Verbatim( wxString str )
322 { return TranslatableString( std::move( str ) ); }
323 
324 #endif
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
TranslatableString::PluralTemp::operator()
TranslatableString && operator()(Args &&... args)
Definition: TranslatableString.h:252
TranslatableString::Join
TranslatableString && Join(TranslatableString arg, const wxString &separator={}) &&
Definition: TranslatableString.h:164
TranslatableString::empty
bool empty() const
Definition: TranslatableString.h:72
TranslatableString::DoGetContext
static wxString DoGetContext(const Formatter &formatter)
Definition: TranslatableString.cpp:89
TranslatableString::Context
TranslatableString & Context(const wxString &context) &
Choose a non-default and non-null disambiguating context for lookups.
Definition: TranslatableString.h:137
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
TranslatableString::Format
TranslatableString && Format(Args &&...args) &&
Definition: TranslatableString.h:128
TranslatableString::PluralTemp::ts
TranslatableString & ts
Definition: TranslatableString.h:249
Format
Abstract base class used in importing a file.
TranslatableString::Inaudible
static const TranslatableString Inaudible
A special string value that will have no screen reader pronunciation.
Definition: TranslatableString.h:34
TranslatableString::PluralTemp::pluralStr
const wxString & pluralStr
Definition: TranslatableString.h:250
operator<<
Sink & operator<<(Sink &sink, const TranslatableString &str)
Allow TranslatableString to work with shift output operators.
Definition: TranslatableString.h:313
TranslatableString::Debug
wxString Debug() const
Format as an English string for debugging logs and developers' eyes, not for end users.
Definition: TranslatableString.h:82
TranslatableString::NullContextFormatter
static const Formatter NullContextFormatter
Definition: TranslatableString.h:204
TranslatableString::StripOptions
StripOptions
Definition: TranslatableString.h:188
std::hash< TranslatableString >
Definition: TranslatableString.h:301
TranslatableString::DoChooseFormat
static wxString DoChooseFormat(const Formatter &formatter, const wxString &singular, const wxString &plural, unsigned nn, bool debug)
Definition: TranslatableString.cpp:103
operator==
bool operator==(const Tags &lhs, const Tags &rhs)
Definition: Tags.cpp:360
TranslatableString::Strip
TranslatableString && Strip(unsigned options=MenuCodes) &&
Definition: TranslatableString.h:194
Identifier
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
TranslatableString::Strip
TranslatableString & Strip(unsigned options=MenuCodes) &
Definition: TranslatableString.cpp:41
TranslatableString::DoFormat
wxString DoFormat(bool debug) const
Definition: TranslatableString.h:228
TranslatableString::TranslatableString
TranslatableString(const TranslatableString &)=default
TranslatableString::mFormatter
Formatter mFormatter
Definition: TranslatableString.h:286
TranslatableString::DoSubstitute
static wxString DoSubstitute(const Formatter &formatter, const wxString &format, const wxString &context, bool debug)
Definition: TranslatableString.cpp:94
TranslatableString::TranslateArgument
static const T & TranslateArgument(const T &arg, bool)
Definition: TranslatableString.h:236
TranslatableString::TranslatableString
TranslatableString(TranslatableString &&str)
Definition: TranslatableString.h:60
format
int format
Definition: ExportPCM.cpp:54
operator+
TranslatableString operator+(TranslatableString x, TranslatableString y)
Definition: TranslatableString.h:289
TranslatableString::operator=
TranslatableString & operator=(TranslatableString &&str)
Definition: TranslatableString.h:65
TranslatableString::TranslateArgument
static auto TranslateArgument(const std::reference_wrapper< T > &arg, bool debug) -> decltype(TranslatableString::TranslateArgument(arg.get(), debug))
This allows you to wrap arguments of Format in std::cref.
Definition: TranslatableString.h:240
TranslatableString::TranslatableString
TranslatableString()
Definition: TranslatableString.h:47
TranslatableString::Plural
PluralTemp< N > Plural(const wxString &pluralStr) &&
Implements the XP macro.
Definition: TranslatableString.h:180
TranslatableString::mMsgid
wxString mMsgid
Definition: TranslatableString.h:285
TranslatableString::StrippedTranslation
wxString StrippedTranslation() const
Definition: TranslatableString.h:201
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
operator!=
bool operator!=(const SelectedRegion &lhs, const SelectedRegion &rhs)
Definition: SelectedRegion.h:283
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
TranslatableString::Format
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
Definition: TranslatableString.h:103
TranslatableString::Stripped
TranslatableString Stripped(unsigned options=MenuCodes) const
non-mutating, constructs another TranslatableString object
Definition: TranslatableString.h:198
TranslatableString::operator=
TranslatableString & operator=(const TranslatableString &)=default
TranslatableString::Formatter
std::function< wxString(const wxString &, Request) > Formatter
A multi-purpose function, depending on the enum argument.
Definition: TranslatableString.h:45
TranslatableString::TranslatableString
TranslatableString(wxString str)
Construct a TranslatableString that does no translation but passes str verbatim.
Definition: TranslatableString.h:207
Request
Class to construct the HTTP request.
TranslatableString::Context
TranslatableString && Context(const wxString &context) &&
Definition: TranslatableString.h:153
TranslatableString::NullContextName
static const wxChar *const NullContextName
Definition: TranslatableString.h:221
TranslatableString::TranslateArgument
static wxString TranslateArgument(const TranslatableString &arg, bool debug)
Definition: TranslatableString.h:245
TranslatableString::PluralTemp
Definition: TranslatableString.h:248
TranslatableString::TranslatableString
TranslatableString(wxString str, Formatter formatter)
Definition: TranslatableString.h:51