翻译
翻译(Translations)
目录
翻译 Wavelog 是一项庞大的工作,需要社区持续不断的贡献。除了我们的基础语言英语之外,目前已有 26 种附加语言处于部分翻译状态(2025 年 3 月)。为了改进译文并在将来加入更多语言,我们需要所有用户以及国际业余无线电社区的帮助。
为了让 Wavelog 的翻译尽可能简单,我们不再使用 CodeIgniter 内置的语言引擎,转而使用 gettext() 和 po 文件,这为我们的开发流程带来了巨大的好处。
此外,我们还基于开源软件 Weblate 搭建了一个平台,帮助那些不擅长直接处理代码的贡献者。在本 wiki 中,我们要说明如何翻译 Wavelog,让它能为尽可能多的国家所使用。
在翻译平台上找不到你的语言?没问题!发邮件至 translation@wavelog.org,我们会把你的语言加入 Wavelog。
使用我们的 Weblate 平台
开始翻译最简单的方式是使用我们的翻译平台 https://translate.wavelog.org。创建一个账户,然后开始翻译你的语言。你也可以在这里修改错误的译文并加以更正。请记住,有些译文本来就是那样写的。
你的译文会在 24 小时后被自动包含进提交到 dev 分支的 PR(拉取请求)中。
所以你除了翻译之外无需做任何其他事情。就这么简单 :)
手动翻译或使用其他软件翻译(不推荐)
如果你熟悉「Poedit」之类的软件,或者更喜欢直接在代码中翻译,可以按以下步骤操作。
在 GitHub 上创建 fork,并把你的 fork 仓库克隆到本地电脑。然后你可以下载语言文件并用「Poedit」之类的软件编辑,也可以手动编辑。语言文件位于
application/locale/[language code]/LC_MESSAGES/messages.po
例如德语语言文件是 application/locale/de_DE/LC_MESSAGES/messages.po。
编辑完文件后,把改动提交到你的仓库,并向 dev 分支创建 PR(拉取请求)。
警告:PR 中不得包含 *.mo 文件!
绝不要把
mo文件包含进该 PR。PR 合并后,我们会自动在仓库中直接生成 mo 文件。要在本地测试译文,你可以运行位于 Wavelog 主目录中的脚本po_gen.sh,它会为你生成 mo 文件。只需推送你手动修改过的文件。不要包含mo文件或由该脚本生成的文件。
附加内容:在 PHP 中添加新字符串
对于想在 PHP 中添加新字符串的开发者,可以使用经典的 gettext() 函数,其语法略有不同。由于我们使用 gettext 的模拟实现以兼容 CodeIgniter,你需要添加下划线 _ 作为前缀。
在 PHP 代码中添加好 gettext 函数后,你只需运行位于 Wavelog 主目录中的脚本 po_gen.sh。它会生成所有必要的 pot/po 文件,也会编译 mo 文件,但请记住不要把 mo 文件加入 PR(拉取请求)。
./po_gen.sh
函数
我们主要使用四个不同的函数在视图中显示文本。
提示: 在 .po 文件中使用双引号
"会有问题,因为我们无法用\转义它们。如果消息字符串中出现反斜杠,从 po 编译到 mo 的编译器就会失败。因此我建议在函数中始终使用双引号,以避免语法错误(例如用__("Text")而不是__('Text'))
__($string) 「双下划线」
这是 gettext 的基础函数。它会查找译文,如果找不到,就直接显示字符串的内容。在我们的例子中,源语言是英语。
示例
<?php
__("Hello World!") or _gettext("Hello World!")
// Prints out:
"Hello World!"
_ngettext($singular, $plural, $integer)「单数与复数」
用于实现能识别单数和复数的动态语言。用 _ngettext() 函数即可轻松实现。这里的关键是第三个参数 $integer,它必须是整数,否则会报错。为避免这种情况,当变量是字符串时我们可以使用 intval()。
示例
<?php
_ngettext("Banana", "Bananas", 2);
// Prints out Plural because integer is > 1:
"Bananas"
$apples = '1';
_ngettext("Apple", "Apples", intval($apples));
// Prints out Singular because integer is = 1:
"Apple"
_pgettext($context, $string)「上下文助手」
该函数为译者提供附加信息。在某些情况下,一个英语单词在目标语言中可能有不止两种含义。另一种用途是当文本可能不完整时提供特定的上下文。在这些情况下,用 _pgettext() 函数为译者提供附加信息是良好实践。因此,每当字符串的含义可能不清楚时,就用 _pgettext() 提供一些附加信息。这有帮助而无害。
示例
<?php
_pgettext("Noun; Metal", "lead");
// Prints out:
"lead"
// But the german translator knows to translate it as "Blei"
_pgettext("Verb; Lead someone", "lead");
// Prints out:
"lead"
// But the german translator knows to translate it as "führen"
sprintf($string_with_placeholder, $placeholder_string)「构建器」
这不是 gettext 的函数,但我们现在确实需要它。原因是出于安全考虑,我们不希望在翻译文件或编译后的 .mo 二进制文件中出现 URL。为了构建内联文本链接,我们可以用 sprintf() 把变量和其他内容放入译文。这是常见做法,而且非常简单。
<?php
sprintf(__("Click %shere%s to visit the website."), '<a href="https://www.wavelog.org" target="_blank">', '</a>');
Prints out in HTML:
'Click <a href="https://www.wavelog.org" target="_blank">here</a> to visit the website.'
字符串用 %s,整数或浮点数用 %d。你也可以在函数中放置多个占位符,它们会按你定义的顺序依次放入。
<?php
sprintf(__("Link %s, Link %s, Link %s, Number %d, Number %d"), "A", "B", "C", 1, 2);
// Prints out:
"Link A, Link B, Link C, Number 1, Number 2"
