多语言内容

Jant 默认是单语言博客,你可以在 Settings → Language 里设置你写作的语言。

如果你有多种语言的读者,可以在 Settings → Language 中启用多语言。启用时,你需要设置主语言和其他语言。

启用后,主语言的首页是 /,其他语言比如日语,那么日语的首页是 /ja,同时,对应的 collections 是 /ja/collections,archive 是 /ja/archive,每个独立的 collection 则是 /ja/{collection-slug}。不过为了长期的可维护性,每篇日语帖子并不会有 /ja 前缀,而是统一按照 /{slug} 作为永久地址。

前缀是什么意思

主语言留在根地址。其他语言按各自的语言标签(小写)挂在一个 URL 前缀下。

以主语言为简体中文、同时发布英文和日文的站点为例:

界面 简体中文 English 日本語
首页 / /en /ja
Latest /latest /en/latest /ja/latest
Featured /featured /en/featured /ja/featured
归档 /archive /en/archive /ja/archive
搜索 /search /en/search /ja/search
合集目录 /collections /en/collections /ja/collections
一个合集 /reading /en/reading /ja/reading
主订阅源 /feed /en/feed /ja/feed
一篇帖子 /hello /hello /hello

前缀选中的是一个视图:同一个页面,只筛出这种语言的内容。/en/archive 是英文帖子的归档,/en/feed 是英文帖子的订阅源,在视图里翻页也不会跳出去。

有两类地址看着该存在,但故意没有:

  • 主语言自己的前缀会 301 跳回根地址(/zh-hans/)。一种语言只有一个规范地址。
  • 不属于阅读界面的一切——后台、合集编辑页、帖子固定链接——全站只有一个地址。/en/settings 是 404,不是英文版后台。

打开多语言

进入 Settings → Language → Multilingual content,点 Turn on。在对话框里确认哪种语言是主语言,并至少再加一种。

保存时会发生两件事:

  • 没有语言的帖子会被标记为主语言。 帖子原本不带语言,不标记,根视图就会是空的。这是对已有帖子的一次性处理,对话框会告诉你涉及多少篇。其中真的是别的语言写的,之后可以在帖子自己的菜单里改。
  • URL 前缀会和现有地址核对。 如果某个前缀会盖住你已经发布的帖子或页面——站点上已经有一篇帖子占着 /en,又要启用 /en 前缀——这次改动会被拒绝,而不是悄悄挡掉那个地址。

其他什么都不动,帖子地址保持原样。多语言也可以随时再关掉。

发布时选择语言

站点发布的语言超过一种以后,编辑器里会出现一个地球图标的控件。它列出你的每种语言,外加 Detect——根据你已经写下的内容判断语言。

判断用的是字符集投票,不是统计模型,能分辨到哪一步取决于文字本身:

  • 谚文和假名几乎没有歧义,所以韩文和日文很可靠。
  • 简体和繁体靠只属于其中一边的字来分辨,通常一句话就够。两边写法完全相同的文字会被判为「中文,但简繁未定」——只发布其中一种的站点够用,两种都发布的站点则要你自己选。
  • 拉丁字母只能说明「不是 CJK」。只有当站点恰好只发布一种非 CJK 语言时,它才会落到具体语言上,否则把选择留给你。
  • 几个词的片段读不出任何结论,沿用默认语言。

判断结果永远不会是站点没有发布的语言,而且始终只是建议,你可以改。通过 API、Telegram 机器人或 MCP 进来的帖子——没有人选过语言——在服务端跑同一套判断。

一个 Thread 只有一种语言。回复的语言跟着根帖走,改动 Thread 里任何一篇,整个 Thread 都会跟着改。

关联不同语言的版本

打开帖子的 菜单,选 Language。和这篇帖子语言有关的操作都在这里:

  • Change language——设定这篇帖子(以及它所在的 Thread)是用什么语言写的。
  • Write the {语言} version——在编辑器里新开一篇该语言的帖子,并且已经和这篇关联好。写的时候当前这篇留在屏幕上。
  • Link a version you already wrote——搜索你自己的帖子,关联一篇已经写好的。列表里只会出现真正能关联的帖子。也可以直接粘贴那篇帖子的网址——写译文的时候手边通常就是它;要是那篇不能关联,选择框会说明是下面哪条规则挡住了。
  • Other versions——已经关联的帖子,每一篇都能打开,也能解除关联。

