| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \section{\module{gettext} --- | 
					
						
							|  |  |  |          Multilingual internationalization services} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \declaremodule{standard}{gettext} | 
					
						
							|  |  |  | \modulesynopsis{Multilingual internationalization services.} | 
					
						
							| 
									
										
										
										
											2001-01-15 17:08:45 +00:00
										 |  |  | \moduleauthor{Barry A. Warsaw}{barry@digicool.com} | 
					
						
							|  |  |  | \sectionauthor{Barry A. Warsaw}{barry@digicool.com} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The \module{gettext} module provides internationalization (I18N) and | 
					
						
							|  |  |  | localization (L10N) services for your Python modules and applications. | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | It supports both the GNU \code{gettext} message catalog API and a | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | higher level, class-based API that may be more appropriate for Python | 
					
						
							|  |  |  | files.  The interface described below allows you to write your | 
					
						
							|  |  |  | module and application messages in one natural language, and provide a | 
					
						
							|  |  |  | catalog of translated messages for running under different natural | 
					
						
							|  |  |  | languages. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some hints on localizing your Python modules and applications are also | 
					
						
							|  |  |  | given. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsection{GNU \program{gettext} API} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The \module{gettext} module defines the following API, which is very | 
					
						
							|  |  |  | similar to the GNU \program{gettext} API.  If you use this API you | 
					
						
							|  |  |  | will affect the translation of your entire application globally.  Often | 
					
						
							|  |  |  | this is what you want if your application is monolingual, with the choice | 
					
						
							|  |  |  | of language dependent on the locale of your user.  If you are | 
					
						
							|  |  |  | localizing a Python module, or if your application needs to switch | 
					
						
							|  |  |  | languages on the fly, you probably want to use the class-based API | 
					
						
							|  |  |  | instead. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \begin{funcdesc}{bindtextdomain}{domain\optional{, localedir}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | Bind the \var{domain} to the locale directory | 
					
						
							|  |  |  | \var{localedir}.  More concretely, \module{gettext} will look for | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | binary \file{.mo} files for the given domain using the path (on \UNIX): | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \file{\var{localedir}/\var{language}/LC_MESSAGES/\var{domain}.mo}, | 
					
						
							|  |  |  | where \var{languages} is searched for in the environment variables | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \envvar{LANGUAGE}, \envvar{LC_ALL}, \envvar{LC_MESSAGES}, and | 
					
						
							|  |  |  | \envvar{LANG} respectively. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If \var{localedir} is omitted or \code{None}, then the current binding | 
					
						
							|  |  |  | for \var{domain} is returned.\footnote{ | 
					
						
							| 
									
										
										
										
											2001-07-06 19:28:48 +00:00
										 |  |  |         The default locale directory is system dependent; for example, | 
					
						
							|  |  |  |         on RedHat Linux it is \file{/usr/share/locale}, but on Solaris | 
					
						
							|  |  |  |         it is \file{/usr/lib/locale}.  The \module{gettext} module | 
					
						
							|  |  |  |         does not try to support these system dependent defaults; | 
					
						
							|  |  |  |         instead its default is \file{\code{sys.prefix}/share/locale}. | 
					
						
							|  |  |  |         For this reason, it is always best to call | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  |         \function{bindtextdomain()} with an explicit absolute path at | 
					
						
							|  |  |  |         the start of your application.} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \begin{funcdesc}{textdomain}{\optional{domain}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | Change or query the current global domain.  If \var{domain} is | 
					
						
							|  |  |  | \code{None}, then the current global domain is returned, otherwise the | 
					
						
							|  |  |  | global domain is set to \var{domain}, which is returned. | 
					
						
							|  |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{funcdesc}{gettext}{message} | 
					
						
							|  |  |  | Return the localized translation of \var{message}, based on the | 
					
						
							|  |  |  | current global domain, language, and locale directory.  This function | 
					
						
							|  |  |  | is usually aliased as \function{_} in the local namespace (see | 
					
						
							|  |  |  | examples below). | 
					
						
							|  |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{funcdesc}{dgettext}{domain, message} | 
					
						
							|  |  |  | Like \function{gettext()}, but look the message up in the specified | 
					
						
							|  |  |  | \var{domain}. | 
					
						
							|  |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note that GNU \program{gettext} also defines a \function{dcgettext()} | 
					
						
							|  |  |  | method, but this was deemed not useful and so it is currently | 
					
						
							|  |  |  | unimplemented. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Here's an example of typical usage for this API: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | gettext.bindtextdomain('myapplication', '/path/to/my/language/directory') | 
					
						
							|  |  |  | gettext.textdomain('myapplication') | 
					
						
							|  |  |  | _ = gettext.gettext | 
					
						
							|  |  |  | # ... | 
					
						
							|  |  |  | print _('This is a translatable string.') | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsection{Class-based API} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The class-based API of the \module{gettext} module gives you more | 
					
						
							|  |  |  | flexibility and greater convenience than the GNU \program{gettext} | 
					
						
							|  |  |  | API.  It is the recommended way of localizing your Python applications and | 
					
						
							|  |  |  | modules.  \module{gettext} defines a ``translations'' class which | 
					
						
							|  |  |  | implements the parsing of GNU \file{.mo} format files, and has methods | 
					
						
							|  |  |  | for returning either standard 8-bit strings or Unicode strings. | 
					
						
							|  |  |  | Translations instances can also install themselves in the built-in | 
					
						
							|  |  |  | namespace as the function \function{_()}. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | \begin{funcdesc}{find}{domain\optional{, localedir\optional{,  | 
					
						
							|  |  |  |                         languages\optional{, all}}}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | This function implements the standard \file{.mo} file search | 
					
						
							|  |  |  | algorithm.  It takes a \var{domain}, identical to what | 
					
						
							| 
									
										
										
										
											2001-10-18 19:41:48 +00:00
										 |  |  | \function{textdomain()} takes.  Optional \var{localedir} is as in | 
					
						
							|  |  |  | \function{bindtextdomain()}  Optional \var{languages} is a list of | 
					
						
							|  |  |  | strings, where each string is a language code. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | If \var{localedir} is not given, then the default system locale | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | directory is used.\footnote{See the footnote for | 
					
						
							|  |  |  | \function{bindtextdomain()} above.}  If \var{languages} is not given, | 
					
						
							|  |  |  | then the following environment variables are searched: \envvar{LANGUAGE}, | 
					
						
							|  |  |  | \envvar{LC_ALL}, \envvar{LC_MESSAGES}, and \envvar{LANG}.  The first one | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | returning a non-empty value is used for the \var{languages} variable. | 
					
						
							| 
									
										
										
										
											2001-10-18 19:41:48 +00:00
										 |  |  | The environment variables should contain a colon separated list of | 
					
						
							|  |  |  | languages, which will be split on the colon to produce the expected | 
					
						
							|  |  |  | list of language code strings. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | \function{find()} then expands and normalizes the languages, and then | 
					
						
							|  |  |  | iterates through them, searching for an existing file built of these | 
					
						
							|  |  |  | components: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \file{\var{localedir}/\var{language}/LC_MESSAGES/\var{domain}.mo} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The first such file name that exists is returned by \function{find()}. | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | If no such file is found, then \code{None} is returned. If \var{all} | 
					
						
							|  |  |  | is given, it returns a list of all file names, in the order in which | 
					
						
							|  |  |  | they appear in the languages list or the environment variables. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \begin{funcdesc}{translation}{domain\optional{, localedir\optional{, | 
					
						
							| 
									
										
										
										
											2002-01-11 06:33:28 +00:00
										 |  |  |                               languages\optional{,  | 
					
						
							|  |  |  |                               class_,\optional{fallback}}}}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | Return a \class{Translations} instance based on the \var{domain}, | 
					
						
							|  |  |  | \var{localedir}, and \var{languages}, which are first passed to | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | \function{find()} to get a list of the | 
					
						
							|  |  |  | associated \file{.mo} file paths.  Instances with | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | identical \file{.mo} file names are cached.  The actual class instantiated | 
					
						
							|  |  |  | is either \var{class_} if provided, otherwise | 
					
						
							|  |  |  | \class{GNUTranslations}.  The class's constructor must take a single | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | file object argument.   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If multiple files are found, later files are used as fallbacks for | 
					
						
							|  |  |  | earlier ones. To allow setting the fallback, \function{copy.copy} | 
					
						
							|  |  |  | is used to clone each translation object from the cache; the actual | 
					
						
							|  |  |  | instance data is still shared with the cache. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If no \file{.mo} file is found, this function raises | 
					
						
							|  |  |  | \exception{IOError} if \var{fallback} is false (which is the default), | 
					
						
							|  |  |  | and returns a \class{NullTranslations} instance if \var{fallback} is | 
					
						
							|  |  |  | true. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \begin{funcdesc}{install}{domain\optional{, localedir\optional{, unicode}}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | This installs the function \function{_} in Python's builtin namespace, | 
					
						
							|  |  |  | based on \var{domain}, and \var{localedir} which are passed to the | 
					
						
							|  |  |  | function \function{translation()}.  The \var{unicode} flag is passed to | 
					
						
							|  |  |  | the resulting translation object's \method{install} method. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As seen below, you usually mark the strings in your application that are | 
					
						
							| 
									
										
										
										
											2001-07-06 19:28:48 +00:00
										 |  |  | candidates for translation, by wrapping them in a call to the | 
					
						
							|  |  |  | \function{_()} function, like this: | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | print _('This string will be translated.') | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For convenience, you want the \function{_()} function to be installed in | 
					
						
							|  |  |  | Python's builtin namespace, so it is easily accessible in all modules | 
					
						
							|  |  |  | of your application.   | 
					
						
							|  |  |  | \end{funcdesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{The \class{NullTranslations} class} | 
					
						
							|  |  |  | Translation classes are what actually implement the translation of | 
					
						
							|  |  |  | original source file message strings to translated message strings. | 
					
						
							|  |  |  | The base class used by all translation classes is | 
					
						
							|  |  |  | \class{NullTranslations}; this provides the basic interface you can use | 
					
						
							|  |  |  | to write your own specialized translation classes.  Here are the | 
					
						
							|  |  |  | methods of \class{NullTranslations}: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \begin{methoddesc}[NullTranslations]{__init__}{\optional{fp}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | Takes an optional file object \var{fp}, which is ignored by the base | 
					
						
							|  |  |  | class.  Initializes ``protected'' instance variables \var{_info} and | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | \var{_charset} which are set by derived classes, as well as \var{_fallback}, | 
					
						
							|  |  |  | which is set through \method{add_fallback}.  It then calls | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \code{self._parse(fp)} if \var{fp} is not \code{None}. | 
					
						
							|  |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{methoddesc}[NullTranslations]{_parse}{fp} | 
					
						
							|  |  |  | No-op'd in the base class, this method takes file object \var{fp}, and | 
					
						
							|  |  |  | reads the data from the file, initializing its message catalog.  If | 
					
						
							|  |  |  | you have an unsupported message catalog file format, you should | 
					
						
							|  |  |  | override this method to parse your format. | 
					
						
							|  |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | \begin{methoddesc}{NullTranslations}{add_fallback}{fallback} | 
					
						
							|  |  |  | Add \var{fallback} as the fallback object for the current translation | 
					
						
							|  |  |  | object. A translation object should consult the fallback if it cannot | 
					
						
							|  |  |  | provide a translation for a given message. | 
					
						
							|  |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \begin{methoddesc}[NullTranslations]{gettext}{message} | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | If a fallback has been set, forward \method{gettext} to the fallback. | 
					
						
							|  |  |  | Otherwise, return the translated message.  Overridden in derived classes. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{methoddesc}[NullTranslations]{ugettext}{message} | 
					
						
							| 
									
										
										
										
											2002-01-11 06:58:49 +00:00
										 |  |  | If a fallback has been set, forward \method{ugettext} to the fallback. | 
					
						
							|  |  |  | Otherwise, return the translated message as a Unicode string. | 
					
						
							|  |  |  | Overridden in derived classes. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{methoddesc}[NullTranslations]{info}{} | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | Return the ``protected'' \member{_info} variable. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{methoddesc}[NullTranslations]{charset}{} | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | Return the ``protected'' \member{_charset} variable. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \begin{methoddesc}[NullTranslations]{install}{\optional{unicode}} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | If the \var{unicode} flag is false, this method installs | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \method{self.gettext()} into the built-in namespace, binding it to | 
					
						
							|  |  |  | \samp{_}.  If \var{unicode} is true, it binds \method{self.ugettext()} | 
					
						
							|  |  |  | instead.  By default, \var{unicode} is false. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Note that this is only one way, albeit the most convenient way, to | 
					
						
							|  |  |  | make the \function{_} function available to your application.  Because it | 
					
						
							|  |  |  | affects the entire application globally, and specifically the built-in | 
					
						
							|  |  |  | namespace, localized modules should never install \function{_}. | 
					
						
							|  |  |  | Instead, they should use this code to make \function{_} available to | 
					
						
							|  |  |  | their module: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | t = gettext.translation('mymodule', ...) | 
					
						
							|  |  |  | _ = t.gettext | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This puts \function{_} only in the module's global namespace and so | 
					
						
							|  |  |  | only affects calls within this module. | 
					
						
							|  |  |  | \end{methoddesc} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{The \class{GNUTranslations} class} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The \module{gettext} module provides one additional class derived from | 
					
						
							|  |  |  | \class{NullTranslations}: \class{GNUTranslations}.  This class | 
					
						
							|  |  |  | overrides \method{_parse()} to enable reading GNU \program{gettext} | 
					
						
							|  |  |  | format \file{.mo} files in both big-endian and little-endian format. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It also parses optional meta-data out of the translation catalog.  It | 
					
						
							|  |  |  | is convention with GNU \program{gettext} to include meta-data as the | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | translation for the empty string.  This meta-data is in \rfc{822}-style | 
					
						
							|  |  |  | \code{key: value} pairs.  If the key \code{Content-Type} is found, | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | then the \code{charset} property is used to initialize the | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | ``protected'' \member{_charset} instance variable.  The entire set of | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | key/value pairs are placed into a dictionary and set as the | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | ``protected'' \member{_info} instance variable. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | If the \file{.mo} file's magic number is invalid, or if other problems | 
					
						
							|  |  |  | occur while reading the file, instantiating a \class{GNUTranslations} class | 
					
						
							|  |  |  | can raise \exception{IOError}. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The other usefully overridden method is \method{ugettext()}, which | 
					
						
							|  |  |  | returns a Unicode string by passing both the translated message string | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | and the value of the ``protected'' \member{_charset} variable to the | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | builtin \function{unicode()} function. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-07 18:55:08 +00:00
										 |  |  | \subsubsection{Solaris message catalog support} | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The Solaris operating system defines its own binary | 
					
						
							|  |  |  | \file{.mo} file format, but since no documentation can be found on | 
					
						
							|  |  |  | this format, it is not supported at this time. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{The Catalog constructor} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-07 18:55:08 +00:00
										 |  |  | GNOME\index{GNOME} uses a version of the \module{gettext} module by | 
					
						
							|  |  |  | James Henstridge, but this version has a slightly different API.  Its | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | documented usage was: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | cat = gettext.Catalog(domain, localedir) | 
					
						
							|  |  |  | _ = cat.gettext | 
					
						
							|  |  |  | print _('hello world') | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For compatibility with this older module, the function | 
					
						
							|  |  |  | \function{Catalog()} is an alias for the the \function{translation()} | 
					
						
							|  |  |  | function described above. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | One difference between this module and Henstridge's: his catalog | 
					
						
							|  |  |  | objects supported access through a mapping API, but this appears to be | 
					
						
							|  |  |  | unused and so is not currently supported. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsection{Internationalizing your programs and modules} | 
					
						
							|  |  |  | Internationalization (I18N) refers to the operation by which a program | 
					
						
							|  |  |  | is made aware of multiple languages.  Localization (L10N) refers to | 
					
						
							|  |  |  | the adaptation of your program, once internationalized, to the local | 
					
						
							|  |  |  | language and cultural habits.  In order to provide multilingual | 
					
						
							|  |  |  | messages for your Python programs, you need to take the following | 
					
						
							|  |  |  | steps: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{enumerate} | 
					
						
							|  |  |  |     \item prepare your program or module by specially marking | 
					
						
							|  |  |  |           translatable strings | 
					
						
							|  |  |  |     \item run a suite of tools over your marked files to generate raw | 
					
						
							|  |  |  |           messages catalogs | 
					
						
							|  |  |  |     \item create language specific translations of the message catalogs | 
					
						
							|  |  |  |     \item use the \module{gettext} module so that message strings are | 
					
						
							|  |  |  |           properly translated | 
					
						
							|  |  |  | \end{enumerate} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In order to prepare your code for I18N, you need to look at all the | 
					
						
							|  |  |  | strings in your files.  Any string that needs to be translated | 
					
						
							| 
									
										
										
										
											2001-07-06 19:28:48 +00:00
										 |  |  | should be marked by wrapping it in \code{_('...')} --- that is, a call | 
					
						
							|  |  |  | to the function \function{_()}.  For example: | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | filename = 'mylog.txt' | 
					
						
							|  |  |  | message = _('writing a log message') | 
					
						
							|  |  |  | fp = open(filename, 'w') | 
					
						
							|  |  |  | fp.write(message) | 
					
						
							|  |  |  | fp.close() | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | In this example, the string \code{'writing a log message'} is marked as | 
					
						
							|  |  |  | a candidate for translation, while the strings \code{'mylog.txt'} and | 
					
						
							|  |  |  | \code{'w'} are not. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-31 21:21:45 +00:00
										 |  |  | The Python distribution comes with two tools which help you generate | 
					
						
							|  |  |  | the message catalogs once you've prepared your source code.  These may | 
					
						
							|  |  |  | or may not be available from a binary distribution, but they can be | 
					
						
							|  |  |  | found in a source distribution, in the \file{Tools/i18n} directory. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The \program{pygettext}\footnote{Fran\c cois Pinard has | 
					
						
							|  |  |  | written a program called | 
					
						
							| 
									
										
										
										
											2000-09-13 12:04:47 +00:00
										 |  |  | \program{xpot} which does a similar job.  It is available as part of | 
					
						
							|  |  |  | his \program{po-utils} package at | 
					
						
							| 
									
										
										
										
											2001-01-31 21:21:45 +00:00
										 |  |  | \url{http://www.iro.umontreal.ca/contrib/po-utils/HTML}.} program | 
					
						
							|  |  |  | scans all your Python source code looking for the strings you | 
					
						
							|  |  |  | previously marked as translatable.  It is similar to the GNU | 
					
						
							|  |  |  | \program{gettext} program except that it understands all the | 
					
						
							|  |  |  | intricacies of Python source code, but knows nothing about C or C++ | 
					
						
							|  |  |  | source code.  You don't need GNU \code{gettext} unless you're also | 
					
						
							| 
									
										
										
										
											2001-07-06 19:28:48 +00:00
										 |  |  | going to be translating C code (such as C extension modules). | 
					
						
							| 
									
										
										
										
											2001-01-31 21:21:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | \program{pygettext} generates textual Uniforum-style human readable | 
					
						
							|  |  |  | message catalog \file{.pot} files, essentially structured human | 
					
						
							|  |  |  | readable files which contain every marked string in the source code, | 
					
						
							|  |  |  | along with a placeholder for the translation strings. | 
					
						
							|  |  |  | \program{pygettext} is a command line script that supports a similar | 
					
						
							|  |  |  | command line interface as \program{xgettext}; for details on its use, | 
					
						
							|  |  |  | run: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | pygettext.py --help | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Copies of these \file{.pot} files are then handed over to the | 
					
						
							|  |  |  | individual human translators who write language-specific versions for | 
					
						
							|  |  |  | every supported natural language.  They send you back the filled in | 
					
						
							|  |  |  | language-specific versions as a \file{.po} file.  Using the | 
					
						
							|  |  |  | \program{msgfmt.py}\footnote{\program{msgfmt.py} is binary | 
					
						
							|  |  |  | compatible with GNU \program{msgfmt} except that it provides a | 
					
						
							|  |  |  | simpler, all-Python implementation.  With this and | 
					
						
							|  |  |  | \program{pygettext.py}, you generally won't need to install the GNU | 
					
						
							|  |  |  | \program{gettext} package to internationalize your Python | 
					
						
							|  |  |  | applications.} program (in the \file{Tools/i18n} directory), you take the | 
					
						
							|  |  |  | \file{.po} files from your translators and generate the | 
					
						
							|  |  |  | machine-readable \file{.mo} binary catalog files.  The \file{.mo} | 
					
						
							|  |  |  | files are what the \module{gettext} module uses for the actual | 
					
						
							|  |  |  | translation processing during run-time. | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | How you use the \module{gettext} module in your code depends on | 
					
						
							|  |  |  | whether you are internationalizing your entire application or a single | 
					
						
							|  |  |  | module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{Localizing your module} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you are localizing your module, you must take care not to make | 
					
						
							|  |  |  | global changes, e.g. to the built-in namespace.  You should not use | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | the GNU \code{gettext} API but instead the class-based API.   | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Let's say your module is called ``spam'' and the module's various | 
					
						
							|  |  |  | natural language translation \file{.mo} files reside in | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \file{/usr/share/locale} in GNU \program{gettext} format.  Here's what | 
					
						
							|  |  |  | you would put at the top of your module: | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | t = gettext.translation('spam', '/usr/share/locale') | 
					
						
							|  |  |  | _ = t.gettext | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If your translators were providing you with Unicode strings in their | 
					
						
							|  |  |  | \file{.po} files, you'd instead do: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | t = gettext.translation('spam', '/usr/share/locale') | 
					
						
							|  |  |  | _ = t.ugettext | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{Localizing your application} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you are localizing your application, you can install the \function{_()} | 
					
						
							|  |  |  | function globally into the built-in namespace, usually in the main driver file | 
					
						
							|  |  |  | of your application.  This will let all your application-specific | 
					
						
							|  |  |  | files just use \code{_('...')} without having to explicitly install it in | 
					
						
							|  |  |  | each file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In the simple case then, you need only add the following bit of code | 
					
						
							|  |  |  | to the main driver file of your application: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | gettext.install('myapplication') | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | If you need to set the locale directory or the \var{unicode} flag, | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | you can pass these into the \function{install()} function: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | gettext.install('myapplication', '/usr/share/locale', unicode=1) | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{Changing languages on the fly} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If your program needs to support many languages at the same time, you | 
					
						
							|  |  |  | may want to create multiple translation instances and then switch | 
					
						
							|  |  |  | between them explicitly, like so: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | import gettext | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lang1 = gettext.translation(languages=['en']) | 
					
						
							|  |  |  | lang2 = gettext.translation(languages=['fr']) | 
					
						
							|  |  |  | lang3 = gettext.translation(languages=['de']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # start by using language1 | 
					
						
							|  |  |  | lang1.install() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ... time goes by, user selects language 2 | 
					
						
							|  |  |  | lang2.install() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ... more time goes by, user selects language 3 | 
					
						
							|  |  |  | lang3.install() | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsubsection{Deferred translations} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In most coding situations, strings are translated were they are coded. | 
					
						
							|  |  |  | Occasionally however, you need to mark strings for translation, but | 
					
						
							|  |  |  | defer actual translation until later.  A classic example is: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | animals = ['mollusk', | 
					
						
							|  |  |  |            'albatross', | 
					
						
							|  |  |  | 	   'rat', | 
					
						
							|  |  |  | 	   'penguin', | 
					
						
							|  |  |  | 	   'python', | 
					
						
							|  |  |  | 	   ] | 
					
						
							|  |  |  | # ... | 
					
						
							|  |  |  | for a in animals: | 
					
						
							|  |  |  |     print a | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Here, you want to mark the strings in the \code{animals} list as being | 
					
						
							|  |  |  | translatable, but you don't actually want to translate them until they | 
					
						
							|  |  |  | are printed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Here is one way you can handle this situation: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | def _(message): return message | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | animals = [_('mollusk'), | 
					
						
							|  |  |  |            _('albatross'), | 
					
						
							|  |  |  | 	   _('rat'), | 
					
						
							|  |  |  | 	   _('penguin'), | 
					
						
							|  |  |  | 	   _('python'), | 
					
						
							|  |  |  | 	   ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | del _ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ... | 
					
						
							|  |  |  | for a in animals: | 
					
						
							|  |  |  |     print _(a) | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This works because the dummy definition of \function{_()} simply returns | 
					
						
							|  |  |  | the string unchanged.  And this dummy definition will temporarily | 
					
						
							|  |  |  | override any definition of \function{_()} in the built-in namespace | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | (until the \keyword{del} command). | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | Take care, though if you have a previous definition of \function{_} in | 
					
						
							|  |  |  | the local namespace. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note that the second use of \function{_()} will not identify ``a'' as | 
					
						
							|  |  |  | being translatable to the \program{pygettext} program, since it is not | 
					
						
							|  |  |  | a string. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Another way to handle this is with the following example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{verbatim} | 
					
						
							|  |  |  | def N_(message): return message | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | animals = [N_('mollusk'), | 
					
						
							|  |  |  |            N_('albatross'), | 
					
						
							|  |  |  | 	   N_('rat'), | 
					
						
							|  |  |  | 	   N_('penguin'), | 
					
						
							|  |  |  | 	   N_('python'), | 
					
						
							|  |  |  | 	   ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ... | 
					
						
							|  |  |  | for a in animals: | 
					
						
							|  |  |  |     print _(a) | 
					
						
							|  |  |  | \end{verbatim} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In this case, you are marking translatable strings with the function | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \function{N_()},\footnote{The choice of \function{N_()} here is totally | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | arbitrary; it could have just as easily been | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  | \function{MarkThisStringForTranslation()}. | 
					
						
							|  |  |  | } which won't conflict with any definition of | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  | \function{_()}.  However, you will need to teach your message extraction | 
					
						
							|  |  |  | program to look for translatable strings marked with \function{N_()}. | 
					
						
							|  |  |  | \program{pygettext} and \program{xpot} both support this through the | 
					
						
							|  |  |  | use of command line switches. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \subsection{Acknowledgements} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following people contributed code, feedback, design suggestions, | 
					
						
							|  |  |  | previous implementations, and valuable experience to the creation of | 
					
						
							|  |  |  | this module: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | \begin{itemize} | 
					
						
							|  |  |  |     \item Peter Funk | 
					
						
							|  |  |  |     \item James Henstridge | 
					
						
							| 
									
										
										
										
											2000-08-30 04:19:20 +00:00
										 |  |  |     \item Marc-Andr\'e Lemburg | 
					
						
							| 
									
										
										
										
											2000-08-30 03:27:10 +00:00
										 |  |  |     \item Martin von L\"owis | 
					
						
							|  |  |  |     \item Fran\c cois Pinard | 
					
						
							|  |  |  |     \item Barry Warsaw | 
					
						
							|  |  |  | \end{itemize} |