您的位置:首页 > 编程语言 > Qt开发

Qt国际化(Q_DECLARE_TR_FUNCTIONS() 宏给非Qt类添加翻译支持,以前没见过QTextEncoder和QTextDecoder和QLibraryInfo::location()和QEvent::LanguageChange)

2016-02-01 20:02 489 查看
InternationalizationwithQt

应用程序的国际化就是使得程序能在国际间可用而不仅仅是在本国可用的过程。

RelevantQtClassesandAPIs

以下的类支持Qt的国际化。

QTextCodec

QTextDecoder

QTextEncoder

QTranslator

QLocale

LanguagesandWritingSystems

有时,国际化是比较简单的,例如,把美国的应用程序让澳大利亚或英国的用户可访问,只需要简单的改变拼写。但是,把美国的应用程序对日本用户可用,或者韩国的应用程序对德国人可用,不仅仅需要软件操作不同的语言,还需要使用不同的输入技术,不同的字符编码和显示规则。

对于开发者,Qt尽可能的把国际化简单化。Qt内置提供的所有的输入控制和文本绘制方法支持所有的语言。内置的字体引擎能同时正确和精美的显示来自各种不同的输入系统的文本。

Qt支持大多数现在用的语言,特别是:

·所有的东亚国家的语言(中文,日文和韩文)

·所有的西方国家的语言(使用拉丁文)

·阿拉伯语

·斯拉夫字母语言

·希腊语

·希伯来语

·泰国和老挝语

·所有不需要特殊处理的Unicode6.2编码的脚本

·孟加拉语

·缅甸语

·梵文

·吉吉拉特语

·果鲁穆奇语

·坎那达语

·高棉语

·马拉雅拉姆语

·泰米尔语

·泰卢固语

·藏语

以上列表都是被支持和在所有的平台上都能工作的,只要系统有渲染这些安装的输入系统的字体。

在Windows,Linux和Unix系统,使用字体配置,下面的语言也能支持:

·迪维希语

·叙利亚语

·西非书面语言

在MacOS系统,下面的语言也被支持:

·奥里雅语

·僧伽罗语

许多的书写系统表现出特殊的功能:

·特殊的自动换行形式:一些亚洲语言字之间没有空白,自动换行可以发生在任何字符的后面,比如中文,日文和韩文,或者在逻辑词边界的泰语。

·双向书写:阿拉伯语和希伯来语是从右到左书写的,除了数字和嵌入的英文单词是从左到右书写之外。

·非间距或变音符号(欧洲语言的口音或变音符号):一些语言比如越南语大量的使用这些符号,并且一些字符同时有超过一个标记来表明读音。

·连字:在特殊的语境,一些成对的字符被一些字结合的连字替换。常见的例子是,在美国和欧洲书记中使用的fl和fi的连字。

Qt视图照顾到以上列出的特殊的特性,你通常不用担心这些特性,只要你使用Qt的输入控制和Qt的显示控制。

支持这些书写系统对程序员是透明的,完全被封装在Qt'stextengine.。这意味着你在用特定的语言时不需要知道任何书写系统信息,除了以下几点:

·QPainter::drawText(intx,inty,constQString&str)把绘制的字符串的左边缘在给定的x,y参数的位置。这通常会给你左对齐的字符串。阿拉伯语和希伯来语的应用程序的字符串通常是右对齐的,所以对于这些语言需要用接收QRect的drawText()版本,这样才与语言一直。

·当你自己写文本输入控制时,用QTextLayout。在某些语言,宽度和形状会根据周围的字符而改变,这就是QTextLayout所考虑的。写输入控制通常需要知道一种特定的脚本使用方法的知识。通常最简单的方法是继承QLineEdit或QTextEdit.。

StepbyStep

用Qt写跨平台的国际化软件是一个温和,渐进的过程。在一些的阶段,你的软件可以变得国际化:

UseQStringforAllUser-VisibleText

由于QString内部使用了Unicode编码,世上的所有语言都能用熟悉的文本处理操作进行透明的处理。因为所有向用户显示文本的Qt函数都是以Qstring作为参数的,所有不存在从char*转换到QString的开销。

