1

我们使用GNU gettext 实用程序直接从我们的代码库创建 PO 文件。然而,问题是我们的一些代码库是用 Scala 编写的(大部分是 Java)。我们正在使用 gradle 进行构建和部署。

据我所见,根据 xgettext 文档,Scala 不是受支持的语言:

5.1.3 输入文件语言的选择

'-L 名称'</p>

'--language=name' 指定输入文件的语言。

支持的语言有 C、C++、ObjectiveC、PO、Shell、Python、Lisp、EmacsLisp、librep、Scheme、Smalltalk、Java、JavaProperties、C#、awk、YCP、Tcl、Perl、PHP、GCC-source、NXStringTable、RST、 RSJ、Glade、Lua、JavaScript、Vala、GSettings、桌面。

有没有办法将 xgettext 用于 Scala 文件?我发现这个 sbt 编译器插件可以满足我们的需要,但不幸的是我们使用的是 gradle 而不是 sbt。

4

2 回答 2

2

我使用了一个非常简单的解决方案,我将 Vala 指定为 xgettext 的语言。在转义文字和函数调用语法方面,它与 Scala 非常接近。这不是一个严格的解决方案,但在我的实践中,它对我来说已经足够好了。

我有一个Po类保存消息目录,并允许我通过几个简单的方法执行翻译:

def t(singular: String): String = lookupSingular(None, singular)
def tf(singular: String, parameters: Any*): String = format(t(singular), Array(parameters: _*))
def tc(ctx: String, singular: String): String = lookupSingular(Some(ctx), singular)
def tcf(ctx: String, singular: String, parameters: Any*): String = format(lookupSingular(Some(ctx), singular), Array(parameters: _*))
def tn(singular: String, plural: String, n: Long): String = lookupPlural(None, singular, plural, n)
def tcn(ctx: String, singular: String, plural: String, n: Long): String = lookupPlural(Some(ctx), singular, plural, n)

t代表 Translate,f代表 Formatted(有参数),c代表 Context(意思是 gettext 上下文,以及将其与具有相同文本的其他消息区分开来的消息的附加信息),n代表指定 N 的复数。你可以编自己的名字。

这些方法既可用作执行翻译的方法,又可用作 xgettext 的标记,以.pot从源代码中提取文件。

我使用这样的:

new JMenuItem(po.t("Copy to clipboard"))
new JButton(po.tc("errorDialog", "Copy to clipboard"))
po.tf("Camera {0}", number),

等等

通过这个设置,我像这样运行 xgettext:

xgettext \
    --package-name="xxx" \
    -ktc:1c,2 \
    -ktcf:1c,2 \
    -ktnc:1c,2,3 \
    -ktf \
    -kt \
    -ktn:1,2 \
    -o "output.po" \
    $(find "DIRECTORY" -name *.scala) 2>&1 | grep -v "extension 'scala' is unknown; will try C"

重要的部分是-k参数,它将自定义 xgettext 关键字直接映射到我的方法名称。这样,xgettext 可以配置为使用自定义关键字。

但是,不支持 Scala 的三引号。xgettext 在遇到它们时会警告“未终止的文字”,但无论如何都会进行。

IIRC,甚至-c命令行参数也可以用来支持对已翻译消息的评论,这对翻译者来说非常有用。

实践中的一些观察结果并没有直接回答原始问题:

  • 如果我再次实现它,方法t, tc, ... 将不会直接返回翻译后的字符串,而是一些LocalizableMessage封装原始字符串和扩展参数的方法,稍后可以通过适当的目录懒惰地翻译。
  • 我不使用这些方法tn (gettext 处理复数的方式)。我建议使用更通用的 ICU 消息扩展库或类似的东西。
于 2020-05-16T06:44:58.660 回答
1

Perl 模块Locale::XGettext允许您为几乎每种文本格式编写自己的 xgettext 变体。您只需为能够提取字符串的语言/格式提供解析器。

可以在 Java 中使用最少的 Perl 样板代码编写解析器。我在一篇博文中描述了这个过程,用 Locale::XGettext 扩展 Xgettext。Java 中的示例提取器可在https://github.com/gflohr/Locale-XGettext/tree/master/samples/Java获得

免责声明:我是上述所有软件和文档的作者!

如果与 Perl 代码的接口听起来太复杂,您也可以使用您选择的语言为 Scala 编写解析器,在 xgettext 之前运行该解析器,然后将所有可翻译的字符串转储为您的版本可以xgettext理解的格式,例如 C:

gettext("Hello, world!");
gettext("Another string.");

xgettext然后,您只需将生成的虚拟源文件与构建设置中的其他源文件一起用作输入。

xgettext可能值得注意的是.po.pot即使您使用--language=java. 这意味着,.po或者.pot文件最适合从 Scala 文件中转储可翻译字符串,前提是您找到了生成.po/.pot文件的方法。

最后,gettext 工具的源代码设计为可扩展的。如果您能够在 C 中为其编写字符串提取器和格式检查器,则可以添加 Scala 语言。但是,您不能在运行时添加对另一种语言的支持,但您必须编译自己的版本xgettext或贡献您的提取器GNU gettext 项目。

于 2020-01-16T21:04:01.400 回答