静态页面多语言的实现
生成一个静态页面之后,需要将文本翻译成其他语言,如果同时维护多个文本不同的页面,难免会出现错漏翻译文本、需要同步页面结构等诸多麻烦。因此希望在完成一个静态页面之后,可以使用工具自动生成对应的翻译页面。
思路
使用正则提取静态页面中的文本,按照 Gettext 标准生成翻译文件,随后在打包时,自动生成对应的翻译页面。
实现
下面以英文翻译成中文为例来说明实现方法。
1. 提取文本
为了简单方便直接采用特殊符号包裹文本,方便正则处理:
// 英文 HTML
<div>
<h2>{{Home}}</h2>
<a title="{{Features}}">{{Features}}</a>
</div>
使用正则提取 {{*}}
内容,循环遍历和旧的 zh_CN.po
做比较,然后更新 zh_CN.po
文件内容。
const fs = require('fs')
const path = require('path')
const po2json = require('po2json')
const htmlPath = path.resolve(__dirname, 'src/index.html')
const htmlContent = fs.readFileSync(htmlPath).toString()
const matches = htmlContent.match(/{{[^}}]+}}/g)
const poPath = path.resolve(__dirname, 'langs/zh_CN.po')
let poData = {}
try {
// po 文件内容转成 json
poData = po2json.parseFileSync(poPath)
} catch (err) {}
let poContent = ''
Array.from(new Set(matches)).forEach(raw => {
const key = raw.replace(/^{{/, '').replace(/}}$/, '')
// 已经翻译的文字作为翻译结果
const translateText = (key in poData) ? poData[key][1] : ''
poContent += `msgid "${key}"\nmsgstr "${translateText}"\n\n`
})
fs.writeFileSync(poPath, poContent)
生成的 .po
文件大致如下:
msgid "Home"
msgstr "" // 未翻译
msgid "Features"
msgstr ""
msgid "FAQ"
msgstr "常见问题" // 已翻译
2. 翻译文本
翻译文本推荐使用 Poedit,升级到 Pro 版本还有自动翻译功能。
3. 生成对应的翻译页面
const fs = require('fs')
const path = require('path')
const po2json = require('po2json')
const htmlPath = path.resolve(__dirname, 'dist/index.html')
let htmlContent = fs.readFileSync(htmlPath).toString()
// 原英文 HTML 包含 {{}},需要删除
htmlContent = htmlContent
.replace(/{{/g, '')
.replace(/}}/g, '')
fs.writeFileSync(htmlPath, htmlContent)
const poPath = path.resolve(__dirname, 'langs/zh_CN.po')
const poContent = po2json.parseFileSync(file)
const zhCNHTMLPath = path.resolve(__dirname, 'dist/index-zh_CN.html')
let zhCNHTMLContent = htmlContent
Object.keys(poContent)
.forEach(key => {
while (newHTMLContent.includes(key)) {
zhCNHTMLContent = newHTMLContent.replace(key, poContent[key][1])
}
})
fs.writeFileSync(zhCNHTMLPath, zhCNHTMLContent)
评论(1)
使用正则提取静态页面中的文本,按照 Gettext 标准生成翻译文件,随后在打包时,自动生成对应的翻译页面。 --------------------------------------------------------- 这个思路不错!