关联起来的帖子构成一个翻译组:每种语言一篇,没有方向,也没有原文,互为版本。解除其中一篇不影响其余的。

站点会守住两条规则,避免一次关联悄悄重排你的内容:

  • 一个组里每种语言最多一篇。
  • 两篇帖子如果各自已经属于一个组,不能关联,因为那等于合并两个组。先解除其中一边。

只有 Thread 的根帖能关联。回复属于它的 Thread,有语言的是 Thread。

读者看到什么

  • 有其他版本的帖子会显示 Also available in,并列出每个版本的链接。
  • 页头的切换器意思是「带我去这种语言的站点」。从列表页去的是该语言的同一个列表页;从一篇帖子去的是它在该语言的版本,没有版本时去该语言的首页。它不会指向 404,也不会弹警告。
  • 每个视图的订阅源会声明自己的语言,所以订阅 /en/feed 拿到的帖子在阅读器里标着英文。
  • 按语言划分的页面都带有每种语言的 <link rel="alternate" hreflang> 以及 x-default,站点地图里也是同一组关系。两者都需要配置绝对站点地址才会生效,见配置

管理语言

都在 Settings → Language。多语言打开后,原来的单个语言选择器会变成一个语言列表。

添加语言。 加上就出现在切换器里,前缀立刻生效,不需要先有一篇该语言的帖子。

把某种语言设为主语言。 两者一步对调:新的主语言接管根地址,原来的主语言移到自己的前缀下。帖子地址不变——但订阅了 /feed 的人从此收到的是新主语言的帖子,因为 /feed 是根视图的订阅源。

移除语言。 只有在没有帖子使用它时才允许。已经有帖子时没有好答案——隐藏、迁移还是重定向,都是在替你猜——所以 Jant 会告诉你还有多少篇在用,并给出链接,把决定留给你。语言一旦移除,它的前缀也就不再响应。

移除最后一个,多语言会一起关掉。 按语言划分的视图得有第二种语言才有意义,所以移除主语言之外仅剩的那一个时,多语言会在同一步里关闭。Jant 会先问一次,并说明会变成什么样。上面那条规则依然成立:还有帖子在用的语言不能移除,是不是最后一个都一样——先改掉那些帖子的语言。

关掉多语言

在语言页选 Turn off。根地址恢复显示所有语言,原来的前缀会重定向过去,已有的链接和订阅仍然有效。

语言列表和每篇帖子的语言都会保留。重新打开时还是原来那套设置,也不会再标记一次。

一个个把语言移除,最后到的是同一个地方,只有一点不同:被移除的语言不在列表里了,它的前缀是不再响应,而不是重定向。以后还想回来就用关闭,确定不再用那种语言就移除。

设置项对照

设置 存的是什么
SITE_LANGUAGE 主语言,也就是根地址提供的语言
ADDITIONAL_LANGUAGES 挂在前缀下的语言,按切换器顺序
MULTILINGUAL_ENABLED 是否提供按语言划分的视图
DASHBOARD_LANGUAGE 你自己后台的显示语言

前三项由语言页写入,不直接编辑:它们的值必须彼此一致,也必须和帖子上标记的语言一致。Config Editor 里能查到它们,但只给一个回到语言页的链接,不能在那里改。

DASHBOARD_LANGUAGE 和你发布什么无关。它决定私有后台的显示语言,只有你看得到;选 Follow content language 就跟着站点主语言走。

API

每个语言操作都有对应的 HTTP 接口,脚本和 agent 可以做同样的事:

接口 作用
PUT /api/posts/:id/language 设置整个 Thread 的语言
GET /api/posts/:id/translations 列出与这篇关联的版本
GET /api/posts/:id/translations/candidates 搜索可以关联的帖子
GET /api/posts/:id/translations/resolve 按网址查一篇,或说明为什么不能关联
POST /api/posts/:id/translations 把另一篇关联为这篇的版本
DELETE /api/posts/:id/translations 把这篇移出它的翻译组

通过 API 创建帖子时可以带 language,也可以用 translationOfId 在创建时就加入已有的翻译组。不带语言时由服务端判断。请求和响应的字段见 API 参考(英文)

接下来