起因:Transifex 这货闭源一段时间后突然开始抢钱了。

正巧一堆开源项目需要一个在线协作的翻译平台,于是测试了几个比较知名的开源程序。一遍折腾下来,发现 Weblate 可以最大化满足要求。顺便提一句,Weblate 也是有 hosted 付费服务的,但是在预算内的源字符串等限制依旧太多,所以选择使用他们的源码来搭建一套。

以及:我讨厌 Docker。

Weblate 文档 提供了非常全面的从起步到上手到各种高级用法的指南,因此这里不多赘述安装的过程。只记录少许踩过的坑。

这套程序看似简单,但实际上是基于 Django、使用了一大堆组件的复杂程序。如果想保持 system clean,最好(最快)的办法还是使用 Docker。

准备

小型实例只需要一台虚拟机即可。但是即便只托管几个项目,它依旧会吃掉 2 个 CPU 核心和 4GB 内存,和曾经开源版的 Transifex 有得一拼 大概也解释了为何这类服务都死贵

如果是托管在公网上的实例,则推荐使用 HTTPS。Weblate 的 Docker compose 提供了 HTTPS 支持,稍后会提到。

安装 Git, Docker 和 docker compose,在一些软件仓库中一般是 docker-cedocker-compose,其他软件均不需要手动安装。

搭建

首先克隆 docker compose 配置到本地

1
2
git clone https://github.com/WeblateOrg/docker.git weblate-docker
cd weblate-docker

为了直接开始使用 HTTPS,现在需要先建立域名解析记录,将要使用的域名(例如 weblate.example.com)指向服务器 IP。然后在该目录下创建配置文件 docker-compose-https.override.yml 内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: '2'
services:
weblate:
environment:
- WEBLATE_DEBUG=0
- WEBLATE_EMAIL_HOST=smtp.gmail.com
- WEBLATE_EMAIL_HOST_USER=noreply@weblate.org
- WEBLATE_EMAIL_HOST_PASSWORD=system.email.password.here
- WEBLATE_ALLOWED_HOSTS=weblate.example.com
- WEBLATE_SERVER_EMAIL=noreply@weblate.org
- DEFAULT_FROM_EMAIL=noreply@weblate.org
- WEBLATE_REGISTRATION_OPEN=0
- WEBLATE_TIME_ZONE=UTC
- WEBLATE_OFFLOAD_INDEXING=1
- WEBLATE_REQUIRE_LOGIN=1
- WEBLATE_ADMIN_NAME=Weblate Admin
- WEBLATE_ADMIN_EMAIL=admin@weblate.org
- WEBLATE_ADMIN_PASSWORD=your+initial+password
https-portal:

environment:
DOMAINS: 'weblate.example.com -> http://weblate'

这份配置文件指定了:

  • 关闭 Django DEBUG mode (即生产模式)
  • 系统外发邮件服务器 smtp.gmail.com
  • 系统外发邮件用户名 noreply@weblate.org
  • 系统外发邮件密码 system.email.password.here
  • 允许使用的域名 weblate.example.com,如果有多个域名,使用逗号隔开
  • 系统外发邮件地址 noreply@weblate.org
  • 关闭注册通道,用户必须管理员手动添加
  • 设置系统时间为 UTC
  • 打开后台索引,降低运行时的负载
  • 执行任何操作前要求登陆
  • 默认管理员名称是 Weblate Admin
  • 默认管理员邮箱地址是 admin@weblate.org
  • 默认管理员密码是 your+initial+password

然后在 https-portal 容器中指定了要使用 SSL 的域名 weblate.example.com 和后端指向的容器 http://weblate

在当前目录中执行

1
docker-compose -f docker-compose-https.yml -f docker-compose-https.override.yml up

会顺序拉取、启动 4 个 docker 容器,分别是:

  • https-portal
  • weblate
  • postgresql
  • memcached

第一次启动需要一些时间拉取镜像并导入初始数据。全部完成后,访问 weblate.example.com 应该可以看到一个 HTTPS 的 Weblate 实例运行,使用之前定义的默认管理员邮箱地址和密码即可登入。

此时转回终端,按一次 ^C 等待四个容器正确关闭,然后编辑 docker-compose-https.override.yml,删除以下配置

  • WEBLATE_ADMIN_NAME
  • WEBLATE_ADMIN_EMAIL
  • WEBLATE_ADMIN_PASSWORD

否则,如果更改了默认管理员的信息(如用户名等)下次启动会再次创建管理员帐号,并使用相同的邮箱,导致默认管理员无法使用邮箱登陆(报错返回 2 个用户信息)。解决办法是使用用户名…(摔

集成配置

再次运行 docker-compose -f docker-compose-https.yml -f docker-compose-https.override.yml up 后可以很快启动所有需要的程序。此时登入 Weblate 实例,指向 /admin/ssh/ 点击创建 SSH 密钥。

在对单一 repo 提交的情况下,此 SSH Key 可作为 GitHub deploy key,但是如果需要多个不同 repo 提交时,有两种方法:

  • 创建一个 GitHub 用户,然后将此 SSH Key 添加到此用户下,再给此用户所有必要的写权限
  • 使用 Access Token 作为 HTTPS 密码访问必要的 repo

浏览器指向 /admin/trans/project/ 新建一个 Project。这个 Project 不仅指一个项目,也可以作为一个 Organization 的存在,更精确的解释是一个软件集,例如 KDE 套件可以包含一大堆的组件。

Weblate Project

指向 /admin/trans/subproject/ 这里才是可以添加要翻译的项目的地方。如果对应的 repo 添加了公钥,这里可以直接使用 SSH 方式的 push URL。

Weblate Import strings

File mask 填写所有语言文件相对 repo root 的路径,使用 * 代替语言代号。如果是 Monolingual language file,例如 key 是 user.info.comment_posted 这样而非原本即可阅读的文本,则 Monolingual base language fileBase file for new translations 均为源语言文件相对 repo root 的路径,这样即可正确识别源语言的字符串不至于让别人拿着 comment_posted 这样的 key 来猜意思

Weblate Translation Interface

持续集成

提交翻译后,Weblate 会在后台完成索引并提交必要的更改。当然也会一不小心刷了别人的屏…

Weblate continous translation

在 repo 的 settings -> integration 中可以添加 Weblate 作为集成,每次有新的提交即可触发 Weblate 更新源语言文件。

结论

我很开心可以省下每年数千美元来用一个非常卡的在线协作翻译平台

当然,我依旧讨厌 Docker。