大数跨境
0
0

【麒麟在线讲堂】浅谈 KF5 国际化

【麒麟在线讲堂】浅谈 KF5 国际化 优麒麟
2021-02-02
2
导读:简要介绍一下 KF5 框架下国际化 KI18n 的实现。

引言

基于增加与软件产品交互的良好性,以及更便于软件产品的使用及推广,国际化成为了满足以上条件的基本要素之一。今日,笔者角度,以己拙见,简要介绍一下KF5框架下国际化 KI18n的实现。

KF5KDE Framework 5 的简体缩写,是开源桌面KDE发行的第五版框架,其中KI18n作为其国际化模块封装其中。i18n为英文 internationalization 取首位字母in,以18代替中间被省略的18个字符,用以代表国际化的意思,与之类似的,l10n代表localization,即本地化的含义。而 KI18n 国际话的实现其实就是依托于Linux 系统下基于GUN gettext的本地化实现。

本文以cmake 软件工程为例,浅谈下如何在自己的软件产品中使用KI18n 国际化,以及如何使用Linux本地化替代KI18n国际化的实现方法。

本地化介绍

本地化通常为将翻译文件(.po)文件编译为供软件程序加载的二进制文件(.mo),实现根据本地语言自动调用翻译的二进制文件,进而翻译软件中文字。

Linux下,GUN利用gettext命令生成翻译文件的模板(.pot)文件,可通过复制模板或msginit命令等方法生成翻译文件,其中msginit命令会对模板通用部分进行补充后在本地生成翻译文件。自动填充内容对比下图:

图:本地化模板文件(图左) 对比 本地化翻译文件(图右)

我们可以看到,翻译(.po)文件是msgidmsgstr 一一对应的,其中msgid为翻译的标识文本,msgstr为翻译后的文本,软件产品中通过对标识文本的读取,根据语言码、国家码及编码获取对应翻译文件中的msgstr,进而实现本地化语言的展示输出。

但是,由于翻译文件属于源文本文件,软件产品如何实现对翻译文件的读取呢?当然不可能利用文本IO方法读取了,所以最后,利用msgfmt命令将翻译(.po)文件编译为二进制(.mo)文件,供软件产品调用,软件产品根据本地语言码,国家码及编码调用对应的二进制文件,实现本地化语言翻译的实现。

KI18n的使用

软件产品若希望使用KI18n国际化框架,需要在cmake列表中添加find_package(KF5I18n NO_MODULE)找到KI18n包,并利用语句target_link_libraries(yourAPP KF5::I18n)将KI18n动态库引入到自己的软件工程中。若使用qt工程研发,在工程.pro文件中需要添加 QT += KI18n

在编码中,需要在程序中需要被翻译前的位置,利用如下语句引入自己的翻译文件:



KLocalizedString::setApplicationDomain("yourPO");

其具体使用方法可参考用户手册,地址为:


https://api.kde.org/frameworks/ki18n/html/prg_guide.html#link_prog

其中头文件<KLocalizedString>包含具体翻译实现方法


inline QString i18n(const char *text)

等等,其深层次都是对KF5KI18n等翻译函数的封装,由此,在生成对应翻译模板(.pot)文件时,关键key的选择可包含如下信息:


i18n,i18nc, i18np, i18ncp, tr2i18n, I18N_NOOP,I18N_NOOP2, aliasLocale, ki18n, ki18nc, ki18np, ki18ncp等。

生成翻译模板文件(.pot)可参考如下脚本:


#!/bin/sh
BASEDIR="yourPath"  # root of translatable sources
PROJECT="yourName"  # project name
WDIR=`pwd`      # working dir

echo "Preparing rc files"
cd ${BASEDIR}
# we use simple sorting to make sure the lines do not jump around too much from system to system
find . -name '*.rc' -o -name '*.ui' -o -name '*.kcfg' | sort > ${WDIR}/rcfiles.list
xargs --arg-file=${WDIR}/rcfiles.list extractrc > ${WDIR}/rc.cpp
# additional string for KAboutData
echo 'i18nc("NAME OF TRANSLATORS","Your names");' >> ${WDIR}/rc.cpp
echo 'i18nc("EMAIL OF TRANSLATORS","Your emails");' >> ${WDIR}/rc.cpp
cd ${WDIR}
echo "Done preparing rc files"

echo "Extracting messages"
cd ${BASEDIR}
# see above on sorting
find . -name '*.cpp' -o -name '*.h' -o -name '*.c' | sort > ${WDIR}/infiles.list
echo "rc.cpp" >> ${WDIR}/infiles.list
cd ${WDIR}
xgettext --from-code=UTF-8 -C -kde -ci18n -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 -ktr2i18n:1 \
    -kI18N_NOOP:1 -kI18N_NOOP2:1c,2 -kaliasLocale -kki18n:1 -kki18nc:1c,2 -kki18np:1,2 -kki18ncp:1c,2,3 \
    --files-from=infiles.list -D ${BASEDIR} -D ${WDIR} -o ${PROJECT}.pot || { echo "error while calling xgettext. aborting."; exit 1; }
echo "Done extracting messages"

echo "Merging translations"
catalogs=`find . -name '*.po'`
for cat in $catalogs; do
  echo $cat
  msgmerge -o $cat.new $cat ${PROJECT}.pot
  mv $cat.new $cat
done
echo "Done merging translations"

echo "Cleaning up"
cd ${WDIR}
rm rcfiles.list
rm infiles.list
rm rc.cpp
echo "Done"


KI18n的替换方案

由前文可知,KI18n的实现是基于Linux GUN的本地化,由此,我们是否完全可以用Linux GUN的本地化方法来替代KI18n的实现?让我们开始做一下实验。

首先,我们需要引入Linux GUN本地化的头文件<libintl>,主要使用


extern char *gettext (const char *__msgid) __THROW __attribute_format_arg__ (1);

函数,来实现对二进制翻译文件内容的读取。

其次,我们需要指定去哪里寻找编译后的翻译文件,即域(domain),需要用到



extern char *bindtextdomain (const char *__domainname, const char *__dirname) __THROW;

函数来对域与域所在路径进行绑定,其中__domainname指的为翻译的二进制文件(.mo)的名称,即域,__dirname为翻译的二进制文件(.mo)所有在路径,即install的路径。

最后,需要在调用gettext前之前,对翻译域(domain)的确认,此时要用到



extern char *textdomain (const char *__domainname) __THROW;

函数,__domainname指的为翻译的二进制文件(.mo)的名称,即域,如果__domainname传入为NULL,该函数会返回当前默认的域的名称,如果传入参数为””(即空字符串),则表示重置域为messages

接下来,就是见证奇迹的时刻,请您自己动手,举一反三,实现自己软件产品的国际化吧。



往期精选 | Selection in the past

【2021纳新】优麒麟社区欢迎你的加入!

告别2020,迎接2021—优麒麟未来可期
CrossOver正式版来了,微信、QQ上架麒麟软件商店!


↓↓↓  点击下方“阅读原文”,查看优麒麟国际排名~

【声明】内容源于网络
0
0
优麒麟
优麒麟公众账号,用于发布优麒麟(UKylin)官方认可的信息。
内容 232
粉丝 0
优麒麟 优麒麟公众账号,用于发布优麒麟(UKylin)官方认可的信息。
总阅读103
粉丝0
内容232