惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
K
Kaspersky official blog
T
The Exploit Database - CXSecurity.com
NISL@THU
NISL@THU
AWS News Blog
AWS News Blog
V2EX - 技术
V2EX - 技术
Google DeepMind News
Google DeepMind News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Security @ Cisco Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
Attack and Defense Labs
Attack and Defense Labs
Jina AI
Jina AI
The Last Watchdog
The Last Watchdog
W
WeLiveSecurity
H
Help Net Security
V
Visual Studio Blog
宝玉的分享
宝玉的分享
C
Cybersecurity and Infrastructure Security Agency CISA
T
Threat Research - Cisco Blogs
IT之家
IT之家
Hugging Face - Blog
Hugging Face - Blog
Latest news
Latest news
T
Tor Project blog
I
Intezer
美团技术团队
GbyAI
GbyAI
T
Tailwind CSS Blog
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
Google DeepMind News
Google DeepMind News
Scott Helme
Scott Helme
Y
Y Combinator Blog
博客园 - 司徒正美
T
Tenable Blog
O
OpenAI News
N
News and Events Feed by Topic
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
Vulnerabilities – Threatpost
P
Palo Alto Networks Blog
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Threatpost
Google Online Security Blog
Google Online Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
Help Net Security
Help Net Security

Dallas Lu

OpenWRT 使用 udp2raw 对抗 WireGuard 阻断 博客程序架构的思考与展望 如何证明你是原创作者 Nginx 泛域名配置的隐患与对策 WISeID S/MIME 证书 V2EX 刑满释放记 使用 Radicale 在 Ubuntu 24.04 中搭建 vCards CardDav 服务 邮件服务的域名成功从 SURBL 黑名单移除 网站评论系统的目前进展和展望 在公网使用 iptables 转发端口时保留客户端 IP 邮件投递平台 Postal 的使用经验 自建 Postal 完美替代 SendGrid 互联网在崩塌吗,然后呢 在 SvelteKit 应用中使用 JSON-LD 网页的打印样式应该怎么写 “茴字的四种写法”之 IP 与域名 怎么伪造 Git 提交的时区 供大众交流的论坛和其它替代产品还是不好用 改编不是照搬 一次排查诡异的网络问题的经历 在 OpenWRT 23 中使用 nftset 配置 Shadowsocks 规则 使用自建 Tabby Web 来同步 Tabby 配置 手动建立自己的 IPv6 Tunnel 服务 在 PVE 手动配置网络及虚拟机 IPv6 公网 在 PVE 中缩小 Ubuntu 虚拟机的磁盘 Beancount 摊销与折旧的使用以及相关插件 Nginx 反代 Apache Subversion 添加 HTTPS 使用你的主域名作为 Mastodon 实例名 Firefox 和 Chrome 为何要革 EV 证书的命
网站多语言的设计细节
达拉斯・卢 · 2024-08-23 · via Dallas Lu

早在用 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.mditem.zh.md 文件中引入两个不同链接之外,还有一个方式是创建 image.en.pngimage.zh.png 两个文件,使用 ![](image.png) 来引用。是的,URL /imag.png 也会返回不同语言的内容,Accep-Language 头就是这样用的。

时至今日,还有人怀念 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 评论了。“英特纳雄耐尔”,就一定要实现!


  1. 在 Grav 中,可以创建一个隐藏的内容页,用来存储站点配置的多语言版本,但这种方式需要使用支持此功能的定制主题。 ↩

  1. Dallas Lu. ...原始文章是你自己写的,这个理解程度是他人作品所不能比的。整个过程既有输出的强化练习,又有高效地学习吸收.... 𝕏. 2024-05-01. ↩

  2. 何加盐. 中文互联网正在加速崩塌. cnBeta. 2024-05-23. 首发于微信公众号. ↩

  3. 大毛. 我们正在目睹中国文明的孤岛化. 积薪. 2024-08-13. ↩