原文:https://phrase.com/blog/posts/10-common-mistakes-in-software-localization/
国际化、本地化的概念在 马什么梅?I什么N?浅谈 web 前端开发中的国际化 一文中做过详细的介绍。如何避免误用本地化,可以注意以下 10 点:
将文字直接嵌入代码将极大地拖慢软件本地化的进度,翻译者不得不阅读代码以决定哪些段落需要翻译。同时,这将使得本地化代价高昂且翻译的一致性难以保证。
以 Python 为例,在 .po
资源文件中保存了每种 locale 的翻译:
# ./locales/en_US/LC_MESSAGES/messages.po
msgid "button_order"
msgstr "Order Now"
msgid "login_message"
msgstr "Welcome back!"
# ./locales/de_DE/LC_MESSAGES/messages.po
msgid "button_order"
msgstr "Jetzt bestellen"
msgid "login_message"
msgstr "Willkommen zurück!""
使用 gettext 函数完成翻译:
import gettext
de_DE = gettext.translation('messages', localedir='locales', languages=['de_DE'])
de_DE.install()
print(gettext("login_message"))
# Willkommen zurück!
print(gettext("button_order"))
# Jetzt bestellen
不同的语言文字有着迥异的长度和密度。
如果对此一无所知,就可能在本地化过程中造成没有足够的布局空间,文字可能会超出控件,从而不得不在翻译后重新调整设计。
各个国家有各个国家的国歌,而各个国家的国歌可能是由同一种语言演唱的。
有时同一种语言会根据使用它的国家不同而有所区别,因为不同的地域会造成口语和拼写的微妙差别(如 en-GB 和 en-US)。仅指定了语言,而不指定国家代码,会让本地化变得困难。
所以总是应该使用完整的 locale,比如:
# ./locales/en_US/LC_MESSAGES/messages.po
msgid "login_message"
msgstr "Hi there!"
# ./locales/en_AU/LC_MESSAGES/messages.po
msgid "login_message"
msgstr "G'Day Mate!"
有些开发者喜欢将字符串拼接,虽然字段的常量部分是从资源文件取出的,但整个句子的单词顺序和措辞结构还是被按某种特定语言硬编码了。
在这个反面例子中,仅仅是在一个固定的结构中将句子打散为小块:
msgid "welcome_back_msg_start"
msgstr "Hey "
msgid "welcome_back_msg_end"
msgstr ", welcome back!"
print(gettext('welcome_back_msg_start') + username + gettext('welcome_back_msg_end'))
# Hey John, welcome back!
一方面,这种文字游戏有时很难甚至无法被翻译,也会让翻译者对你的胡闹心怀怨恨,因为没有人喜欢因为拼接过多带来的猜字游戏;另一方面,同一句话的前后结构可能完全不同,这使得翻译完全无法进行。
合理的做法是对整句进行本地化,并使用占位符传入变量:
msgid "welcome_back_msg"
msgstr "Hey %(username)s, welcome back!"
print(gettext('welcome_back_msg', username="John"))
# Hey John, welcome back!
当你使用了一个错误的或无法处理 Unicode 的字符编码时,翻译工作也将失败。
编程语言经常使用系统默认的编码存储文件,当你的服务器是英文环境而你的用户以中文浏览器访问时,显示的字符可能就会出错。
总是应该使用 UTF-8
因此,另一个本地化的最佳实践就是一直用 UTF-8。这几乎总是最佳选择,因为它通过使用跨浏览器和服务器的标准化编码解决了问题。所以,理想情况下,你的技术栈中间的每一层都应该使用 UTF-8:无论是 HTML、HTTP 服务器、数据库以及你的应用本身莫不如此。例如:
<meta http-equiv="content-type" content="text/html; charset=utf-8">
Content-Type: text/html; charset=utf-8
# MySQL
CREATE DATABASE dbname CHARACTER SET utf8 COLLATE utf8_general_ci;
软件国际化并不是仅仅翻译单词 -- 这关乎整个文化的适配。
因为不同语言和不同国家的差异,硬编码日期、时间或货币格式会在翻译过程中带来麻烦。26.04.2015
或 04.26.2014
?14:00
或是 2 p.m.
?1,000 英里
还是 1,609 公里
?
使用专业的工具库来处理国际化中的数字、货币、单位、日期和时间
比如使用了 Python babel 库的一个例子:
from babel.dates import format_datetime
from babel.numbers import format_currency
print(format_datetime(locale='ru_RU'))
# 26 июля 2013 г., 15:48:18
print(format_currency(10.50, 'EUR', locale='de_DE'))
# 10,50 €
print(format_currency(10.50, 'USD', locale='en_AU'))
# US$10.50
阿拉伯文、希伯来文和一些其他语言是从右到左书写的;一些东亚语言比如某些中文文本,或传统蒙古文,也会让你大开眼界 -- 它们有着竖版书写的悠长历史。如果有必要服务于足够多的地区,就要准备好应对上述这些排版方式。
从右到左可能还能通过反向字符串解决;但当字符串竖版排练时,并非简单地旋转 90 度。比较正确的方式是基于 locale 在资源文件中包含一个指示方向的字符串,并根据其调用不同的 CSS 样式。例如:
h1 {
direction: rtl;
}
<h1>
Read me from right-to-left.
</h1>
当字符串包含变量,且被用在一个特定上下文或使用了有歧义的措辞时,你的翻译团队就不好过了。翻译者通常基于无上下文格式的文件和字符串工作。所以,他们难以感知单个术语“联系”是个动词还是个按钮名称。
合理运用图片可以有效降低本地化成本,因为易于理解的图片减少了描述清楚一件事所需的文本数量。但有时候包含文字的图片会让翻译者抓狂,甚至会让你为翻译付出的金钱成本倍增。
还有一种小的错误可能会妨碍软件在其他语言下正常工作。如果源内容本身存在错误,可能会导致翻译后的其他若干种语言连带出现同样或更严重的错误,而修复这些不同的语言则会花费数倍时间。
总之,基于源语言开发软件时,就应该时刻保持本地化意识。如果你能有效避免上述 10 种常见陷阱并遵守文中提到的最佳实践,你的应用就能顺利本地化并能随时拥抱国际市场。