All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Translator.h
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/common/Translator.h
22 
23  \brief This class is designed for dealing with multi-language text translation in TerraLib.
24 */
25 
26 #ifndef __TERRALIB_COMMON_INTERNAL_TRANSLATOR_H
27 #define __TERRALIB_COMMON_INTERNAL_TRANSLATOR_H
28 
29 // TerraLib
30 #include "Config.h"
31 
32 #ifdef TERRALIB_TRANSLATOR_ENABLED
33 #include "Singleton.h"
34 
35 // STL
36 #include <map>
37 #include <string>
38 
39 namespace te
40 {
41  namespace common
42  {
43  /*!
44  \class Translator
45 
46  \brief This singleton is designed to deal with multi-language text translation in TerraLib.
47 
48  The Translator job is to manage "Internationalization" of the TerraLib messages.
49  This class is all about Native Language Support.
50  For each string you want to have a translation, you have to use
51  the special macro TR_XXX("string"). This macro does nothing with your code;
52  its job is just to mark the code fragment that you want to translate and it does
53  all the job of calling the translation for you. Actually, the translation
54  is done using GNU Text Utilities. So, you can use commands like:
55  \verbatim
56  terralib# xgettext -D ../src/terralib/common -d tlcommon -o tlcommon.pot -f common.txt --keyword=TE_TR --from-code=UTF-8 --msgid-bugs-address=gribeiro.mg@gmail.com -p common
57  terralib# msgmerge --directory=common -U tlcommon-pt_BR.po tlcommon.pot
58  msgfmt --directory=common -c -v -o common/tlcommon-pt_BR.mo tlcommon-pt_BR.po
59  \endverbatim
60 
61  Each module must define its translation macro. For example, in the
62  Common module we define the macro TE_TR, and all strings in the Common module are marked like:
63 
64  \code
65  #include <terralib/common/Translator.h>
66  ...
67  char* msg = TE_TR("My Message");
68  ...
69  or
70  ...
71  std::cout << TE_TR("Other message");
72  ...
73  \endcode
74 
75  Note that all marked messages will be part of a .pot file from where you can
76  create several po documents, one for each idiom. These .po files
77  can be used to generate a .mo binary file with the translation.
78 
79  To create a translation macro, just do the following "define":
80  \code
81  #define TR_MYMODULE(message) TR(message, MY_MODULE_TEXT_DOMAIN)
82  \endcode
83 
84  It is recommended that you create a text domain for your module like:
85  \code
86  #define MY_MODULE_TEXT_DOMAIN "mymodule"
87  #define MY_MODULE_TEXT_DOMAIN_DIR "locale"
88  \endcode
89 
90  Then you can create a initialization routine for registering your module's text domain (i.e. the message catalog of your module):
91  \code
92  #include <terralib/common/Translator.h>
93  ...
94  te::common::Translator::getInstance().addTextDomain(MY_MODULE_TEXT_DOMAIN, MY_MODULE_TEXT_DOMAIN_DIR);
95  \endcode
96 
97  This will register your module text domain, enabling the selection of the domain
98  the strings are coming from when you use the macro TR_MYMODULE.
99 
100  You can create plurals like:
101  \code
102  int n = f(...);
103  const char* c = TR_PLURAL_COMMON("The module was initialized!", "The modules were initialized!", n);
104  \endcode
105 
106  \warning It is supposed that PO files are UTF-8 encoded.
107 
108  \todo Investigar o uso da biblioteca de formatacao de mensagens da BOOST para que seja possivel construir mensagens parametrizadas como no caso do printf. Isso pode dar um efeito muito melhor aas mensagens!
109 
110  \todo O todo acima deve ser considerado e todo codigo deve ser visto para poder colocar caracteres curinga dentro da mensagem que sejam substituidas, como o printf e cia!
111 
112  \todo Investigar o uso de mensagens no plural: http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html#Plural-forms.
113 
114  \ingroup common
115  */
116  class TECOMMONEXPORT Translator : public Singleton<Translator>
117  {
118  friend class Singleton<Translator>;
119 
120  public:
121 
122  /** @name Translation Methods
123  * Methods that can be used to tranlate texts.
124  */
125  //@{
126 
127  /*!
128  \brief It tries to translate the specified text string.
129 
130  If no translation is available it will return the
131  original message (always in English).
132 
133  \param message The text to be translated.
134  \param textDomain The text domain used in translation. A text domain is the name of the catalog used to translate the message.
135 
136  \return A pointer to the translated message. You must not delete the memory pointed by the returned pointer.
137 
138  \note The returned message is UTF-8 encoded.
139  */
140  const char* translate(const std::string& message,
141  const std::string& textDomain);
142 
143  /*!
144  \brief It tries to translate the specified text string.
145 
146  If no translation is available it will return the
147  original message (always in English).
148 
149  \param message The text to be translated.
150  \param textDomain The text domain used in the translation. A text domain is the name of the catalog used to translate the message.
151 
152  \return A pointer to the translated message. You must not delete the memory pointed by the returned pointer.
153 
154  \note The returned message is UTF-8 encoded.
155  */
156  const char* translate(const char* message,
157  const char* textDomain);
158 
159  /*!
160  \brief It tries to translate the specified text string accounting for plural forms.
161 
162  If no translation is available it will return the
163  original message (always in English).
164 
165  \param textDomain The text domain used in the translation. A text domain is the name of the catalog used to translate the message.
166  \param msg1 The singular form of the text to be translated.
167  \param msg2 The plural form of the text to be translated.
168  \param n This parameter is used to determine the plural form.
169 
170  \return A pointer to the translated message. You must not delete the memory pointed by the returned pointer.
171 
172  \note The returned message is UTF-8 encoded.
173  */
174  const char* translate(const std::string& textDomain,
175  const std::string& msg1,
176  const std::string& msg2,
177  unsigned int n);
178 
179  /*!
180  \brief It tries to translate the specified text string accounting for plural forms.
181 
182  If no translation is available it will return the
183  original message (always in English).
184 
185  \param textDomain The text domain used in translation. A text domain is the name of the catalog used to translate the message.
186  \param msg1 The singular form of the text to be translated.
187  \param msg2 The plural form of the text to be translated.
188  \param n This parameter is used to determine the plural form.
189 
190  \return A pointer to the translated message. You must not delete the memory pointed by the returned pointer.
191 
192  \note The returned message is UTF-8 encoded.
193  */
194  const char* translate(const char* textDomain,
195  const char* msg1,
196  const char* msg2,
197  unsigned int n);
198 
199  /*!
200  \brief It adds a new text domain (text catalog) associated to a given directory.
201 
202  \param textDomain A given message domain (just a name). A text domain is the name of the catalog used to translate the message.
203  \param textDomainDir The base directory for the message catalogs (added with full path).
204 
205  \return A NULL string if the domain is not added.
206 
207  \exception Exception If the text domain already exists it raises an exception. If you are not sure about the existence of a text domain, use the exist() method.
208  */
209  const char* addTextDomain(const std::string& textDomain, const std::string& textDomainDir);
210 
211  /*!
212  \brief It can be used to specify the output character set for a given message catalog.
213 
214  \param textDomain A given message domain (just a name). A text domain is the name of the catalog used to translate the message.
215  \param codeset If NULL returns the currently selected codeset for the domain. A valid codeset name is, for instance, UTF-8.
216 
217  \return A pointer to a string containing the name of the selected codeset. Don't delete the returned pointer!
218 
219  \exception Exception If the text domain doesn't exists. If you are not sure about the existence of a text domain, use the exist() method.
220  */
221  const char* setTextDomainCodeSet(const std::string& textDomain, const std::string& codeset);
222 
223  /*!
224  \brief It returns true if the text domain (text catalog) exists and false otherwise.
225 
226  \param textDomain A given message domain (just a name).
227  */
228  bool exist(const std::string& textDomain);
229 
230  /*!
231  \brief It returns the base directory for the message catalog identified by the text domain.
232 
233  \param textDomain A given message domain (just a name).
234 
235  \return The base directory for the message catalog identified by the text domain.
236 
237  \note If the domain doesn't exist, it will return an empty string.
238  */
239  std::string getTextDomainDir(const std::string& textDomain);
240 
241  //@}
242 
243  protected:
244 
245  /*! \brief Singleton constructor must be protected. */
246  Translator();
247 
248 
249  /* \brief Destructor. */
250  ~Translator();
251 
252  private:
253 
254  std::map<std::string, std::string> m_textDomainMap; //!< A map from text domains to base directory for the message catalog.
255  };
256 
257  } // end namespace common
258 } // end namespace te
259 
260 #endif // TERRALIB_TRANSLATOR_ENABLED
261 
262 /** @name Internationalization Defines
263  * Flags for TerraLib code internationalization.
264  */
265 //@{
266 
267 
268 // Check if the TR macro has already been defined
269 // by another application... if so, it will output
270 // an error message and stop compiling!
271 #ifdef TERRALIB_TRANSLATOR_ENABLED
272 #ifdef TE_TR
273 #error "The TE_TR macro has been already defined by another application or code. Please, inform TerraLib Development Team <terralib-team@dpi.inpe.br>, we will be glad to help solving this problem!"
274 #endif
275 #endif
276 
277 /*!
278  \def TERRALIB_TEXT_DOMAIN
279 
280  \brief It contains the name of the text domain used in the translation of messages in TerraLib.
281  */
282 #define TERRALIB_TEXT_DOMAIN "terralib"
283 
284 /*!
285  \def TERRALIB_TEXT_DOMAIN_DIR
286 
287  \brief It contains the translation catalog directory.
288  */
289 #define TERRALIB_TEXT_DOMAIN_DIR "locale"
290 
291 
292 /*!
293  \def TE_ADD_TEXT_DOMAIN
294 
295  \brief It adds the given text domain located at domain-dir with the given codeset to the multilingual system.
296 
297  \note This macro will check if the domain already exists before doing anyting.
298  */
299 #ifdef TERRALIB_TRANSLATOR_ENABLED
300  #define TE_ADD_TEXT_DOMAIN(domain, domaindir, codeset) \
301  if(!te::common::Translator::getInstance().exist(domain)) \
302  { \
303  te::common::Translator::getInstance().addTextDomain(domain, domaindir); \
304  te::common::Translator::getInstance().setTextDomainCodeSet(domain, codeset); \
305  } \
306  ((void)0)
307 #else
308  #define TE_ADD_TEXT_DOMAIN(domain, domaindir, codeset) ((void)0)
309 #endif
310 
311 /*!
312  \def TE_GENERAL_TR
313 
314  \brief Try to translate the message according to the given domain. See the TE_TR macro for more infomation on how to create a translation mark for your code.
315  */
316 #ifdef TERRALIB_TRANSLATOR_ENABLED
317  #define TE_GENERAL_TR(message, domain) te::common::Translator::getInstance().getInstance().translate(message, domain)
318 #else
319  #define TE_GENERAL_TR(message, domain) message
320 #endif
321 
322 /*!
323  \def TE_GENERAL_TR_PLURAL
324 
325  \brief Try to translate the message according to the given domain and plural form. See the TE_TR_PLURAL macro for more infomation on how to create a translation mark for your code.
326  */
327 #ifdef TERRALIB_TRANSLATOR_ENABLED
328  #define TE_GENERAL_TR_PLURAL(domain, message1, message2, n) te::common::Translator::getInstance().getInstance().translate(domain, message1, message2, n)
329 #else
330  #define TE_GENERAL_TR_PLURAL(domain, message1, message2, n) (n > 1 ? message2 : message1)
331 #endif
332 
333 /*!
334  \def TE_TR
335 
336  \brief It marks a string in order to get translated.
337 
338  Example of usage:
339  \code
340  std::cout << TE_TR("My message!");
341 
342  throw Exception(TE_TR("My other message!"));
343  \endcode
344  */
345 #define TE_TR(message) TE_GENERAL_TR(message, TERRALIB_TEXT_DOMAIN)
346 
347 /*!
348  \def TE_TR_PLURAL
349 
350  \brief It marks a string in order to get translated according to plural form.
351 
352  Example of usage:
353  \code
354  int n = f(...);
355 
356  std::cout << TE_TR_PLURAL("One Message!", "Two Messages", n);
357 
358  throw Exception(TE_TR_PLURAL("One Message!", "Two Messages", n));
359  \endcode
360 
361  In the above example, the parameter n can be
362  a threshold that helps to choose between the first or the second construction.
363  If your trabslation file is configured with a theashold of 1,
364  indicating that if n > 1 must choose the second construction,
365  the plural versin will be choosed, otherwise, it will choose the
366  singular form (the fisrt one).
367  */
368 #define TE_TR_PLURAL(message1, message2, n) TE_GENERAL_TR_PLURAL(TERRALIB_TEXT_DOMAIN, message1, message2, n)
369 
370 //@}
371 
372 #endif // __TERRALIB_COMMON_INTERNAL_TRANSLATOR_H
373 
Configuration flags for the TerraLib Common Runtime module.
Template support for singleton pattern.
#define TECOMMONEXPORT
You can use this macro in order to export/import classes and functions from this module.
Definition: Config.h:68