/src/wxwidgets/include/wx/translation.h
Line | Count | Source |
1 | | ///////////////////////////////////////////////////////////////////////////// |
2 | | // Name: wx/translation.h |
3 | | // Purpose: Internationalization and localisation for wxWidgets |
4 | | // Author: Vadim Zeitlin, Vaclav Slavik, |
5 | | // Michael N. Filippov <michael@idisys.iae.nsk.su> |
6 | | // Created: 2010-04-23 |
7 | | // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> |
8 | | // (c) 2010 Vaclav Slavik <vslavik@fastmail.fm> |
9 | | // Licence: wxWindows licence |
10 | | ///////////////////////////////////////////////////////////////////////////// |
11 | | |
12 | | #ifndef _WX_TRANSLATION_H_ |
13 | | #define _WX_TRANSLATION_H_ |
14 | | |
15 | | #include "wx/defs.h" |
16 | | #include "wx/string.h" |
17 | | |
18 | | #if wxUSE_INTL |
19 | | |
20 | | #include "wx/buffer.h" |
21 | | #include "wx/language.h" |
22 | | #include "wx/strconv.h" |
23 | | |
24 | | // This is a hack, but this header used to include wx/hashmap.h which, in turn, |
25 | | // included wx/wxcrt.h and it turns out quite some existing code relied on it |
26 | | // by using the CRT wrapper functions declared there without explicitly |
27 | | // including that header, so keep including it from here to let it continue to |
28 | | // compile. |
29 | | #include "wx/wxcrt.h" |
30 | | |
31 | | #include <memory> |
32 | | #include <unordered_map> |
33 | | |
34 | | using wxTranslationsHashMap = std::unordered_map<wxString, wxString>; |
35 | | |
36 | | // ============================================================================ |
37 | | // global decls |
38 | | // ============================================================================ |
39 | | |
40 | | // ---------------------------------------------------------------------------- |
41 | | // macros |
42 | | // ---------------------------------------------------------------------------- |
43 | | |
44 | | // gettext() style macros (notice that xgettext should be invoked with |
45 | | // --keyword="_" --keyword="wxPLURAL:1,2" options |
46 | | // to extract the strings from the sources) |
47 | | #ifndef WXINTL_NO_GETTEXT_MACRO |
48 | 0 | #define _(s) wxUnderscoreWrapper((s)) |
49 | | #endif |
50 | | |
51 | 0 | #define wxPLURAL(sing, plur, n) wxPluralWrapper((sing), (plur), n) |
52 | | |
53 | | // wx-specific macro for translating strings in the given context: if you use |
54 | | // them, you need to also add |
55 | | // --keyword="wxGETTEXT_IN_CONTEXT:1c,2" --keyword="wxGETTEXT_IN_CONTEXT_PLURAL:1c,2,3" |
56 | | // options to xgettext invocation. |
57 | | #define wxGETTEXT_IN_CONTEXT(c, s) \ |
58 | | wxGettextInContextWrapper((c), (s)) |
59 | | #define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n) \ |
60 | | wxGettextInContextPluralWrapper((c), (sing), (plur), (n)) |
61 | | |
62 | | // another one which just marks the strings for extraction, but doesn't |
63 | | // perform the translation (use -kwxTRANSLATE with xgettext!) |
64 | 0 | #define wxTRANSLATE(str) str |
65 | | |
66 | | // another one which just marks the strings, with a context, for extraction, |
67 | | // but doesn't perform the translation (use -kwxTRANSLATE_IN_CONTEXT:1c,2 with |
68 | | // xgettext!) |
69 | | #define wxTRANSLATE_IN_CONTEXT(c, str) str |
70 | | |
71 | | // ---------------------------------------------------------------------------- |
72 | | // forward decls |
73 | | // ---------------------------------------------------------------------------- |
74 | | |
75 | | class WXDLLIMPEXP_FWD_BASE wxArrayString; |
76 | | class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader; |
77 | | class WXDLLIMPEXP_FWD_BASE wxLocale; |
78 | | |
79 | | class wxPluralFormsCalculator; |
80 | | using wxPluralFormsCalculatorPtr = std::unique_ptr<wxPluralFormsCalculator>; |
81 | | |
82 | | // ---------------------------------------------------------------------------- |
83 | | // wxMsgCatalog corresponds to one loaded message catalog. |
84 | | // ---------------------------------------------------------------------------- |
85 | | |
86 | | class WXDLLIMPEXP_BASE wxMsgCatalog |
87 | | { |
88 | | public: |
89 | | // Ctor is protected, because CreateFromXXX functions must be used, |
90 | | // but destruction should be unrestricted |
91 | | ~wxMsgCatalog(); |
92 | | |
93 | | // load the catalog from disk or from data; caller is responsible for |
94 | | // deleting them if not null |
95 | | static wxMsgCatalog *CreateFromFile(const wxString& filename, |
96 | | const wxString& domain); |
97 | | |
98 | | static wxMsgCatalog *CreateFromData(const wxScopedCharBuffer& data, |
99 | | const wxString& domain); |
100 | | |
101 | | // get name of the catalog |
102 | 0 | wxString GetDomain() const { return m_domain; } |
103 | | |
104 | | // get the translated string: returns nullptr if not found |
105 | | const wxString *GetString(const wxString& sz, unsigned n = UINT_MAX, const wxString& ct = wxEmptyString) const; |
106 | | |
107 | | protected: |
108 | | wxMsgCatalog(const wxString& domain); |
109 | | |
110 | | private: |
111 | | // variable pointing to the next element in a linked list (or nullptr) |
112 | | wxMsgCatalog *m_pNext; |
113 | | friend class wxTranslations; |
114 | | |
115 | | wxTranslationsHashMap m_messages; // all messages in the catalog |
116 | | wxString m_domain; // name of the domain |
117 | | |
118 | | wxPluralFormsCalculatorPtr m_pluralFormsCalculator; |
119 | | }; |
120 | | |
121 | | // ---------------------------------------------------------------------------- |
122 | | // wxTranslations: message catalogs |
123 | | // ---------------------------------------------------------------------------- |
124 | | |
125 | | // this class allows to get translations for strings |
126 | | class WXDLLIMPEXP_BASE wxTranslations |
127 | | { |
128 | | public: |
129 | | wxTranslations(); |
130 | | ~wxTranslations(); |
131 | | |
132 | | // returns current translations object, may return nullptr |
133 | | static wxTranslations *Get(); |
134 | | // sets current translations object (takes ownership; may be null) |
135 | | static void Set(wxTranslations *t); |
136 | | |
137 | | // changes loader to non-default one; takes ownership of 'loader' |
138 | | void SetLoader(wxTranslationsLoader *loader); |
139 | | |
140 | | void SetLanguage(wxLanguage lang); |
141 | | void SetLanguage(const wxString& lang); |
142 | | |
143 | | // get languages available for this app |
144 | | wxArrayString GetAvailableTranslations(const wxString& domain) const; |
145 | | |
146 | | // find best available translation language for given domain |
147 | | wxString GetBestAvailableTranslation(const wxString& domain); |
148 | | |
149 | | wxString GetBestTranslation(const wxString& domain, wxLanguage msgIdLanguage); |
150 | | wxString GetBestTranslation(const wxString& domain, |
151 | | const wxString& msgIdLanguage = wxASCII_STR("en")); |
152 | | |
153 | | // add catalog for the given domain returning true if it could be found by |
154 | | // wxTranslationsLoader |
155 | | bool AddAvailableCatalog(const wxString& domain, wxLanguage msgIdLanguage = wxLANGUAGE_ENGLISH_US); |
156 | | |
157 | | // add standard wxWidgets catalog ("wxstd") |
158 | | bool AddStdCatalog(); |
159 | | |
160 | | // add catalog with given domain name and language, looking it up via |
161 | | // wxTranslationsLoader -- unlike AddAvailableCatalog(), this function also |
162 | | // returns true if this catalog is not needed at all because msgIdLanguage |
163 | | // is an acceptable language to use directly |
164 | | bool AddCatalog(const wxString& domain, |
165 | | wxLanguage msgIdLanguage = wxLANGUAGE_ENGLISH_US); |
166 | | |
167 | | // check if the given catalog is loaded |
168 | | bool IsLoaded(const wxString& domain) const; |
169 | | |
170 | | // access to translations |
171 | | const wxString *GetTranslatedString(const wxString& origString, |
172 | | const wxString& domain = wxEmptyString, |
173 | | const wxString& context = wxEmptyString) const; |
174 | | const wxString *GetTranslatedString(const wxString& origString, |
175 | | unsigned n, |
176 | | const wxString& domain = wxEmptyString, |
177 | | const wxString& context = wxEmptyString) const; |
178 | | |
179 | | wxString GetHeaderValue(const wxString& header, |
180 | | const wxString& domain = wxEmptyString) const; |
181 | | |
182 | | // this is hack to work around a problem with wxGetTranslation() which |
183 | | // returns const wxString& and not wxString, so when it returns untranslated |
184 | | // string, it needs to have a copy of it somewhere |
185 | | static const wxString& GetUntranslatedString(const wxString& str); |
186 | | |
187 | | private: |
188 | | enum class Translations |
189 | | { |
190 | | NotNeeded = -1, |
191 | | NotFound = 0, |
192 | | Found = 1 |
193 | | }; |
194 | | |
195 | | Translations DoAddCatalog(const wxString& domain, wxLanguage msgIdLanguage); |
196 | | |
197 | | // perform loading of the catalog via m_loader |
198 | | bool LoadCatalog(const wxString& domain, const wxString& lang); |
199 | | |
200 | | // find catalog by name in a linked list, return nullptr if !found |
201 | | wxMsgCatalog *FindCatalog(const wxString& domain) const; |
202 | | |
203 | | // same as Set(), without taking ownership; only for wxLocale |
204 | | static void SetNonOwned(wxTranslations *t); |
205 | | friend class wxLocale; |
206 | | |
207 | | wxString DoGetBestAvailableTranslation(const wxString& domain, const wxString& additionalAvailableLanguage); |
208 | | |
209 | | private: |
210 | | wxString m_lang; |
211 | | wxTranslationsLoader *m_loader; |
212 | | |
213 | | wxMsgCatalog *m_pMsgCat; // pointer to linked list of catalogs |
214 | | |
215 | | // In addition to keeping all the catalogs in the linked list, we also |
216 | | // store them in a hash map indexed by the domain name to allow finding |
217 | | // them by name efficiently. |
218 | | using wxMsgCatalogMap = std::unordered_map<wxString, wxMsgCatalog*>; |
219 | | wxMsgCatalogMap m_catalogMap; |
220 | | }; |
221 | | |
222 | | |
223 | | // abstraction of translations discovery and loading |
224 | | class WXDLLIMPEXP_BASE wxTranslationsLoader |
225 | | { |
226 | | public: |
227 | 0 | wxTranslationsLoader() = default; |
228 | 0 | virtual ~wxTranslationsLoader() = default; |
229 | | |
230 | | virtual wxMsgCatalog *LoadCatalog(const wxString& domain, |
231 | | const wxString& lang) = 0; |
232 | | |
233 | | virtual wxArrayString GetAvailableTranslations(const wxString& domain) const = 0; |
234 | | }; |
235 | | |
236 | | |
237 | | // standard wxTranslationsLoader implementation, using filesystem |
238 | | class WXDLLIMPEXP_BASE wxFileTranslationsLoader |
239 | | : public wxTranslationsLoader |
240 | | { |
241 | | public: |
242 | | static void AddCatalogLookupPathPrefix(const wxString& prefix); |
243 | | |
244 | | virtual wxMsgCatalog *LoadCatalog(const wxString& domain, |
245 | | const wxString& lang) override; |
246 | | |
247 | | virtual wxArrayString GetAvailableTranslations(const wxString& domain) const override; |
248 | | }; |
249 | | |
250 | | |
251 | | #ifdef __WINDOWS__ |
252 | | // loads translations from win32 resources |
253 | | class WXDLLIMPEXP_BASE wxResourceTranslationsLoader |
254 | | : public wxTranslationsLoader |
255 | | { |
256 | | public: |
257 | | virtual wxMsgCatalog *LoadCatalog(const wxString& domain, |
258 | | const wxString& lang) override; |
259 | | |
260 | | virtual wxArrayString GetAvailableTranslations(const wxString& domain) const override; |
261 | | |
262 | | protected: |
263 | | // returns resource type to use for translations |
264 | | virtual wxString GetResourceType() const { return wxASCII_STR("MOFILE"); } |
265 | | |
266 | | // returns module to load resources from |
267 | | virtual WXHINSTANCE GetModule() const { return nullptr; } |
268 | | }; |
269 | | #endif // __WINDOWS__ |
270 | | |
271 | | |
272 | | // ---------------------------------------------------------------------------- |
273 | | // global functions |
274 | | // ---------------------------------------------------------------------------- |
275 | | |
276 | | // get the translation of the string in the current locale |
277 | | inline const wxString& wxGetTranslation(const wxString& str, |
278 | | const wxString& domain = wxString(), |
279 | | const wxString& context = wxString()) |
280 | 0 | { |
281 | 0 | wxTranslations *trans = wxTranslations::Get(); |
282 | 0 | const wxString *transStr = trans ? trans->GetTranslatedString(str, domain, context) |
283 | 0 | : nullptr; |
284 | 0 | if ( transStr ) |
285 | 0 | return *transStr; |
286 | 0 | else |
287 | | // NB: this function returns reference to a string, so we have to keep |
288 | | // a copy of it somewhere |
289 | 0 | return wxTranslations::GetUntranslatedString(str); |
290 | 0 | } |
291 | | |
292 | | inline const wxString& wxGetTranslation(const wxString& str1, |
293 | | const wxString& str2, |
294 | | unsigned n, |
295 | | const wxString& domain = wxString(), |
296 | | const wxString& context = wxString()) |
297 | 0 | { |
298 | 0 | wxTranslations *trans = wxTranslations::Get(); |
299 | 0 | const wxString *transStr = trans ? trans->GetTranslatedString(str1, n, domain, context) |
300 | 0 | : nullptr; |
301 | 0 | if ( transStr ) |
302 | 0 | return *transStr; |
303 | 0 | else |
304 | | // NB: this function returns reference to a string, so we have to keep |
305 | | // a copy of it somewhere |
306 | 0 | return n == 1 |
307 | 0 | ? wxTranslations::GetUntranslatedString(str1) |
308 | 0 | : wxTranslations::GetUntranslatedString(str2); |
309 | 0 | } |
310 | | |
311 | | #ifdef wxNO_IMPLICIT_WXSTRING_ENCODING |
312 | | |
313 | | /* |
314 | | * It must always be possible to call wxGetTranslation() with const |
315 | | * char* arguments. |
316 | | */ |
317 | | inline const wxString& wxGetTranslation(const char *str, |
318 | | const char *domain = "", |
319 | | const char *context = "") { |
320 | | const wxMBConv &conv = wxConvWhateverWorks; |
321 | | return wxGetTranslation(wxString(str, conv), wxString(domain, conv), |
322 | | wxString(context, conv)); |
323 | | } |
324 | | |
325 | | inline const wxString& wxGetTranslation(const char *str1, |
326 | | const char *str2, |
327 | | unsigned n, |
328 | | const char *domain = "", |
329 | | const char *context = "") { |
330 | | const wxMBConv &conv = wxConvWhateverWorks; |
331 | | return wxGetTranslation(wxString(str1, conv), wxString(str2, conv), n, |
332 | | wxString(domain, conv), |
333 | | wxString(context, conv)); |
334 | | } |
335 | | |
336 | | // We can't construct wxString implicitly in this case, so use a helper. |
337 | | inline wxString wxTRANS_INPUT_STR(const char* s) |
338 | | { |
339 | | return wxString::FromAscii(s); |
340 | | } |
341 | | |
342 | | inline wxString wxTRANS_INPUT_STR(const wchar_t* s) |
343 | | { |
344 | | return wxString(s); |
345 | | } |
346 | | #else // !wxNO_IMPLICIT_WXSTRING_ENCODING |
347 | | // We can rely on implicit conversion, so don't bother with the helper. |
348 | 0 | #define wxTRANS_INPUT_STR(s) s |
349 | | #endif // wxNO_IMPLICIT_WXSTRING_ENCODING |
350 | | |
351 | | #ifndef wxNO_REQUIRE_LITERAL_MSGIDS |
352 | | |
353 | | // Wrapper functions that only accept string literals as arguments, |
354 | | // not variables, not char* pointers, and define the fall backs only in |
355 | | // order to point out to the comment below: |
356 | | |
357 | | /* |
358 | | *** LITERALS-MSGID comment marker *** |
359 | | |
360 | | This comment explains the reason for static assert failures below. Please |
361 | | see https://wxwidgets.org/help/msgid-literals for a more detailed and |
362 | | possibly more up-to-date version of this comment. |
363 | | |
364 | | If you get a compile error when using any of the translation macros, i.e. |
365 | | _(), wxPLURAL() etc, it means that you're passing something other than a |
366 | | literal string, i.e. just simple "whatever", to wx translation functions. |
367 | | This most likely indicates a bug in your program which is now detected when |
368 | | it was silently ignored before and should be fixed by changing the code to |
369 | | use string literals. For example, existing code doing |
370 | | |
371 | | _(wxString::Format("Hello %s", who)) |
372 | | |
373 | | wouldn't work properly even if it were allowed to compile and should be |
374 | | changed to |
375 | | |
376 | | wxString::Format(_("Hello %s"), who)) |
377 | | |
378 | | However if you can't do this, for some reason, you may choose to predefine |
379 | | wxNO_REQUIRE_LITERAL_MSGIDS which disables these checks. Please note that |
380 | | this is *NOT* recommended, as the problematic strings still won't be |
381 | | translated, because they won't have been extracted by xgettext in the first |
382 | | place and the right thing to do remains to fix the code instead. |
383 | | */ |
384 | | |
385 | | template<size_t N, typename T> |
386 | | const wxString& wxUnderscoreWrapper(const T (&msg)[N]) |
387 | 0 | { |
388 | 0 | return wxGetTranslation(wxTRANS_INPUT_STR(msg)); |
389 | 0 | } Unexecuted instantiation: wxString const& wxUnderscoreWrapper<4ul, char>(char const (&) [4ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<7ul, char>(char const (&) [7ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<5ul, char>(char const (&) [5ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<29ul, char>(char const (&) [29ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<25ul, char>(char const (&) [25ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<20ul, char>(char const (&) [20ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<45ul, char>(char const (&) [45ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<30ul, char>(char const (&) [30ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<42ul, char>(char const (&) [42ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<53ul, char>(char const (&) [53ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<49ul, char>(char const (&) [49ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<26ul, char>(char const (&) [26ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<11ul, char>(char const (&) [11ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<47ul, char>(char const (&) [47ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<10ul, char>(char const (&) [10ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<57ul, char>(char const (&) [57ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<77ul, char>(char const (&) [77ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<144ul, char>(char const (&) [144ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<35ul, char>(char const (&) [35ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<40ul, char>(char const (&) [40ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<44ul, char>(char const (&) [44ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<43ul, char>(char const (&) [43ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<41ul, char>(char const (&) [41ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<67ul, char>(char const (&) [67ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<31ul, char>(char const (&) [31ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<48ul, char>(char const (&) [48ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<54ul, char>(char const (&) [54ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<59ul, char>(char const (&) [59ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<58ul, char>(char const (&) [58ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<36ul, char>(char const (&) [36ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<37ul, char>(char const (&) [37ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<38ul, char>(char const (&) [38ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<46ul, char>(char const (&) [46ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<84ul, char>(char const (&) [84ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<28ul, char>(char const (&) [28ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<39ul, char>(char const (&) [39ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<17ul, char>(char const (&) [17ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<22ul, char>(char const (&) [22ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<8ul, char>(char const (&) [8ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<52ul, char>(char const (&) [52ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<34ul, char>(char const (&) [34ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<33ul, char>(char const (&) [33ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<23ul, char>(char const (&) [23ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<64ul, char>(char const (&) [64ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<14ul, char>(char const (&) [14ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<85ul, char>(char const (&) [85ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<65ul, char>(char const (&) [65ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<24ul, char>(char const (&) [24ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<12ul, char>(char const (&) [12ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<60ul, char>(char const (&) [60ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<50ul, char>(char const (&) [50ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<51ul, char>(char const (&) [51ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<21ul, char>(char const (&) [21ul]) Unexecuted instantiation: wxString const& wxUnderscoreWrapper<63ul, char>(char const (&) [63ul]) |
390 | | |
391 | | template <typename T> |
392 | | wxString wxUnderscoreWrapper(T) |
393 | | { |
394 | | static_assert(!sizeof(T), "See https://wxwidgets.org/help/msgid-literals or LITERALS-MSGID comment above."); |
395 | | return {}; |
396 | | } |
397 | | |
398 | | template<size_t M, size_t N, typename T> |
399 | | const wxString& wxPluralWrapper(const T (&msg)[M], |
400 | | const T (&plural)[N], |
401 | | int count) |
402 | 0 | { |
403 | 0 | return wxGetTranslation(wxTRANS_INPUT_STR(msg), wxTRANS_INPUT_STR(plural), |
404 | 0 | count); |
405 | 0 | } Unexecuted instantiation: wxString const& wxPluralWrapper<39ul, 40ul, char>(char const (&) [39ul], char const (&) [40ul], int) Unexecuted instantiation: wxString const& wxPluralWrapper<52ul, 53ul, char>(char const (&) [52ul], char const (&) [53ul], int) |
406 | | |
407 | | template <typename T, typename U> |
408 | | wxString wxPluralWrapper(T, U, int) |
409 | | { |
410 | | static_assert(!sizeof(T), "See https://wxwidgets.org/help/msgid-literals or LITERALS-MSGID comment above."); |
411 | | return {}; |
412 | | } |
413 | | |
414 | | template<size_t M, size_t N, typename T> |
415 | | const wxString& wxGettextInContextWrapper(const T (&ctx)[M], |
416 | | const T (&msg)[N]) |
417 | | { |
418 | | return wxGetTranslation(wxTRANS_INPUT_STR(msg), wxString(), |
419 | | wxTRANS_INPUT_STR(ctx)); |
420 | | } |
421 | | |
422 | | template <typename T, typename U> |
423 | | wxString wxGettextInContextWrapper(T, U) |
424 | | { |
425 | | static_assert(!sizeof(T), "See https://wxwidgets.org/help/msgid-literals or LITERALS-MSGID comment above."); |
426 | | return {}; |
427 | | } |
428 | | |
429 | | template<size_t L, size_t M, size_t N, typename T> |
430 | | const wxString& wxGettextInContextPluralWrapper(const T (&ctx)[L], |
431 | | const T (&msg)[M], |
432 | | const T (&plural)[N], |
433 | | int count) |
434 | | { |
435 | | return wxGetTranslation(wxTRANS_INPUT_STR(msg), wxTRANS_INPUT_STR(plural), |
436 | | count, wxString(), wxTRANS_INPUT_STR(ctx)); |
437 | | } |
438 | | |
439 | | template <typename T, typename U, typename V> |
440 | | wxString wxGettextInContextPluralWrapper(T, U, V, int) |
441 | | { |
442 | | static_assert(!sizeof(T), "See https://wxwidgets.org/help/msgid-literals or LITERALS-MSGID comment above."); |
443 | | return {}; |
444 | | } |
445 | | |
446 | | #else // wxNO_REQUIRE_LITERAL_MSGIDS |
447 | | |
448 | | // Wrapper functions that accept both string literals and variables |
449 | | // as arguments. |
450 | | inline const wxString& wxUnderscoreWrapper(const char *msg) |
451 | | { |
452 | | return wxGetTranslation(wxTRANS_INPUT_STR(msg)); |
453 | | } |
454 | | |
455 | | inline const wxString& wxPluralWrapper(const char *msg, |
456 | | const char *plural, |
457 | | int count) |
458 | | { |
459 | | return wxGetTranslation(wxTRANS_INPUT_STR(msg), wxTRANS_INPUT_STR(plural), |
460 | | count); |
461 | | } |
462 | | |
463 | | inline const wxString& wxGettextInContextWrapper(const char *ctx, |
464 | | const char *msg) |
465 | | { |
466 | | return wxGetTranslation(wxTRANS_INPUT_STR(msg), wxString(), |
467 | | wxTRANS_INPUT_STR(ctx)); |
468 | | } |
469 | | |
470 | | inline const wxString& wxGettextInContextPluralWrapper(const char *ctx, |
471 | | const char *msg, |
472 | | const char *plural, |
473 | | int count) |
474 | | { |
475 | | return wxGetTranslation(wxTRANS_INPUT_STR(msg), wxTRANS_INPUT_STR(plural), |
476 | | count, wxString(), wxTRANS_INPUT_STR(ctx)); |
477 | | } |
478 | | |
479 | | #endif // wxNO_REQUIRE_LITERAL_MSGIDS |
480 | | |
481 | | #else // !wxUSE_INTL |
482 | | |
483 | | // the macros should still be defined - otherwise compilation would fail |
484 | | |
485 | | #if !defined(WXINTL_NO_GETTEXT_MACRO) |
486 | | #if !defined(_) |
487 | | #ifndef wxNO_IMPLICIT_WXSTRING_ENCODING |
488 | | #define _(s) (s) |
489 | | #else |
490 | | #define _(s) wxASCII_STR(s) |
491 | | #endif |
492 | | #endif |
493 | | #define wxPLURAL(sing, plur, n) ((n) == 1 ? (sing) : (plur)) |
494 | | #define wxGETTEXT_IN_CONTEXT(c, s) (s) |
495 | | #define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n) wxPLURAL(sing, plur, n) |
496 | | #endif |
497 | | |
498 | | #define wxTRANSLATE(str) str |
499 | | #define wxTRANSLATE_IN_CONTEXT(c, str) str |
500 | | |
501 | | // NB: we use a template here in order to avoid using |
502 | | // wxLocale::GetUntranslatedString() above, which would be required if |
503 | | // we returned const wxString&; this way, the compiler should be able to |
504 | | // optimize wxGetTranslation() away |
505 | | |
506 | | template<typename TString> |
507 | | inline TString wxGetTranslation(TString str) |
508 | | { return str; } |
509 | | |
510 | | template<typename TString, typename TDomain> |
511 | | inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain)) |
512 | | { return str; } |
513 | | |
514 | | template<typename TString, typename TDomain, typename TContext> |
515 | | inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain), TContext WXUNUSED(context)) |
516 | | { return str; } |
517 | | |
518 | | template<typename TString, typename TDomain> |
519 | | inline TString wxGetTranslation(TString str1, TString str2, size_t n) |
520 | | { return n == 1 ? str1 : str2; } |
521 | | |
522 | | template<typename TString, typename TDomain> |
523 | | inline TString wxGetTranslation(TString str1, TString str2, size_t n, |
524 | | TDomain WXUNUSED(domain)) |
525 | | { return n == 1 ? str1 : str2; } |
526 | | |
527 | | template<typename TString, typename TDomain, typename TContext> |
528 | | inline TString wxGetTranslation(TString str1, TString str2, size_t n, |
529 | | TDomain WXUNUSED(domain), |
530 | | TContext WXUNUSED(context)) |
531 | | { return n == 1 ? str1 : str2; } |
532 | | |
533 | | #endif // wxUSE_INTL/!wxUSE_INTL |
534 | | |
535 | | // define this one just in case it occurs somewhere (instead of preferred |
536 | | // wxTRANSLATE) too |
537 | | #if !defined(WXINTL_NO_GETTEXT_MACRO) |
538 | | #if !defined(gettext_noop) |
539 | 0 | #define gettext_noop(str) (str) |
540 | | #endif |
541 | | #if !defined(N_) |
542 | | #define N_(s) (s) |
543 | | #endif |
544 | | #endif |
545 | | |
546 | | #endif // _WX_TRANSLATION_H_ |