从 CoSign 看开源软件本地化(1)
开源软件本地化,一般来说都是 a piece of cake。但是 CoSign (密歇根大学开发的单点登录系统)的本地化却是让我们大费周折,很是经历一些往复。
CoSign 是用 C 语言开发的,其 web 服务也是通过 C 语言开发的 CGI 来提供,而Web 页面是通过页面模板加载经过处理后形成的。CoSign 本身并没有提供多语言支持,但是模板可以用户自定义,就是说可以用中文来写 web 页面模板。
在我们最早的版本中,采用的是:多模板(根据语种自适应选择),以及 Apache 的内容协商实现的多语种支持。
在最近我们通过 Gettext 在底层实现了本地化,又通过精简模板,静态页面模板化等方法让单点登录页面定制更简单。
我们在 CoSign 本地化中所经历的,在我们众多开源产品的本地化中是最复杂和独特的,因此撰文共享。
模板自适应选择
正如之前所说,CoSign 的 web 服务是由一些用 c 语言写的 CGI 来提供,这些 CGI 会读取页面模板文件,经过处理后,动态产生 web 页面。 页面模板位于 /opt/cosign/lib/templates-local 目录下。缺省包含如下模板文件:- login.html 登录页面模板
- login_error.html 登录过程中出现错误时,使用的模板。和 login.html 相比只是多了一处显示错误的区域( id 为 "error" 的 DIV)。
- reauth.html 双因子认证,或者由于IP地址变更等语言需要的二次登录页面
- error.html 显示系统错误的页面模板
- expired_error.html 口令过期错误的页面模板
- verify-logout.html 退出登录前,提示用户确认的页面模板
- 模板的加载和替换,是由文件 cgi/subfile.c 的 subfile() 函数实现的
- 模板文件的加载缺省都是在一个目录下完成的: /opt/cosign/lib/templates-local。
- 多模板支持只需要在 subfile() 函数的文件加载时,根据语种选择不同的模板目录。例如中文选择 /opt/cosign/lib/templates-local/zh 不就可以了么?
- 而且这么做对代码的侵入最小。
- 增加一个叫做 lang.c 文件,提供 get_accept_language() 函数,返回浏览器支持的语种列表
- 在 subfile() 函数中依次对语言列表中的语言进行尝试,如果发现存在相应语言的模板文件,就读取相应文件,提供给客户本地化语言的页面展示
- 当由于口令错误等原因认证失败时,页面显示的错误信息仍然是英文!
- 这些英文出错信息是认证因子(factor)返回的出错信息,直接替换掉模板中的 $e 宏。
- 认证因子是脱离 Web 服务器执行的,不可能在认证因子本身中实现本地化!
- 每个语言都需要定制一系列的模板,如前所述,包括: login.html, login_error.html, 等等
- 模板之间的冗余度非常之高,经常出现一个小小的改动,要打十来个文件,一一重复的去修改。这时因为我们同时支持两套风格的页面模板(经典式和Google式),以及两个不同语种(英文和中文)