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