使用@wordpress/babel-plugin-makepot插件来提取pot文件(翻译模板)
WordPress 5.0 的新功能 Gutenberg 是一個名為「區塊編輯器」的豐富編輯器,是一個強大的 JavaScript 前端專案。Gutenberg 的存儲庫採用了使用 Lerna 构建的單一存儲庫結構,其中包含了許多有趣的工具在 ./packages 資料夾中。
在本文中,我们将介绍 Gutenberg 工具箱中附带的 Babel 插件 @wordpress/babel-plugin-makepot。
“Babel 是什么意思?”
Babel 是一种用于进行 JavaScript 转译的工具链。例如,通过”巴别塔”转译,可以将用现代 JavaScript 编写的 ECMAScript 2015 版本及其之后的代码转换成旧浏览器等也能执行的向后兼容的 JavaScript。
// main.js
const list = [1, 2, 3].map(n => n ** 2)
$ yarn add @babel/cli @babel/core @babel/preset-env --dev
$ npx babel main.js --presets "@babel/preset-env" --out-file output.js
// output.js
"use strict";
var list = [1, 2, 3].map(function (n) {
return Math.pow(n, 2);
});
Babel是一个处理JavaScript的AST(抽象语法树)的库集合。它包含了解析JavaScript代码生成AST(即解析器)、遍历和重组AST的工具(即遍历器)、以及从AST生成新的JavaScript代码的工具(即生成器)。
在前端圈子中,我们经常使用babel-loader将React的JSX转换为webpack所需的格式,这是一个常见的工具。
POT 是什么?
另一个话题是翻译模板称为POT。除了.po文件和.mo文件,.pot文件是用于i18n(国际化)和l10n(本地化)主题和插件的文件,对于WordPress用户来说非常熟悉。它是基于名为gettext的国际化和本地化库的机制。
例如,当您想要翻译WordPress插件或主题程序中嵌入的”Translate me!”字符串时,按照以下步骤进行。your-domain代表插件或主题的名称等。
- プログラムに WordPress 組み込みの翻訳関数(__ など)を適用する
<?php echo __('Translate me!', 'your-domain'); ?>
- プログラムを静的解析して翻訳テンプレート(pot ファイル)を生成する
# main.php:1
msgid: "Translate me!"
msgstr: ""
pot ファイルをコピーして各ロケールの翻訳を作成する
ja_JP.po
# main.js:1
msgid: “Translate me!”
msgstr: “翻訳お願い!”
zh_CN.po
# main.js:1
msgid: “Translate me!”
msgstr: “翻译吧!”
po ファイル を元にバイナリの mo ファイルを生成してプログラムに同梱する
在前端项目中实施翻译
WordPress のプロジェクトでは、フロントエンドであっても pot ファイル・ po ファイル を使った翻訳の手法が取られているようです。この手法が WordPress テーマ・プラグイン開発者に馴染み深いものであること、バックエンド側と pot ファイル・ po ファイルを共通化できることが理由のように思われます。ただし、フロントエンドではバイナリの mo ファイルではなく Jed と呼ばれる形式の JSON ファイルを用います。この JSON ファイルを @wordpress/i18n のライブラリで読み込むことで、フロントエンドでも翻訳を適用することができます。
JSON ファイルの生成には、 WP CLI の wp i18n make-json コマンドや po2json というライブラリを使いますが、ここでは詳細は省きます。
ja_JP.po から生成した Jed 形式の ja_JP.json
{
“domain”: “your-domain”,
“locale_data”: {
“your-domain”: {
“”: {
“domain”: “your-domain”
},
“Translate me!”: [“翻訳お願い!”]
}
}
}
翻訳対象になる JavaScript プログラムの例
import { __, setLocaleData } from '@wordpress/i18n'
import ja_JP from './languages/ja_JP.json'
// 翻訳辞書を適用
const localeData = ja_JP.locale_data['your-domain']
setLocaleData(localeData, 'your-domain')
console.log(__('Translate me!', 'your-domain')) // 翻訳お願い!
これに先立って、JavaScript を静的解析して pot ファイルを生成しないといけないわけですが、そこで用いられているのが @wordpress/babel-plugin-makepotです。
生成POT文件
我将使用 Babel 将上述的 JavaScript 进行转换。
// main.js
import { __, setLocaleData } from '@wordpress/i18n'
import ja_JP from './languages/ja_JP.json'
const localeData = ja_JP.locale_data['your-domain']
setLocaleData(localeData, 'your-domain')
console.log(__('Translate me!', 'your-domain')) // 翻訳お願い!
$ yarn add @wordpress/babel-plugin-makepot --dev
$ npx babel main.js --plugins "@wordpress/babel-plugin-makepot"
$ cat gettext.pot
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"X-Generator: babel-plugin-makepot\n"
#: translate.js:7
msgid "Translate me!"
msgstr ""
Babel を通した時に副作用として gettext.pot が生成されています。
translate.js -> (Babel) -> translate.js
└> gettext.pot
在这种情况下,不需要 Babel 的标准输出,可以将其丢弃。
$ npx babel main.js --plugins "@wordpress/babel-plugin-makepot" > /dev/null
pot ファイルの出力先を指定する
使用.babelrc配置文件可以指定插件的选项。
在@wordpress/babel-plugin-makepot中有一个名为output的选项,用于指定pot文件的输出路径。
$ cat .babelrc
{
"plugins": [
["@wordpress/babel-plugin-makepot", {"output":"src/languages/my-domain.pot"}]
]
}
我想在React和TypeScript中使用它。
如果你正在使用React、JSX和TypeScript,大概是这样的感觉。
// component.tsx
import { __, sprintf } from '@wordpress/i18n'
type Props = {
name: string
}
export const Component = (props: Props) => {
return <p>{sprintf(__('My name is %s.', 'your-domain'), props.name)}</p>
}
$ cat .babelrc
{
"presets": ["@babel/preset-react", "@babel/preset-typescript"],
"plugins": ["@wordpress/babel-plugin-makepot"]
}
$ yarn add @babel/preset-react @babel/preset-typescript --dev
$ npx babel component.tsx
$ cat gettext.pot
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"X-Generator: babel-plugin-makepot\n"
#: component.tsx:8
msgid "My name is %s."
msgstr ""
※ 「言語を変えた時に render() が走らないから翻訳が適用されないじゃないか!」という問題があります。WordPress はロケールの変更の時に必ずページ遷移があるようなので、問題が発生しないのだと思いますが、ページ遷移なしで言語を切り替えたい時は工夫が必要そうです
总结
Gutenberg のツール @wordpress/babel-plugin-makepot について紹介しました。pot ファイルを生成するためにはコードを静的解析する必要があるのですが、AST を走査できる Babel にはうってつけです。栄枯盛衰の激しいフロントエンドの開発ツールが、伝統的な翻訳の手法とシームレスに統合されているところが非常に面白く感じます。