wxMsgCatalog destructor should be public.
[wxWidgets.git] / include / wx / translation.h
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 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // (c) 2010 Vaclav Slavik <vslavik@fastmail.fm>
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifndef _WX_TRANSLATION_H_
14 #define _WX_TRANSLATION_H_
15
16 #include "wx/defs.h"
17 #include "wx/string.h"
18
19 #if wxUSE_INTL
20
21 #include "wx/buffer.h"
22 #include "wx/language.h"
23 #include "wx/hashmap.h"
24 #include "wx/strconv.h"
25 #include "wx/scopedptr.h"
26
27 // ============================================================================
28 // global decls
29 // ============================================================================
30
31 // ----------------------------------------------------------------------------
32 // macros
33 // ----------------------------------------------------------------------------
34
35 // gettext() style macros (notice that xgettext should be invoked with
36 // --keyword="_" --keyword="wxPLURAL:1,2" options
37 // to extract the strings from the sources)
38 #ifndef WXINTL_NO_GETTEXT_MACRO
39 #define _(s) wxGetTranslation((s))
40 #define wxPLURAL(sing, plur, n) wxGetTranslation((sing), (plur), n)
41 #endif
42
43 // another one which just marks the strings for extraction, but doesn't
44 // perform the translation (use -kwxTRANSLATE with xgettext!)
45 #define wxTRANSLATE(str) str
46
47 // ----------------------------------------------------------------------------
48 // forward decls
49 // ----------------------------------------------------------------------------
50
51 class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader;
52 class WXDLLIMPEXP_FWD_BASE wxLocale;
53
54 class wxPluralFormsCalculator;
55 wxDECLARE_SCOPED_PTR(wxPluralFormsCalculator, wxPluralFormsCalculatorPtr)
56
57 // ----------------------------------------------------------------------------
58 // wxMsgCatalog corresponds to one loaded message catalog.
59 // ----------------------------------------------------------------------------
60
61 class WXDLLIMPEXP_BASE wxMsgCatalog
62 {
63 public:
64 // Ctor is protected, because CreateFromXXX functions must be used,
65 // but destruction should be unrestricted
66 #if !wxUSE_UNICODE
67 ~wxMsgCatalog();
68 #endif
69
70 // load the catalog from disk or from data; caller is responsible for
71 // deleting them if not NULL
72 static wxMsgCatalog *CreateFromFile(const wxString& filename,
73 const wxString& domain);
74
75 static wxMsgCatalog *CreateFromData(const wxScopedCharBuffer& data,
76 const wxString& domain);
77
78 // get name of the catalog
79 wxString GetDomain() const { return m_domain; }
80
81 // get the translated string: returns NULL if not found
82 const wxString *GetString(const wxString& sz, unsigned n = UINT_MAX) const;
83
84 protected:
85 wxMsgCatalog(const wxString& domain)
86 : m_pNext(NULL), m_domain(domain)
87 #if !wxUSE_UNICODE
88 , m_conv(NULL)
89 #endif
90 {}
91
92 private:
93 // variable pointing to the next element in a linked list (or NULL)
94 wxMsgCatalog *m_pNext;
95 friend class wxTranslations;
96
97 wxStringToStringHashMap m_messages; // all messages in the catalog
98 wxString m_domain; // name of the domain
99
100 #if !wxUSE_UNICODE
101 // the conversion corresponding to this catalog charset if we installed it
102 // as the global one
103 wxCSConv *m_conv;
104 #endif
105
106 wxPluralFormsCalculatorPtr m_pluralFormsCalculator;
107 };
108
109 // ----------------------------------------------------------------------------
110 // wxTranslations: message catalogs
111 // ----------------------------------------------------------------------------
112
113 // this class allows to get translations for strings
114 class WXDLLIMPEXP_BASE wxTranslations
115 {
116 public:
117 wxTranslations();
118 ~wxTranslations();
119
120 // returns current translations object, may return NULL
121 static wxTranslations *Get();
122 // sets current translations object (takes ownership; may be NULL)
123 static void Set(wxTranslations *t);
124
125 // changes loader to non-default one; takes ownership of 'loader'
126 void SetLoader(wxTranslationsLoader *loader);
127
128 void SetLanguage(wxLanguage lang);
129 void SetLanguage(const wxString& lang);
130
131 // add standard wxWidgets catalog ("wxstd")
132 bool AddStdCatalog();
133
134 // add catalog with given domain name and language, looking it up via
135 // wxTranslationsLoader
136 bool AddCatalog(const wxString& domain);
137 bool AddCatalog(const wxString& domain, wxLanguage msgIdLanguage);
138 #if !wxUSE_UNICODE
139 bool AddCatalog(const wxString& domain,
140 wxLanguage msgIdLanguage,
141 const wxString& msgIdCharset);
142 #endif
143
144 // check if the given catalog is loaded
145 bool IsLoaded(const wxString& domain) const;
146
147 // access to translations
148 const wxString& GetString(const wxString& origString,
149 const wxString& domain = wxEmptyString) const;
150 const wxString& GetString(const wxString& origString,
151 const wxString& origString2,
152 unsigned n,
153 const wxString& domain = wxEmptyString) const;
154
155 wxString GetHeaderValue(const wxString& header,
156 const wxString& domain = wxEmptyString) const;
157
158 // this is hack to work around a problem with wxGetTranslation() which
159 // returns const wxString& and not wxString, so when it returns untranslated
160 // string, it needs to have a copy of it somewhere
161 static const wxString& GetUntranslatedString(const wxString& str);
162
163 private:
164 // perform loading of the catalog via m_loader
165 bool LoadCatalog(const wxString& domain, const wxString& lang);
166
167 // find best translation for given domain
168 wxString ChooseLanguageForDomain(const wxString& domain,
169 const wxString& msgIdLang);
170
171 // find catalog by name in a linked list, return NULL if !found
172 wxMsgCatalog *FindCatalog(const wxString& domain) const;
173
174 // same as Set(), without taking ownership; only for wxLocale
175 static void SetNonOwned(wxTranslations *t);
176 friend class wxLocale;
177
178 private:
179 wxString m_lang;
180 wxTranslationsLoader *m_loader;
181
182 wxMsgCatalog *m_pMsgCat; // pointer to linked list of catalogs
183 };
184
185
186 // abstraction of translations discovery and loading
187 class WXDLLIMPEXP_BASE wxTranslationsLoader
188 {
189 public:
190 wxTranslationsLoader() {}
191 virtual ~wxTranslationsLoader() {}
192
193 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
194 const wxString& lang) = 0;
195 };
196
197
198 // standard wxTranslationsLoader implementation, using filesystem
199 class WXDLLIMPEXP_BASE wxFileTranslationsLoader
200 : public wxTranslationsLoader
201 {
202 public:
203 static void AddCatalogLookupPathPrefix(const wxString& prefix);
204
205 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
206 const wxString& lang);
207 };
208
209
210 #ifdef __WINDOWS__
211 // loads translations from win32 resources
212 class WXDLLIMPEXP_BASE wxResourceTranslationsLoader
213 : public wxTranslationsLoader
214 {
215 public:
216 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
217 const wxString& lang);
218
219 protected:
220 // returns resource type to use for translations
221 virtual wxString GetResourceType() const { return "MOFILE"; }
222
223 // returns module to load resources from
224 virtual WXHINSTANCE GetModule() const { return 0; }
225 };
226 #endif // __WINDOWS__
227
228
229 // ----------------------------------------------------------------------------
230 // global functions
231 // ----------------------------------------------------------------------------
232
233 // get the translation of the string in the current locale
234 inline const wxString& wxGetTranslation(const wxString& str,
235 const wxString& domain = wxEmptyString)
236 {
237 wxTranslations *trans = wxTranslations::Get();
238 if ( trans )
239 return trans->GetString(str, domain);
240 else
241 // NB: this function returns reference to a string, so we have to keep
242 // a copy of it somewhere
243 return wxTranslations::GetUntranslatedString(str);
244 }
245
246 inline const wxString& wxGetTranslation(const wxString& str1,
247 const wxString& str2,
248 unsigned n,
249 const wxString& domain = wxEmptyString)
250 {
251 wxTranslations *trans = wxTranslations::Get();
252 if ( trans )
253 return trans->GetString(str1, str2, n, domain);
254 else
255 // NB: this function returns reference to a string, so we have to keep
256 // a copy of it somewhere
257 return n == 1
258 ? wxTranslations::GetUntranslatedString(str1)
259 : wxTranslations::GetUntranslatedString(str2);
260 }
261
262 #else // !wxUSE_INTL
263
264 // the macros should still be defined - otherwise compilation would fail
265
266 #if !defined(WXINTL_NO_GETTEXT_MACRO)
267 #if !defined(_)
268 #define _(s) (s)
269 #endif
270 #define wxPLURAL(sing, plur, n) ((n) == 1 ? (sing) : (plur))
271 #endif
272
273 #define wxTRANSLATE(str) str
274
275 // NB: we use a template here in order to avoid using
276 // wxLocale::GetUntranslatedString() above, which would be required if
277 // we returned const wxString&; this way, the compiler should be able to
278 // optimize wxGetTranslation() away
279
280 template<typename TString>
281 inline TString wxGetTranslation(TString str)
282 { return str; }
283
284 template<typename TString, typename TDomain>
285 inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain))
286 { return str; }
287
288 template<typename TString, typename TDomain>
289 inline TString wxGetTranslation(TString str1, TString str2, size_t n)
290 { return n == 1 ? str1 : str2; }
291
292 template<typename TString, typename TDomain>
293 inline TString wxGetTranslation(TString str1, TString str2, size_t n,
294 TDomain WXUNUSED(domain))
295 { return n == 1 ? str1 : str2; }
296
297 #endif // wxUSE_INTL/!wxUSE_INTL
298
299 // define this one just in case it occurs somewhere (instead of preferred
300 // wxTRANSLATE) too
301 #if !defined(WXINTL_NO_GETTEXT_MACRO)
302 #if !defined(gettext_noop)
303 #define gettext_noop(str) (str)
304 #endif
305 #if !defined(N_)
306 #define N_(s) (s)
307 #endif
308 #endif
309
310 #endif // _WX_TRANSLATION_H_