时间:2021-05-25
gettext 是GNU 提供的一套 国际化与本地化 处理的相关函数库。大多数语言都有对应的gettext实现。本文主要使用jed 来实现gettext 一系列方法对应的功能。
pot/po文件
xgettext/msginit/msgmerge
多语言支持流程
安装gettext
langs-loader 加载语言文件
需要修改webpack.config.js文件在module->rules(webpack 2.0)下面添加loader规则:
{ test: /\.pot$/i, use: [ "json", { loader: 'langs', options: {isLoadAll: isDev,format:"jed1.x", "fallback-to-msgid":true, code:langCode} } ]}isLoadAll表示会把所有语言版本的文件通过po2json转换成json,然后组合成一个json作为数据传给引用的地方。
code选项一般需要在代码发布时指定,不同语言版本打包时通过传入不同的code区分不同语言版本的代码打包。
代码中使用gettext系列函数
各端开发时使用各自实现的gettext方法去包装需要实现多语言的文案。使用gettext函数包装后, langs-util 就能知道代码中有需要多语言翻译的地方,并可以通过 langs-util 生成相关的pot及po文件。gettext方法底层我们使用jed 来实现其对应功能。
import toi18n from "common/i18n";const _ = toi18n(require("langs/index.pot"));const hiStr = _.gettext("Hi!");const num = Math.ceil(Math.random() * 2);const numStr = _.ngettext("item", "items", num);// I like your red shirt.console.log(_.sprintf( "I like your %1$s %2$s.", 'red', 'shirt'));一般使用 gettext 方法包装一个需要翻译的字符串。
可以用于单复数处理,第一个参数传入单数情况下的翻译,第二个参数传入复数情况下的翻译,第三个传入实际需要执行判断的数据。
Jed内置提供了sprintf的支持,它是使用javascript-sprintf的sprintf函数的实现。
通过gettext 一系列函数的配合,使用 langs-util 进行生成处理后就能生成对应的pot及po文件。
langs-util gen -i src/# langs/index.potmsgid "Hi!"msgstr ""msgid "item"msgid_plural "items"msgstr[0] ""msgstr[1] ""# langs/index.th.pomsgid "Hi"msgstr ""msgid "item"msgid_plural "items"msgstr[0] ""msgstr[1] ""把生成的文件交由对应的翻译人员完成翻译就可以重新放回到文件夹当中替换目标po文件。
打包&发布
各端打包方式都会有相应的差异,最终目的无非就是使线上代码可以按照不同语言的版本加载不同的语言文件。对于 后台 等系统则可以使用isLoadAll的方式把所有语言版本的文件都加载进来,通过i18n的包装函数去从数据源中拿出不同国家的多语言数据文件。
cross-env LANG_CODE=th移动端发布使用环境变量 LANG_CODE 来区分要编译成的语言版本。
const langCode = process.env.LANG_CODE{ test: /\.pot$/i, use: [ "json", { loader: 'langs', options: {isLoadAll: isDev,format:"jed1.x", "fallback-to-msgid":true, code:langCode} } ]}生成完所有语言语言版本的静态文件后,需要让浏览器能够运行不同语言版本的js文件。一种方式可以通过后台程序读出语言版本,再把正确语言版本的js路径输出到html当中。另外一种方式可以新建一个多语言loader的文件,通过前端js代码动态插入正确语言版本的js代码(文件打包的时候需要把各语言版本的js文件路径输出到页面之中)。
import {languageCode} from "common/constant";const loadScript = (path: string) => { const script = window.document.createElement("script"); script.setAttribute("src", path); window.document.body.appendChild(script); return new Promise((resolve, reject) => { script.onload = resolve; script.onerror = reject; });};const {mainFilePath} = window;if (typeof mainFilePath === "string") { loadScript(mainFilePath);}else if (typeof mainFilePath !== "string") { loadScript(mainFilePath[languageCode] );}langs-loader 实现
在loader代码中拿到require文件的实际路径,如果存在code选项的话则根据pot文件找到对应code的po文件,然后使用po2json转换为对应格式的json文件,最后再返回给引用的地方。如果存在isLoadAll选项并且isLoadAll选项为true的话,则会load 同名pot文件的所有对应语言版本的po文件,然后再通过po2json转换组合成一个json文件,再返回出去。
langs-util 实现
langs-util主要整合了xgettext/msginit/msgmerge等方法。传入所需要解析的文件或文件夹,生成对应的po及pot文件。
const genPoFiles = (inputFilePaths: string | string[], potFilePath: string, langs: string[]) => { const potDirName = dirname(potFilePath); const filename = basename(potFilePath, extname(potFilePath)); const filePaths = typeof inputFilePaths === "string" ? inputFilePaths : inputFilePaths.join(" "); execOnlyErrorOutput(`xgettext --language=JavaScript --add-comments --sort-output --from-code=UTF-8 --no-location --msgid-bugs-address=wanglin@ezbuy.com -o ${potFilePath} ${filePaths}`); checkFileExists(potFilePath).then((ifPotFileExists) => { if (ifPotFileExists) { console.log(green(potFilePath)); writeFileSync(potFilePath, readFileSync(potFilePath).toString().replace("charset=CHARSET", "charset=UTF-8")); langs.forEach((lang) => { const poFilePath = join(potDirName, `${filename}${lang === "" ? "" : `.${lang}` }.po`); checkFileExists(poFilePath).then((ifExists) => { if (ifExists) { execOnlyErrorOutput(`msgmerge --output-file=${poFilePath} ${poFilePath} ${potFilePath}`); }else { execOnlyErrorOutput(`msginit --no-translator --input=${potFilePath} --locale=${lang} --output=${poFilePath}`); } }); }); } });};生成po文件时,需要传入需要给xgettext解析的文件列表以及目标pot文件路径还有生成的多语言版本种类。xgettext会根据传入的解析文件生成新的pot文件,如果生成成功则开始生成对应语言版本的po文件,如果对应的po文件存在则使用msgmerge更新po文件,如果不存在则使用msginit创建新的po文件。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
我们今天用一个简单的实例说明一下在PHP中的getText的用法(getText是一系列的工具和库函数,帮助程序员和翻译人员开发多语言软件的),从而实现PHP的
始因--懒最近项目中,经常用到多语言翻译,而iOS的多语言适配,设计给出的多语言都是指定的翻译制作成的一系列表格,基本都要一点一点复制到对应的语言文件中,如此反
最近要对一款游戏进行多语言本地化,在网上找了一些方案,加上自己的一点点想法整理出一套方案和大家分享!多语言在应用程序中一般有两种做法:一、程序中提供给用户自己选
前言最近公司需要切换多语言和字体大小功能,上网查看比较少的实用方案。于是我经过几天尝试和思考完成了第一版的应用内多语言版本切换的功能Demo。下面分享给大家,需
前言多语言本地化,是我们在做IOS项目的时候经常用的,下面根据自己的经验和使用场景,来全面的说说多语言本地化的解决方案。本文从提升效率和减少错误两方面对传统的多