# 翻译指南 翻译程序能够将特定的文本替换成您的翻译, 作用范围为网页中所有文本节点(`nodeType === Node.TEXT_NODE`), 文本框的提示文字(`placeholder`), 以及鼠标停留时弹出的提示文字(`title`). ## 文件目录 - `i18n.css` 界面元素调整样式 - `i18n.js` 主程序 - `i18n.ts` 主程序(TypeScript) - `i18n.ja-JP.js` 日语翻译 - `i18n.en-US.js` 英语翻译 - `i18n.de-DE.js` 德语翻译 - `i18n.md` 本说明文档 即翻译文本均存放在`i18n.[ISO语言代码].js`中. ## 添加翻译文本 1. 用代码编辑器打开相应的翻译文件, 以英语为例, 则打开`i18n.en-US.js`. 2. 文件结构大致为: ```js export const map = new Map([ /* Your translation here */ [`*`, [ /* CSS translation here */ ]], ]); export const regex = new Map([ /* Regex translation here */ ]); export default { export: { map, regex }, }; ``` 3. 在`/* Your translation here */`上方添加翻译, 或在`/* CSS translation here */`上方添加选择器翻译, 在`/* Regex translation here */`上方添加正则翻译, 详细语法见下一节. ## 翻译语法 有多种翻译方式可供选择. ### 直接翻译 格式为``[`原文本`,`翻译后文本`],``. 例如, 将`主站`翻译为`Home`, 则添加: ```js [`主站`, `Home`], ``` 添加后的文件大致如下: ```js export const map = new Map([ /* 其他翻译... */ [`主站`, `Home`], ]); export default { export: { map }, }; ``` ### 特殊翻译 可以为特定元素的文本特别指定一种翻译, 通常用于特殊语境下词语的翻译, 但是需要翻译者对[CSS](https://developer.mozilla.org/zh-CN/docs/Glossary/CSS)的[选择器语法](https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Selectors)有一定了解. 格式为: ```js [`原文本`, { selector: `CSS选择器`, text: `翻译后文本`, }], ``` 例如: ```js [`主站`, { selector: `.xxx.yyy`, text: `Home2`, }], ``` 将在文本所属节点匹配`.xxx.yyy`选择器时, 将`主站`翻译为`Home2`. 按照上面的例子, 以下的元素 ```html 主站 主站 ``` 将翻译为 ```html Home2 主站 ``` 如果希望**不匹配**选择器的文本接受翻译, 只需添加一行`not,`: ```js [`主站`, { not, selector: `.xxx.yyy`, text: `Home2`, }], ``` 这样, 所有**不匹配**这个选择器的文本都将被翻译. ### 混合翻译 可以组合以上两种翻译方式, 为同一词语使用多种翻译. 格式为: ```js [`原文本`, [ `直接翻译`, { selector: `CSS选择器1`, text: `特殊翻译1`, }, { selector: `CSS选择器2`, text: `特殊翻译2`, }, ]], ``` 即存放翻译文本的地方改成一个数组`[]`, 其中存放多种翻译, 用逗号`,`隔开每一项. - 直接翻译只能有一个, 而特殊翻译可以有多个. - 越在后面的特殊翻译优先级越高, 如果一个元素同时满足两种翻译里的选择器, 程序会使用较后面出现的翻译. - 程序其实不会检查直接翻译到底有几个, 要是真的有多个, 只有最后一个出现的直接翻译被采用. 例如以下混合翻译: ```js [`主站`, [ `Home`, { text: `Home2`, selector: `.xxx.yyy` }, ]] ``` 能够将 ```html 主站 主站 ``` 翻译为 ```html Home2 Home ``` ### 使用选择器翻译 当原文本很长或很复杂时, 放在翻译文件里会影响易读性, 这时可以用CSS选择器选择该节点进行翻译. 这种翻译统一放在原文本为`*`的一节翻译中. > ⚠ 这种翻译方式不管原文本是什么, 只要匹配了选择器就执行翻译. 格式为: ```js [`*`, [ { selector: `CSS选择器1`, text: `翻译文本1`, }, { selector: `CSS选择器2`, text: `翻译文本2`, }, ]], ``` 例如以下选择器翻译: ```js [`*`, [ { selector: `.xxx.yyy`, text: `Home3`, }, ]] ``` 能够将 ```html very very long text very very long text very very long text very very long text very very long text ``` 翻译为 ```html Home3 ``` ### 使用正则翻译 当原文本包含一段不确定内容时, 可以使用正则翻译来匹配, 需要翻译者对正则表达式有一定了解. 这种翻译放在这一区域: (`export const regex`) ```js export const regex = new Map([ /* Regex translation here */ ]); ``` 例如, 要将`浏览:23.3w`翻译为`Read: 23.3w`, 则添加: ```js [/浏览:([0-9\.a-z])/, `Read: $1`], ``` 第一个元素是正则表达式, 用一对斜杠(`/`)包围, 语法可在[MDN文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)中学习. 第二个元素是替换文本. 在这个例子中, `$1`指代原文本中的浏览量数字, 利用了正则表达式的分组功能, 详见文档中的["使用括号的子字符串匹配"](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions#%E4%BD%BF%E7%94%A8%E6%8B%AC%E5%8F%B7%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D_2)一节. ## 调整界面元素 一些界面元素的尺寸是固定大小, 如果添加翻译后, 无法适应翻译后的文本长度, 可以在`i18n.css`中添加CSS样式来调整. ## 示例翻译文件 此文件简单展示了一下每一种翻译方式. 其中所有的CSS选择器和翻译文本仅作示例使用, 并不代表实际情况. ```js export const map = new Map([ [`主站`, `Home`], // 直接翻译 [`大会员`, { // 特殊翻译, 只有匹配.aaa的元素会被翻译 selector: `.aaa`, text: `VIP`, }], [`关注`, [ // 混合翻译: `Follow`, // 直接翻译, 适用于"关注"的动词形式 { // 特殊翻译, 适用于"关注"的名词形式 selector: `.bbb`, text: `Following`, }, ]], /* Your translation here */ [`*`, [ // 选择器翻译 { // 选择匹配.xxx的元素, 翻译为XXX selector: `.xxx`, text: `XXX`, }, { // 选择匹配.xxx的元素, 翻译为YYY selector: `.yyy`, text: `YYY`, }, /* CSS translation here */ ]], ]); export const regex = new Map([ [/(\d+)次播放/, `Played $1 times`], /* Regex translation here */ ]); export default { export: { map, regex }, }; ``` 该文件能够将类似以下的网页内容 ```html 主站 主站 大会员 大会员 关注 关注 其他 其他 其他 233次播放 ``` 翻译为 ```html Home Home VIP 大会员 Following Follow XXX YYY Played 233 times ```