在程序员空间的字符串(如QObject名和文件格式文本)不需要用Qstring,传统的char*或QByteArray就足够了。

你可能没注意到你用Unicode编码:Qstring和Qchar就像用传统的C中的constchar*和char一样那么简单。

当进行隐式转换为QString是,源码中的char*被假定是用UTF-8编码。如果你的C字面值字符串用的是不同的编码,用QString::fromLatin1()或QTextCodec把它转换为Unicode编码的Qstring。

Usetr()forAllLiteralText

如果你的程序有用“”引用的向用户显示的文本,确保用QCoreApplication::translate()函数来处理它。要实现这一过程基本上都需要用QObject::tr().。例如:假设LoginWidget是QWidget:的子类:

LoginWidget::LoginWidget()

{

QLabel*label=newQLabel(tr("Password:"));

...

}


这个占了你可能写的99%的用户可见字符串。

如果引用的文本不在QObject子类的成员函数中,用一个适当的类的tr()函数或直接用QCoreApplication::translate()函数。

voidsome_global_function(LoginWidget*logwid)

{

QLabel*label=newQLabel(

LoginWidget::tr("Password:"),logwid);

}


voidsame_global_function(LoginWidget*logwid)

{

QLabel*label=newQLabel(

qApp->translate("LoginWidget","Password:"),logwid);

}


如果你需要翻译的文本完全在函数的外部,那么可以用这两个宏:QT_TR_NOOP()和QT_TRANSLATE_NOOP().。它们仅仅为以下介绍的lupdate工具提取的文本进行标记,宏只是扩展文本。

QT_TR_NOOP()的例子:

QStringFriendlyConversation::greeting(inttype)

{

staticconstchar*greeting_strings[]={

QT_TR_NOOP("Hello"),

QT_TR_NOOP("Goodbye")

};

returntr(greeting_strings[type]);

}


QT_TR_NOOP()的例子:

staticconstchar*greeting_strings[]={

QT_TRANSLATE_NOOP("FriendlyConversation","Hello"),

QT_TRANSLATE_NOOP("FriendlyConversation","Goodbye")

};


QStringFriendlyConversation::greeting(inttype)

{

returntr(greeting_strings[type]);

}


QStringglobal_greeting(inttype)

{

returnqApp->translate("FriendlyConversation",

greeting_strings[type]);

}


如果你用宏QT_NO_CAST_FROM_ASCII定义来编译软件禁止从constchar*到Qstring的转换,你就可能捕获任何漏掉的字符串。

UseQKeySequence()forAcceleratorValues

快捷键值如Ctrl+Q或Alt+F也需要翻译。如果你在程序中为“quit”退出用硬编码Qt::CTRL+Qt::Key_Q,转换器就不能重写它们。正确的做法是:

exitAct=newQAction(tr("E&xit"),this);

exitAct->setShortcuts(QKeySequence::Quit);


UseQString::arg()forDynamicText

QString::arg()提供简单的替换参数的方法:

voidFileCopier::showProgress(intdone,inttotal,

constQString¤tFile)

{

label.setText(tr("%1of%2filescopied.\nCopying:%3")

.arg(done)

.arg(total)

.arg(currentFile));

}


在有的语言中参数的顺序可能需要改变,实现这个只需要改变参数中%的顺序就好。例如:

QStrings1="%1of%2filescopied.Copying:%3";

QStrings2="Kopierernu%3.Avtotalt%2filerer%1kopiert.";


qDebug()<<s1.arg(5).arg(10).arg("somefile.txt");

qDebug()<<s2.arg(5).arg(10).arg("somefile.txt");


生成了正确的英语和挪威语的输出:

5of10filescopied.Copying:somefile.txt

Kopierernusomefile.txt.Avtotalt10filerer5kopiert.


ProduceTranslations

一旦你在整个程序中用了tr(),你可以在你的程序中开始对用户可见文本生成翻译。

翻译Qt程序需要三个步骤:

1.运行lupdate工具来提取Qt程序C++源代码中可以翻译的文本,生成给翻译器的一个消息文件(TS文件)。该工具识别tr()和以上提到的宏QT_TR*_NOOP()并生成TS文件。

2.用QtLinguist.为TS文件中的源文本提供翻译,因为TS文件是XML格式,你也可以手工进行编辑。

