五种语言
博客现在会说中文和俄语了。准确地说,是“家具”会说:导航、按钮、表单、页脚,全都在 /zh 和 /ru 下面有了对应版本。文章本身会随着我翻译它们慢慢跟上,这是需要老老实实做的活,我不打算赶工。

俄语版首页。同一座岛,换了文字。
从三种语言变成五种,逼着我做了一直拖着没做的清理工作。语言列表不知不觉地多处重复:路由里一份,切换器里一份,日期格式里一份,站点地图里还有一份。现在只有一个统一的注册表,其他所有地方都从它派生出来。我用一个测试向自己证明了这一点:这个测试虚构出一种第六语言,检查路由、切换器、翻译目标和站点地图是不是都能自动识别它,不需要再改任何其他地方。以后要加第六种语言,就只需要一条注册表记录和一份对应的文案文件。
切换器也得跟着改。三种语言作为侧边栏里的链接还凑合,五种语言看起来就像一张绑架信了。现在它变成了一个下拉菜单,位置不变,每种语言都用它自己的文字写着:English, norsk, español, 中文, русский。选一种当前页面存在的语言,你会落到那个语言版本;选一种当前页面不存在的语言,你会落到那个语言的首页,而不是一个 404。
缺失的翻译在其他地方也有一个柔和的兜底方案。/ru 下的隐私政策页面,在我写出俄语版本之前,会在俄语的界面外壳里显示英文正文,这总比在任何语言下看到一个错误页面要好。
为了让自己保持条理,后台新增了一个“语言”板块:一个网格,纵向是站点所有页面,横向是所有语言,显示每个组合是否存在、是否缺失。缺失的格子会给我两个按钮:翻译它,或者以英文版本为起点创建它,这样我是在改写内容,而不是盯着一个空白框发呆。文章故意没有放进这个网格里,我会在编辑器里一篇一篇地翻译,当一篇文章值得翻译的时候再动手。
一切都挂在这个注册表上:
const LANGUAGE_REGISTRY = [
{ code: 'en', nativeName: 'English', locale: 'en-US' },
{ code: 'no', nativeName: 'norsk', locale: 'nb-NO' },
{ code: 'es', nativeName: 'español', locale: 'es-ES' },
{ code: 'zh', nativeName: '中文', locale: 'zh-CN' },
{ code: 'ru', nativeName: 'русский', locale: 'ru-RU' }
] as const;
export type Language = (typeof LANGUAGE_REGISTRY)[number]['code'];字体反而是最简单的部分,像样的 CJK 和西里尔字体后备方案都到位了,衬线风格看起来也依然站得住。现在我就差给书架添些书了。