translation.h 11 KB

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