3.运行lrelease从TS文件中得到一个轻型的消息文件(QM文件),只适合最终用途。想象TS文件是源文件,QM文件是目标文件。翻译器编辑TS文件,但是程序的用户只需要QM文件。这些文件都是独立于平台和地域的。

典型的,你每次发布程序都需要重复这些步骤。Linguist工具尽可能重用之前的版本的翻译。

在运行lupdate之前,你应该准备工程文件。例如:

HEADERS=funnydialog.h\

wackywidget.h

SOURCES=funnydialog.cpp\

main.cpp\

wackywidget.cpp

FORMS=fancybox.ui

TRANSLATIONS=superapp_dk.ts\

superapp_fi.ts\

superapp_no.ts\

superapp_se.ts


当你运行lupdate或lrelease,时,你必须把工程文件名作为命令行的参数。

在这个例子中,支持四种语言:丹麦,芬兰,挪威和瑞典。如果你用qmake,lupdate通常不需要额外的工程文件。一旦你添加了TRANSLATIONS条目qmake工程文件就能正常工作。

在你的程序中,必须为用户的语言适当的调用QTranslator::load()装载翻译文件,并用QCoreApplication::installTranslator()进行安装。

linguist,lupdate和lrelease被安装到Qt安装的根目录中的bin子目录。点击QtLinguist的Help|Manual进入用户手册。它包含一个开始的教程。

Qt本身包含超过400个需要翻译成目标语言的字符串。你会找到很多个翻译文件,以及在QtTranslations模块中翻译成其他语言的模板。

典型的,你的程序的main()函数看起来像这样:

intmain(intargc,char*argv[])

{

QApplicationapp(argc,argv);


QTranslatorqtTranslator;

qtTranslator.load("qt_"+QLocale::system().name(),

QLibraryInfo::location(QLibraryInfo::TranslationsPath));

app.installTranslator(&qtTranslator);


QTranslatormyappTranslator;

myappTranslator.load("myapp_"+QLocale::system().name());

app.installTranslator(&myappTranslator);


...

returnapp.exec();

}


注意:用QLibraryInfo::location()来定位Qttranslations。开发者应该在运行时传递QLibraryInfo::TranslationsPath到这个函数而不是用程序的环境变量QTDIR来请求该该路径。

SupportforEncodings

QTextCodec类和QTextStream工具很容易的支持许多用户数据的输入输出编码。当程序启动时,当处理外部的8位数据,程序的语言环境奖觉得使用的8位编码。QTextCodec::codecForLocale()返回一个可以用来转换本地编码和Unicode的解码器。

程序偶尔需要除了默认8位编码之外的编码。例如,一个程序在CyrillicKOI8-R地区可能需要输出Cyrillic的ISO8859-5编码;可能的代码如下:

QStringstring=...;//someUnicodetext


QTextCodec*codec=QTextCodec::codecForName("ISO8859-5");

QByteArrayencodedString=codec->fromUnicode(string);


把Unicode转换为本地的8位编码,一个简便的方法是:QString::toLocal8Bit()函数返回这样的8位编码数据。另外的捷径是QString::toUtf8(),返回8位的UTF-8编码的文本。这个很好的保存了Unicode信息,如果文本完全是ASCII看起来像纯的ASCII文本。

其他的转换方法,有QString::fromUtf8()和QString::fromLocal8Bit()方便的函数,或者是通常代码,从ISO8859-5Cyrillic转换到Unicode的演示:

QByteArrayencodedString=...;//someISO8859-5encodedtext


QTextCodec*codec=QTextCodec::codecForName("ISO8859-5");

QStringstring=codec->toUnicode(encodedString);


UnicodeI/O应用来使全世界范围用户的文档可移植性最大化。由于用户可能需要处理已经存在的文档,有时它也需要支持其他编码。需要支持的最重要的额外编码就是QTextCodec::codecForLocale(),返回的。因为它是用户最可能用来与其他人或应用程序交互的。

Qt支持大多数本地最经常使用的编码。

有时对于不怎么经常使用的编码你可能需要写自己的QTextCodec子类。如果比较紧急,可以联系Qt技术支持团队或在Qt兴趣列表里找是否有人已经实现了对该编码的支持。

