Add support for storing translations in win32 resources.
[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
24 #if !wxUSE_UNICODE
25 #include "wx/hashmap.h"
26 #endif
27
28 // ============================================================================
29 // global decls
30 // ============================================================================
31
32 // ----------------------------------------------------------------------------
33 // macros
34 // ----------------------------------------------------------------------------
35
36 // gettext() style macros (notice that xgettext should be invoked with
37 // --keyword="_" --keyword="wxPLURAL:1,2" options
38 // to extract the strings from the sources)
39 #ifndef WXINTL_NO_GETTEXT_MACRO
40 #define _(s) wxGetTranslation((s))
41 #define wxPLURAL(sing, plur, n) wxGetTranslation((sing), (plur), n)
42 #endif
43
44 // another one which just marks the strings for extraction, but doesn't
45 // perform the translation (use -kwxTRANSLATE with xgettext!)
46 #define wxTRANSLATE(str) str
47
48 // ----------------------------------------------------------------------------
49 // forward decls
50 // ----------------------------------------------------------------------------
51
52 class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader;
53 class WXDLLIMPEXP_FWD_BASE wxLocale;
54 class wxMsgCatalog;
55
56 // ----------------------------------------------------------------------------
57 // wxTranslations: message catalogs
58 // ----------------------------------------------------------------------------
59
60 // this class allows to get translations for strings
61 class WXDLLIMPEXP_BASE wxTranslations
62 {
63 public:
64 wxTranslations();
65 ~wxTranslations();
66
67 // returns current translations object, may return NULL
68 static wxTranslations *Get();
69 // sets current translations object (takes ownership; may be NULL)
70 static void Set(wxTranslations *t);
71
72 // changes loader to non-default one; takes ownership of 'loader'
73 void SetLoader(wxTranslationsLoader *loader);
74
75 void SetLanguage(wxLanguage lang);
76 void SetLanguage(const wxString& lang);
77
78 // add standard wxWidgets catalog ("wxstd")
79 bool AddStdCatalog();
80
81 // add catalog with given domain name and language, looking it up via
82 // wxTranslationsLoader
83 bool AddCatalog(const wxString& domain);
84 bool AddCatalog(const wxString& domain, wxLanguage msgIdLanguage);
85 #if !wxUSE_UNICODE
86 bool AddCatalog(const wxString& domain,
87 wxLanguage msgIdLanguage,
88 const wxString& msgIdCharset);
89 #endif
90
91 // check if the given catalog is loaded
92 bool IsLoaded(const wxString& domain) const;
93
94 // load catalog data directly from file or memory
95 bool LoadCatalogFile(const wxString& filename,
96 const wxString& domain = wxEmptyString);
97 bool LoadCatalogData(const wxScopedCharTypeBuffer<char>& data,
98 const wxString& domain = wxEmptyString);
99
100 // access to translations
101 const wxString& GetString(const wxString& origString,
102 const wxString& domain = wxEmptyString) const;
103 const wxString& GetString(const wxString& origString,
104 const wxString& origString2,
105 size_t n,
106 const wxString& domain = wxEmptyString) const;
107
108 wxString GetHeaderValue(const wxString& header,
109 const wxString& domain = wxEmptyString) const;
110
111 // this is hack to work around a problem with wxGetTranslation() which
112 // returns const wxString& and not wxString, so when it returns untranslated
113 // string, it needs to have a copy of it somewhere
114 static const wxString& GetUntranslatedString(const wxString& str);
115
116 private:
117 // perform loading of the catalog via m_loader
118 bool LoadCatalog(const wxString& domain, const wxString& lang);
119
120 // find best translation for given domain
121 wxString ChooseLanguageForDomain(const wxString& domain,
122 const wxString& msgIdLang);
123
124 // find catalog by name in a linked list, return NULL if !found
125 wxMsgCatalog *FindCatalog(const wxString& domain) const;
126
127 // same as Set(), without taking ownership; only for wxLocale
128 static void SetNonOwned(wxTranslations *t);
129 friend class wxLocale;
130
131 private:
132 wxString m_lang;
133 wxTranslationsLoader *m_loader;
134
135 wxMsgCatalog *m_pMsgCat; // pointer to linked list of catalogs
136
137 #if !wxUSE_UNICODE
138 wxStringToStringHashMap m_msgIdCharset;
139 #endif
140 };
141
142
143 // abstraction of translations discovery and loading
144 class WXDLLIMPEXP_BASE wxTranslationsLoader
145 {
146 public:
147 wxTranslationsLoader() {}
148 virtual ~wxTranslationsLoader() {}
149
150 virtual bool LoadCatalog(wxTranslations *translations,
151 const wxString& domain, const wxString& lang) = 0;
152 };
153
154
155 // standard wxTranslationsLoader implementation, using filesystem
156 class WXDLLIMPEXP_BASE wxFileTranslationsLoader
157 : public wxTranslationsLoader
158 {
159 public:
160 static void AddCatalogLookupPathPrefix(const wxString& prefix);
161
162 virtual bool LoadCatalog(wxTranslations *translations,
163 const wxString& domain, const wxString& lang);
164 };
165
166
167 #ifdef __WINDOWS__
168 // loads translations from win32 resources
169 class WXDLLIMPEXP_BASE wxResourceTranslationsLoader
170 : public wxTranslationsLoader
171 {
172 public:
173 virtual bool LoadCatalog(wxTranslations *translations,
174 const wxString& domain, const wxString& lang);
175
176 protected:
177 // returns resource type to use for translations
178 virtual wxString GetResourceType() const { return "MOFILE"; }
179
180 // returns module to load resources from
181 virtual WXHINSTANCE GetModule() const { return 0; }
182 };
183 #endif // __WINDOWS__
184
185
186 // ----------------------------------------------------------------------------
187 // global functions
188 // ----------------------------------------------------------------------------
189
190 // get the translation of the string in the current locale
191 inline const wxString& wxGetTranslation(const wxString& str,
192 const wxString& domain = wxEmptyString)
193 {
194 wxTranslations *trans = wxTranslations::Get();
195 if ( trans )
196 return trans->GetString(str, domain);
197 else
198 // NB: this function returns reference to a string, so we have to keep
199 // a copy of it somewhere
200 return wxTranslations::GetUntranslatedString(str);
201 }
202
203 inline const wxString& wxGetTranslation(const wxString& str1,
204 const wxString& str2,
205 size_t n,
206 const wxString& domain = wxEmptyString)
207 {
208 wxTranslations *trans = wxTranslations::Get();
209 if ( trans )
210 return trans->GetString(str1, str2, n, domain);
211 else
212 // NB: this function returns reference to a string, so we have to keep
213 // a copy of it somewhere
214 return n == 1
215 ? wxTranslations::GetUntranslatedString(str1)
216 : wxTranslations::GetUntranslatedString(str2);
217 }
218
219 #else // !wxUSE_INTL
220
221 // the macros should still be defined - otherwise compilation would fail
222
223 #if !defined(WXINTL_NO_GETTEXT_MACRO)
224 #if !defined(_)
225 #define _(s) (s)
226 #endif
227 #define wxPLURAL(sing, plur, n) ((n) == 1 ? (sing) : (plur))
228 #endif
229
230 #define wxTRANSLATE(str) str
231
232 // NB: we use a template here in order to avoid using
233 // wxLocale::GetUntranslatedString() above, which would be required if
234 // we returned const wxString&; this way, the compiler should be able to
235 // optimize wxGetTranslation() away
236
237 template<typename TString>
238 inline TString wxGetTranslation(TString str)
239 { return str; }
240
241 template<typename TString, typename TDomain>
242 inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain))
243 { return str; }
244
245 template<typename TString, typename TDomain>
246 inline TString wxGetTranslation(TString str1, TString str2, size_t n)
247 { return n == 1 ? str1 : str2; }
248
249 template<typename TString, typename TDomain>
250 inline TString wxGetTranslation(TString str1, TString str2, size_t n,
251 TDomain WXUNUSED(domain))
252 { return n == 1 ? str1 : str2; }
253
254 #endif // wxUSE_INTL/!wxUSE_INTL
255
256 // define this one just in case it occurs somewhere (instead of preferred
257 // wxTRANSLATE) too
258 #if !defined(WXINTL_NO_GETTEXT_MACRO)
259 #if !defined(gettext_noop)
260 #define gettext_noop(str) (str)
261 #endif
262 #if !defined(N_)
263 #define N_(s) (s)
264 #endif
265 #endif
266
267 #endif // _WX_TRANSLATION_H_