Wekan 批量修改全部用户语言设置:基于 mongosh 的 profile.language 实战指南
【免费下载链接】wekanThe Open Source kanban, built with Meteor. GitHub issues/PRs are only for FLOSS Developers, not for support, support is at https://wekan.fi/commercial-support/ . PR source translation to imports/i18n/data/en.i18n.json, other translations at https://app.transifex.com/wekan/wekan项目地址: https://gitcode.com/GitHub_Trending/we/wekan
导读:本文以 Wekan 官方文档 Change-Language.md 为核心,讲解如何用 MongoDB Shell(mongosh)一次性修改所有用户的语言偏好(
profile.language),例如将英文日期格式统一切换为DD/MM/YY(en-GB)。文中会结合仓库源码剖析语言字段的存储结构、客户端语言解析逻辑与 e2e 测试证据,帮助你理解"改数据库"与"界面语言生效"之间的完整链路,并掌握批量语言迁移的落地操作。
背景:Wekan 用户语言存在哪里?
Wekan(基于 Meteor 的开源看板)把每个用户的语言偏好存放在 MongoDBusers集合的profile.language字段中。这个字段在用户模型中有着明确的 schema 定义,见 models/users.js:
'profile.language': { /** * language of the user */ type: String, optional: true, },在代码层面,几乎所有需要读取用户语言的逻辑都经由Users.getLanguage()获取,它做了兜底回退,见 models/users.js:
getLanguage() { const profile = this.profile || {}; return profile.language || 'en'; },也就是说:未设置语言或写入非法语言代码的用户,最终都会回退到英文(en)。这也是批量修改语言前需要理解的第一条规则——直接写库不会报错,但写入的语言代码必须能被 TAPi18n(Meteor 的 i18n 包)识别,否则界面不会按预期切换。
官方方案:用 mongosh 批量修改所有用户语言
原文档给出的核心场景是:管理员希望强制所有用户(包括新注册、尚未设置语言或语言偏好不正确的用户)统一使用某一种语言。做法是绕过 Web 界面,直接用 MongoDB Shell 对users集合执行一次updateMany。
准备 mongosh
Wekan 的 Snap 版本自带私有 MongoDB 实例,监听在本地127.0.0.1:27019(注意不是默认的 27017)。执行批量更新前,需要先安装mongosh(MongoDB Shell)——它不再随 MongoDB 服务端捆绑,需单独从 MongoDB 官方下载页获取命令行二进制。
提示:Wekan 其他部署形态(如 Docker、源码运行)的数据库地址、端口以实际环境的
MONGO_URL配置为准;本文命令基于 Snap 候选版的默认端口 27019。
创建 language.sh 脚本
将下面的内容保存为language.sh(完整继承自 Change-Language.md):
mongosh --quiet \ --host 127.0.0.1 \ --port 27019 \ --eval 'use wekan' \ --eval 'db.users.updateMany({}, { $set: {"profile.language": "en-GB" }});'逐条参数解读:
| 参数 | 作用 |
|---|---|
--quiet | 抑制启动横幅与多余提示,只输出命令结果 |
--host 127.0.0.1 | 连接本机 MongoDB |
--port 27019 | Snap 版 Wekan 的私有 MongoDB 端口 |
--eval 'use wekan' | 切换到wekan数据库 |
--eval 'db.users.updateMany({}, {...})' | 对users集合全量更新:{}为匹配所有文档,$set将profile.language写为en-GB |
示例中将语言设置为en-GB(英式英语),官方文档特别说明这是为了把英文日期格式切换为DD/MM/YY。
赋予执行权限并运行
chmod +x language.sh然后执行:
$ ./language.sh { acknowledged: true, insertedId: null, matchedCount: 20, modifiedCount: 5, upsertedCount: 0 }读懂返回结果
上面是文档中一个真实运行场景的返回:当时共 20 个用户,其中 5 个新用户的语言尚未正确设置。MongoDB 返回的UpdateResult各项含义如下:
acknowledged: true:写入已被数据库确认;matchedCount: 20:匹配到了 20 个文档(全部用户);modifiedCount: 5:实际发生修改的只有 5 个——其余 15 个用户的profile.language本来就已经是en-GB(或已是同一值),$set写入相同值时 MongoDB 不会重复写入;upsertedCount: 0:updateMany不执行 upsert,因此恒为 0;insertedId: null:非插入操作,故为null。
理解modifiedCount的含义很重要:它统计的是"值真正被改变的文档数",而不是"被扫描到的文档数"。因此第二次运行同样的脚本,modifiedCount会变成 0,这是幂等更新(idempotent)的正常表现,可用于反复修复语言配置而不产生副作用。
语言如何影响日期格式:从 en-GB 说起
为什么文档要把语言设置为en-GB而不是en?因为 Wekan 中日期格式既受profile.dateFormat显式控制,也会跟随语言区域变化。用户模型里日期格式的默认值定义在 models/users.js:
getDateFormat() { const profile = this.profile || {}; return profile.dateFormat || 'YYYY-MM-DD'; },即默认日期格式为YYYY-MM-DD,但不同的语言/区域设置(以及可选的profile.dateFormat、profile.calendarSystem字段)会共同决定界面中日期的呈现。e2e 测试 44-calendar-date-display.e2e.js 正是通过组合写入profile.language、profile.calendarSystem、profile.dateFormat来验证日历与日期展示行为——例如测试中分别将语言设为en、ar(阿拉伯语,同时验证 RTL 日期布局)与lv(拉脱维亚语),逐一断言日期显示是否符合预期。这说明"改语言"与"日期格式变化"在 Wekan 中是强关联的一组配置。
语言字段的服务端校验链路
在 Web 界面内切换语言时,走的是Users.setLanguage()方法,见 server/models/users.js:
async setLanguage(language) { check(language, String); if (!this.userId) throw new Meteor.Error('not-logged-in', 'User must be logged in'); const TAPi18n = getTAPi18n(); if (!TAPi18n.isLanguageSupported(language)) { throw new Meteor.Error('invalid-language', 'Language is not supported'); } await Users.updateAsync(this.userId, { $set: { 'profile.language': language } }); },注意这条校验链路:服务端会先用TAPi18n.isLanguageSupported(language)校验语言代码是否受支持,不支持的代码会直接抛出invalid-language错误。而本文的 mongosh 方案是直接写库,绕过了这层校验——所以批量执行前务必确认目标语言代码与imports/i18n/data/目录下的语言文件名一致(例如en-GB、zh-CN、ja等),否则用户界面会回退到getLanguage()的默认值'en'。
此外还有一条隐性的语言传播规则:当有用户被邀请加入看板时,如果邀请者已设置语言,新用户会继承邀请者的profile.language,相关逻辑见 server/models/users.js。这解释了为什么"新用户语言没设对"是一种常见的初始状态,也说明批量脚本可以作为团队 onboarding 后的统一修正手段。
客户端如何决定界面语言(浏览器设置)
文档中提到的 "Language browser settings"(对应 Wekan issue #4518 的讨论)指向客户端语言解析逻辑。仓库实现位于 client/lib/i18n.js,其优先级顺序为:
- 当前登录用户的
profile.language(最优先,持久化的用户偏好); navigator.languages[0](浏览器首选语言列表第一项);navigator.language(浏览器语言);navigator.userLanguage(IE 等旧浏览器的语言属性)。
选出的候选语言会做"逐步剥离子标签"的降级匹配,例如zh-Hans-CN→zh-Hans→zh-Hans(命中即停),zh-Hant-TW→zh-Hant,裸的zh会经别名映射到zh-Hans;同时TAPi18n.isLanguageSupported不区分大小写,因此zh-hant、JA-JP等写法也能命中。
再配合 client/components/boards/boardsList.js:当用户访问看板列表页时,客户端会读取当前用户的profile.language并调用TAPi18n.setLanguage(userLanguage)应用界面语言。由此可以总结出完整生效链路:
mongosh updateMany(写库) → users.profile.language 更新 → 用户刷新/重新登录后客户端读取 profile → TAPi18n.setLanguage(language) 应用语言包 → 界面文案与日期格式按新语言渲染需要特别指出:直接改数据库不会让已登录用户立刻看到变化。客户端在启动时读取语言(client/lib/i18n.js 中的Meteor.startup+Tracker.autorun逻辑),因此批量修改后,用户需要刷新页面或重新登录才能让新语言生效。
语言代码来源与翻译维护
Wekan 的界面翻译以 imports/i18n/data/en.i18n.json 为英文源文件(其中包含"language": "Language"、"date-format": "Date Format"等关键条目),其他语言通过 Transifex 平台协作翻译。批量脚本中使用的语言代码必须与这些语言文件对应;完整的翻译工作流(新语言接入、新文案同步、发布前拉取)见 docs/Features/Translations/Translations.md。
在 e2e 测试中也能看到同样的"直接写库"手法:如 18-rtl-layout.e2e.js 通过db.updateOne('users', { _id: userId }, { $set: { 'profile.language': lang } })设置语言以验证从右到左布局;19-accessibility.e2e.js 分别设置zh-CN与ja验证不同语言下的无障碍属性。这些测试证明了profile.language字段是驱动 Wekan 多语言与 RTL 布局的单一事实来源(single source of truth)。
实战要点与注意事项汇总
- 确认数据库连接参数:Snap 版默认
127.0.0.1:27019;其他部署方式请以实际MONGO_URL为准,切勿在未确认端口的情况下执行。 - 语言代码必须合法:直接写库绕过
TAPi18n.isLanguageSupported校验,写入不存在的语言代码会导致界面回退英文。 - 幂等可重跑:
updateMany+$set可安全重复执行,modifiedCount为 0 即代表所有用户语言已一致。 - 生效时机:客户端在启动时读取语言,用户需刷新页面或重新登录;对长期在线的用户可考虑配合登录令牌失效机制。
- 区分用户偏好与全局策略:
setLanguage每次只改单个用户,而 mongosh 脚本是全局强制策略;如果希望尊重用户个人选择,应谨慎使用批量覆盖。 - 结合其他 profile 字段:如需同时统一日期格式或日历系统,可在同一
$set中追加profile.dateFormat、profile.calendarSystem字段(参见 44-calendar-date-display.e2e.js 的用法)。
通过上述步骤,管理员可以在几分钟内完成整个 Wekan 实例的语言统一,无论是修正新用户的默认语言、强制切换日期格式,还是为多语言团队做全局基线配置,都能安全、可重复地落地。
【免费下载链接】wekanThe Open Source kanban, built with Meteor. GitHub issues/PRs are only for FLOSS Developers, not for support, support is at https://wekan.fi/commercial-support/ . PR source translation to imports/i18n/data/en.i18n.json, other translations at https://app.transifex.com/wekan/wekan项目地址: https://gitcode.com/GitHub_Trending/we/wekan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考