早在用 WordPress 的时候,就在琢磨用什么样的方式实现网站多语言。WordPress 本身对多语言的支持非常棒,但使用 WordPress 构建多语言网站,就有些困难了。后来转用 Grav,从中学到了一种很好的方式。当我开始自己写网站程序时,就决心实现一个好用、合理的方案。本文讨论一些相关的设计细节。
撰写多语言内容
语言承载着文化,你选择了一种语言,就或多或少自带了一种文化属性。有识之士早在十几年前就开始写英文文章了(awflasher 的博客)。甚至一些人搞垃圾农场站群的人,都在做英文内容。跨出中文圈,还能获得英文内容的更广的受众。也许在某些话题领域,英文的确更适合。
如今的时代,即使英文不是很好,也不耽误与英文世界交流。早年可以使用翻译软件,用多家软件在源语言和目标语言之间互译,充做校对;近年又可以使用更懂人话的 AI。同时,撰写英文内容之后进行人工阅读校对,这是一个极佳的学习英文的途径1。比如 pigleo 在《人人都能写英文博客》中提到,因自己的文章被盗译为英文,于是开始使用软件辅助进行英文写作。
鉴于中文互联网正在逐渐崩塌2,导致文明孤岛化3,撰写多语言内容有助于文化输入输出,做文化搬运工——或者直观点说,老乡,写英文能有更多的流量。
多语言网站实现
当然可以选择做一个独立的英文站,但这还不够国际化。WordPress 建立了不同语言的分站,提供帮助和支持。因为论坛中的发帖的内容,一般都只有单独一个语言的版本。如果你是自己写文章,则网站上的每一篇内容都有可能有多个语言的版本。
有作者在页面提供翻译功能,或者读者会使用翻译软件(如:沉浸式翻译),但这不是原生的内容。对搜索引擎和读者还不够友好。最好还是手动创建多语言内容,哪怕全是 AI 翻译的,耗一点精力校对一遍,也是极好的。
所以,我对多语言网站的理解是,内容和 UI 都原生支持多语言版本,多种语言浏览体验一致,内容及质量一致。本质上是同一个网站,可以使用子域名,甚至不同域名——所以 WordPress 的多站点模式并不在讨论的范围内。
我用过 qtranslate-x 插件来给 WordPress 实现多语言。这个插件更新缓慢,且使用在数据库字段中加入分隔符来存储多语言文本,是一种对 WordPress 不天然支持多语言内容的现状的一种妥协实现方案。在使用和迁移时,常会遇到一些麻烦。我也不太想尝试 WPML。而 Grav 是基于文件的,如果你的中文版本内容的文件名是 item.zh.md
,那么在同级目录创建 item.en.md
就算建立了对应的英文内容。这一设计非常直观和自由。不过 Grav 也有一些小缺陷,站点配置只有一套,比如网站名称,只支持一个语言版本注1。所以我也使用了极为相似的处理方式,在此基础上,可以实现更精细的规划。
内容的规划
你写了一篇文章,来赞美中国大陆的 App 备案制度,你会考虑创建一个英文版本吗?你写了一篇抨击特朗普的长文,你会创建一个台湾正体的版本吗?你写了一篇影评,使用了很多日语中的动漫梗来讽刺,你会考虑做一个德文版本吗?
不做独立站、选择做多语言网站,并不意味着每一种内容都是雷同的翻译。你可以自由选择,为每一篇文章提供哪些语言版本。甚至,你可以在不同版本中,表达迎合其语言文化的营销内容,随您的便。
URL 设计
多个语言的内容挤在一个网站,如何设计 URL 呢?像 Google 一样使用 URL Search Param 在 URL 中加入 ?lang=zh-CN
?或者让访问者选择一种语言,存在 Cookie 里?还是使用 /en/post-slug/
这种?
有时浏览一些英文文章,半懂不懂,翻译软件的质量也堪忧;此时若在页面中瞥见几个汉字,便去寻找其中文版本,往往徒劳无果。如果有多语言版本,那么真的应该实现对请求头中的 Accept-Language
的支持。即便当前文章的确没有对应的语言版本,至少在网站的 UI 上,能使用英文。有时遇到一些俄文、德文网站,找到语言切换按钮都是一种挑战。
所以,我的网站实现了:
- UI 语言与内容语言分离
- 默认 URL 实现自动语言
- URL 中包含语言时,展示对应的文章内容
除了内容之外,一些页面上的元素也应与语言联动,比如简体中文版本可能需要显示ICP备案号、公网安备案号、出版物经营许可证;欧洲语种可能需要显示 Cookie 隐私选项,点击接受就隐藏提示,点击拒绝就跳转到 Google。
英文用户访问本文的路径 /website-multilingual-design-details/
,并不会根据访问者的语言跳转到 /en/website-multilingual-design-details/
,仍留在这个页面,UI 显示为英文,内容也显示英文(如果有提供的话)。
而当你访问指定的语言版本的路径,则内容切换为对应版本,而 UI 语言仍然取决于访问者的浏览器设置。
其他细节
最重要的 URL 方案确定了,其他的细节几乎是水到渠成了。比如语言回滚,如果网站的首选语言是 en-US
,那么网站可以提供其支持的 en
。如果是 zh-CN
,也可以使用 zh-HK
的内容来勉强应对一下。Grav 中还有一个巧妙的设计,可为一篇文章禁用某个语言,只需创建这个语言的内容,并标记为删除即可。
内容语言提示
如果一个非英文的用户,通过 Google 或社媒上的链接,进入了含有英文语言路径的 URL,网站能够检测到内容语言与访问者的首选语言不一致。在页面最上,会提示当前内容的语言,以及与浏览器语言相关的可用内容语言,让访问者自由切换,宾至如归。在文章结尾,还列出了全部语言版本的链接,以方便读者学外语帮忙校对。
UI 语言切换
在页尾,提供了所有的 UI 语言版本,可以自由切换。如果有对应的内容,则内容也会切换语言。这样,即使是使用默认英语的 Tor 浏览器,也能通过点击 Отправить
按钮来发 Spam 啦。
媒体资源的多语言
如果你使用了有文字的图片,除了在 item.en.md
和 item.zh.md
文件中引入两个不同链接之外,还有一个方式是创建 image.en.png
和 image.zh.png
两个文件,使用 ![](image.png)
来引用。是的,URL /imag.png
也会返回不同语言的内容,Accep-Language
头就是这样用的。
RSS
时至今日,还有人怀念 Google Reader。我为 RSS 也实现了自动语言功能。遗憾的是,我尚未没有发现哪家阅读器的机器人,能够传递正确的语言头,以及跟随 atom 文件中的候选语言。于是也支持 /en/feed/
这种链接来专门订阅英文内容。
SEO
不使用发布平台的坏处之一,就是要自己来做 SEO。Google 给多语言网站提供了很好的指引。每篇文章的每种语言都被看作是不同的内容,我将带语言路径的链接,指定为首选版本,而默认的无语言路径的链接则指为 hreflang="x-default"
。Sitemap 中也是如此。基于文件的文章系统,还可以轻易地为每一种语言单独设定 keywords。
以及在 robots.txt 中让更懂中文的百度专注于中文:
User-Agent: Baiduspider
Disallow: /en/
锚点链接
甚至我还考虑到了锚点链接。因为默认情况下,一般情况 Markdown 的 heading 插件,会将中文版本中本节标题的 id 指定为 锚点链接
。如果中文用户分享了无语言路径的带锚点的链接,那么英文用户就无法定位到这一节。理论上在 Markdown 加入属性支持,在所有语言中都用 {#anchor-link}
来指定 id 即可。大概是过度设计了,根本不会有这种情况发生……
评论系统语言
又是一个过度的设计。不过评论系统在这种情况下,的确棘手。我选择记录下评论发生时的内容语言和 UI 语言,可以用来按语言分组展示评论,以及选择评论通知邮件的语言。
结语
经过不断的改进,目前小有成效。曾有人来指出,我的 RSS 出现了 BUG,语言内容出现混乱(诚意感谢这位朋友)。以及,开始有英文和俄文的 Spam 评论了。“英特纳雄耐尔”,就一定要实现!
注释
-
在 Grav 中,可以创建一个隐藏的内容页,用来存储站点配置的多语言版本,但这种方式需要使用支持此功能的定制主题。 ↩
参考
-
Dallas Lu. ...原始文章是你自己写的,这个理解程度是他人作品所不能比的。整个过程既有输出的强化练习,又有高效地学习吸收.... 𝕏. 2024-05-01. ↩
-
何加盐. 中文互联网正在加速崩塌. cnBeta. 2024-05-23. 首发于微信公众号. ↩
-
大毛. 我们正在目睹中国文明的孤岛化. 积薪. 2024-08-13. ↩
Webmention
评论表单
非常感谢分享。我的 wordpress 站点用的是 Polylang,就感觉还是比较笨重。第一次听说 Grav ,看了一下它对多语言的原生支持很给力。不过2024年了在 CMS 领域另立一个山头,总觉得比较害怕后续无人维护生态崩溃……
主题很好看 但感觉这个字体看起来不太舒服
我也有些同感。不知是字重大了,还是间距小了,或者字体的风格需要换一换。看上去有点花,满眼都是字