Localize

本地化是适应本地规则的过程,例如显示数据和时间用本地的首选格式。这样的本地化可以使用适当的tr()字符串达到。

voidClock::setTime(constQTime&time)

{

if(tr("AMPM")=="AMPM"){

//12-hourclock

}else{

//24-hourclock

}

}


在例子中,对于美国,判断为真并会进入12小时的分支。但是在欧洲翻译的结果会是其他所以进入23小时分支。

使用QLocale类对数字,日期,货币字符串进行本地化。

不建议本地化图片,选择适合所有地方的清晰的图标,而不是依据本地的双关语或伸展隐喻。例外的是向左向右图片对于阿拉伯和希伯来语本地化需要进行翻转。

DynamicTranslation

一些应用程序如QtLinguist,,当它们还在运行时必须支持转到用户设置的语言。要让Widgets意识到转换到安装的Qtranslators,重新实现widget的changeEvent()函数检查是否是LanguageChange事件,并用tr()函数更新显示文本。例如:

voidMyWidget::changeEvent(QEvent*event)

{

if(e->type()==QEvent::LanguageChange){

titleLabel->setText(tr("DocumentTitle"));

...

okPushButton->setText(tr("&OK"));

}else

QWidget::changeEvent(event);

}


其他所有的事件通过调用默认实现的函数。

安装的translators列表可能随着LocaleChange事件相应的改变,或应用程序可以提供一个接口运行用户改变当前的程序语言。

QWidget子类的默认事件处理响应QEvent::LanguageChange事件,必要时调用这个函数。

当用QCoreApplication::installTranslator()函数安装新的一个翻译时会发出LanguageChange事件。此外,其他程序组件也可以强制widget通过发出LanguageChange事件来更新它们自己。

TranslatingNon-QtClasses

有时有必要对不是继承QObject或用Q_OBJECT宏的类中的字符串支持国际化开启翻译功能。由于Qt在运行时翻译字符串基于它们关联的类和lupdate在源码中查找可以翻译的字符串,非Qt类必须用一种机制可以提供这些信息。

一种方法是用Q_DECLARE_TR_FUNCTIONS()宏给非Qt类添加翻译支持:

classMyClass

{

Q_DECLARE_TR_FUNCTIONS(MyClass)


public:

MyClass();

...

};


这使得该类可以用tr()函数翻译与该类相关联的字符串和使得lupdate可以在源码中查找可以翻译的字符串。

另外的方法:在特定的上下午中可以调用QCoreApplication::translate()函数,而且该函数可以被lupdate和QtLinguist.识别。

SystemSupport

在Qt运行的一些操作系统和windows系统仅仅是有限的支持Unicode。在下面的系统的支持的级别对Qt在这些平台上的支持有一定的影响,即使通常Qt程序不需要太关心平台限制:

Unix/X11

n语言环境导向的字体和输入方法,Qt隐藏了这些并提供了Unicode的输入输出。

n文件系统约定如UTF-8如今在Unix大部分变体默认使用。所有的Qt函数都接受Unicode,但是把文件名转换为本地的8位编码,这就是Unix的约定。

n文件的IO默认为当地的8位编码,在QTextStream与Unicode选项。

n一些老的Unix发布版本仅仅包含支持一些语言环境。例如,如果你有一个/usr/share/locale/ja_JP.EUC目录,这不意味着可以显示日文,你必须有安装的日文字体并且/usr/share/locale/ja_JP.EUC必须是完整的。为了达到最好的效果,从系统供应商那里获取完整的语言环境。

Linux

Qt提供全部的Unicode支持,包括输入方法,字体,剪贴板和拖放。

n在所有现代的Linux发布版文件系统通常用UTF-8编码,而且不会有问题。文件IO默认为UTF-8。

Windows

nQt提供全部的Unicode支持,包括输入方法,字体,剪贴板,拖放和文件名。

n文件IO默认为Latin1,与在QTextStream的Unicode选项。注意,一些windows程序不理解大端模式的Unicode文本文件即使这是在没有高级别协议的Unicode标准规定顺序。
http://blog.csdn.net/hai200501019/article/details/9192967
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: