index.lxp@lxpwrap=c8212_252ehtm.htm
来自「GUI Programming with Python」· HTM 代码 · 共 634 行
HTM
634 行
<table border="0" cellspacing="0" cellpadding="3" width="100%"><tr><td> <div align="center" id="bldcontent"> <a href="../default.htm"><img src="../images/opendocs.png" width="63" height="76" border="0"></a> <br> <div class="symbol">Your OpenSource Publisher™</div> </div> </td></tr></table> <div align="center" class="author"> <a href="../products.lxp">Products</a> | <a href="../wheretobuy.lxp">Where to buy</a> | <a href="../bookstore.lxp">Retailers</a> | <a href="../faq.lxp">FAQ</a> | <a href="../writeforus.lxp">Write for Us.</a> | <a href="#contact">Contact Us.</a> </div> <table border="0" cellspacing="3" cellpadding="0" width="100%"><tr><td width="100%"> <div class="content"> <table border="0" cellspacing="2" cellpadding="0" width="100%"><tr><td width="100%"> <div align="center"><H4 CLASS="AUTHOR"><A NAME="AEN5">Boudewijn Rempt</A><br><a href="../../https@secure.linuxports.com/opendocs/default.htm"><img src=odpyqt125.png></a><br>ISBN: 0-97003300-4-4<br><a href="../../https@secure.linuxports.com/opendocs/default.htm">Available from bookstores everywhere or you can order it here.</a><p>You can download the source files for the book <a href="pyqtsrc.tgz">(code / eps) here.</a><hr></div> <HTML><HEAD><TITLE>Internationalizing an Application</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.72"><LINKREL="HOME"TITLE="GUI Programming with Python: QT Edition"HREF="book1.htm"><LINKREL="UP"TITLE="Creating real applications with PyQt"HREF="p4627.htm"><LINKREL="PREVIOUS"TITLE="Conclusion"HREF="x8207.htm"><LINKREL="NEXT"TITLE="Delivering your Application"HREF="c8349.htm"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GUI Programming with Python: QT Edition</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><A accesskey="P" href="index.lxp@lxpwrap=x8207_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=c8349_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1>Chapter 25. Internationalizing an Application</A></H1><P>For more than a century people have been uttering the platitude that the world is getting smaller all the time. That's nonsense: it's getting bigger. Although most computer users are still able to work with English-only applications, even speakers of <SPAN><ICLASS="EMPHASIS">really</I></SPAN> obscure languages, like Limbu, own computers and would like some applications in their own language.</P><P>An open-source effort like KDE offers more-or-less complete translations of the entire desktop, including all applications in dozens of languages. And, for a consideration, you can get a version of Windows in your own language, too, even if that language is Basque.</P><P>Of course, there are other aspects to the internationalization of an application, like date and number formats, currency, keyboard, preferred dialog layout and so on. Some of these aspects are handled by Qt - like reversing the dialog layout if the current script is right-to-left. Others, like the date and number formats are handled by Python's <TTCLASS="FILENAME">locale</TT> module - which is alas severely underdocumented.</P><P>Translating texts on screen can be handled either by PyQt - using the <TTCLASS="CLASSNAME">QTranslator</TT> class, or by Python itself - using the <TTCLASS="FILENAME">gettext</TT> module. PyQt's <TTCLASS="CLASSNAME">QTranslator</TT> is far more convenient in use, but <TTCLASS="FILENAME">gettext</TT> is based on the wide-spread GNU gettext library, which is also used by KDE for its translations.</P><DIVCLASS="SECT1"><H1CLASS="SECT1">Translating screen texts</A></H1><P>The first task is to surround all translatable text with the method <TTCLASS="FUNCTION">self.tr()</TT> - every <TTCLASS="CLASSNAME">QObject</TT> - derived class has that method. You don't have to do that manually with designs you have generated with the Designer module or <SPANCLASS="APPLICATION">Qt燚esigner</SPAN>. However, for Kalam, it's a fair bit of work - I'll only show a fragment here:</P><PRECLASS="PROGRAMLISTING"># fragment from kalamapp.py ... def initActions(self): self.actions = {} self.actions["fileNew"] = \ QAction(self.tr("New"), QIconSet(QPixmap(filenew)), self.tr("&New"), QAccel.stringToKey(self.tr("CTRL+N", "File|New")) self) self.connect(self.actions["fileNew"], SIGNAL("activated()"), self.slotFileNew) self.actions["fileOpen"] = \ QAction(self.tr("Open"), QIconSet(QPixmap(fileopen)), self.tr("&Open"), QAccel.stringToKey(self.tr("CTRL+O", "File|Open")), self) self.connect(self.actions["fileOpen"], SIGNAL("activated()"), self.slotFileOpen) ... </PRE><P>You must not only mark all text that will appear on screen, but also all accelerator keys, otherwise translators won't be able to translate them. The extra argument to <TTCLASS="FUNCTION">tr()</TT> gives the translator some extra context.</P><P>The <TTCLASS="FUNCTION">tr()</TT> serves two purposes: at first, it used as a recognition point for a small utility that extracts the strings to create message catalogs - files full of translatable text that you can send your Limbu speaking friends to translate for you.</P><P>Secondly, when you run the application, <TTCLASS="FUNCTION">tr()</TT> looks in a message database to find the right string. This is a very fast operation, so you don't have to worry about performance loss.</P><P>After you've marked all translatable strings, you can use a utility to generate translatable message files. Qt's utility—either <BCLASS="COMMAND">lupdate</B> or <BCLASS="COMMAND">findtr</B>—can only work with strings marked with <TTCLASS="FUNCTION">tr()</TT>, and only with double-quoted strings.</P><P>There is a significant, though quite esoteric, difference between the way Qt2 and Qt3 handle the <TTCLASS="FUNCTION">tr()</TT>. This means that when you use a version of PyQt designed to work with Qt 2, the <TTCLASS="FUNCTION">tr()</TT> doesn't work out of the box. You need to add a <TTCLASS="FUNCTION">tr()</TT> to all your classes that calls <TTCLASS="FUNCTION">qApp.translate()</TT>. This is what is done in the current <SPANCLASS="APPLICATION">Kalam</SPAN> code, because I wrote and developed the book using PyQt 2.5.</P><P>Another important difference: in Qt 3, you can also use <TTCLASS="FUNCTION">trUtf8()</TT>, if the source text is in the utf-8 encoding. That means that if your translators produce utf-8 encoded files, instead of plain two-byte Unicode text, you should use this function, instead of <TTCLASS="FUNCTION">tr()</TT>. With PyQt 3 for Qt 3, <TTCLASS="FUNCTION">trUtf8*()</TT> will be used automatically by <BCLASS="COMMAND">pyuic</B>.</P><P>You can also tell <SPANCLASS="APPLICATION">pyuic</SPAN> to use another function instead of <TTCLASS="FUNCTION">tr()</TT> - for instance, the Python pygettext.py default <TTCLASS="FUNCTION">_()</TT>. If you do that, with the command:</P><PRECLASS="SCREEN">pyuic -tr _ frmsettings.ui </PRE><P>there will be one important difference: by default, the translation function <TTCLASS="FUNCTION">tr()</TT> has class-local scope, i.e. it is prefixed with <TTCLASS="VARNAME">self</TT>. But a custom translation function has global scope - exactly what you need for the Python implementation of gettext.</P><P>So, you can either do:</P><PRECLASS="SCREEN">boud@calcifer:~/doc/pyqt/ch19/kalam > pygettext.py --keyword=tr kalamapp.py </PRE><P>Which creates a file called <TTCLASS="FILENAME">messages.pot</TT>, or:</P><PRECLASS="SCREEN">boud@calcifer:~/doc/pyqt/ch19/kalam > findtr kalamapp.py </PRE><P>The resulting files are almost identical - except for the minor detail of order. You should make a copy of these files for every language you need a translation for, and send them to your translators. They can use any editor, or a specialised application like <SPANCLASS="APPLICATION">KBabel</SPAN> to translate the text, and send it back in the form of a translated <TTCLASS="FILENAME">.pot</TT> file.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>KBabel</P></DIV></P></DIV><P>The result can be compiled to <TTCLASS="FILENAME">.mo</TT> files using the <TTCLASS="FILENAME">msgfmt.py</TT> utility which should hide somewhere in you Python installation.</P><P>Finally, you can use these message catalog by loading it and installing a global function <TTCLASS="FUNCTION">_()</TT>. (That should have been the function you used to mark your strings):</P><PRECLASS="PROGRAMLISTING">import gettextgettext.install('kalam') </PRE><P>Or for message catalogs in the Unicode encoding:</P><PRECLASS="PROGRAMLISTING">import gettextgettext.install('kalam', '/usr/share/locale', unicode=1) </PRE><P>Here, the path should point to a locale directory where all message files can be found.</P><P>If you are working with Qt 3.0, you can also use a new tool: <SPANCLASS="APPLICATION">Qt Linguist</SPAN>. This extracts the messages to a special, xml-based, format, and you can create message catalogs with a nice GUI frontend.</P><P>To use <SPANCLASS="APPLICATION">Qt Linguist</SPAN>, you need to make a Qt project file containing the following text:</P><PRECLASS="SCREEN">SOURCES = configtest.py \dlgfindreplace.py \dlgsettings.py \docmanager.py \docmanagertest.py \edmund.py \frmfindreplace.py \frmsettings.py \kalamapp.py \kalamconfig.py \kalamdoc.py \kalamview.py \macromanager.py \macromanagertest.py \main.py \resources.py \sitecustomize.py \startup.py TRANSLATIONS = kalam_nl.ts </PRE><P>And run the following command:</P><PRECLASS="SCREEN">boud@calcifer:~/doc/pyqt/ch19/kalam > lupdate kalam.pro </PRE><P>After spewing out a lot of warnings (this tool expects C++, not python) a file in xml format is created which you can edit with an editor or with <SPANCLASS="APPLICATION">Qt燣inguist</SPAN>.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The Qt Linguist screen</P></DIV></P></DIV><P>If the translator is finished, he or she can choose "release" in the menubar and generate a <TTCLASS="FILENAME">.qm</TT> message catalog.</P><P>Using this catalog in your application is a simple matter of installing the appropriate translator:</P><DIVCLASS="EXAMPLE"></A><P><B>Example 25-1. Installing the translator</B></P><PRECLASS="PROGRAMLISTING">#!/usr/bin/env python"""main.py - application startercopyright: (C) 2001, Boudewijn Remptemail: boud@rempt.xs4all.nl"""import sys, localefrom qt import *from kalamapp import KalamAppfrom kalamdoc import KalamDocfrom kalamview import KalamViewimport kalamconfigfrom resources import TRUE, FALSEdef main(args): app=QApplication(args) translator = QTranslator(app) translator.load("kalam_" + locale.getlocale()[0] + ".qm", kalamconfig.get("libdir",".")) app.installTranslator(translator) kalam = KalamApp() app.setMainWidget(kalam) kalam.show() if len(args) > 1: for arg in args[1:]: document=KalamDoc() document.open(arg) kalam.docManager.addDocument(document, KalamView) app.exec_loop() if __name__=="__main__": main(sys.argv) </PRE></DIV><P>Two remarks: note how we use the <TTCLASS="FILENAME">locale</TT> module to determine the language of the user. This returns a tuple containing a language code and a character set that correspond the user locale, as set by the operating system: <TTCLASS="VARNAME">['en_US', 'ISO8859-1']</TT>. If you always use the language code as the second part for your filename, then Qt will be able to determine which translation file to load.</P><P>Note also that the location of that message file is determined by a configuration option. Standard Unix <TTCLASS="FILENAME">.mo</TT> files tend to go into <TTCLASS="FILENAME">/usr/share/locale/</TT>, but there is no corresponding standard for Qt <TTCLASS="FILENAME">.qm</TT> messages, and you might as well put those in the application installation directory. Where that is, will be determined in the next chapter.</P></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><A accesskey="P" href="index.lxp@lxpwrap=x8207_252ehtm.htm">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="H" href="index.lxp@lxpwrap=book1_252ehtm">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><A accesskey="N" href="index.lxp@lxpwrap=c8349_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Conclusion</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=p4627_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Delivering your Application</TD></TR></TABLE></DIV></BODY></HTML> </td> </tr> </table> </td> </tr> </table>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?