【问题标题】:Is there any way go get GNU xgettext (or something similar) to work with scala files?有没有办法让 GNU gettext (或类似的东西)与 scala 文件一起工作?
【发布时间】:2020-05-03 07:05:31
【问题描述】:

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

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

5.1.3 输入文件语言的选择

‘-L 名称’

‘--语言=名称’ 指定输入文件的语言。

支持的语言有 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 文件?我发现 this sbt compiler plugin 可以满足我们的需要,但不幸的是我们使用的是 gradle 而不是 sbt。

【问题讨论】:

    标签: scala gradle gettext po xgettext


    【解决方案1】:

    我使用了一个非常简单的解决方案,我将 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 上下文,以及将其与具有相同文本的其他消息区分开来的消息的附加信息),@987654326 @ 表示指定 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 命令行参数也可以用于支持有关已翻译消息的 cmets,这对翻译人员非常有用。

    从实践中得到的更多观察结果并没有直接回答原始问题:

    • 如果我再次执行此操作,ttc、... 方法将不会直接返回翻译后的字符串,但有些 LocalizableMessage 封装了原始字符串和扩展参数,稍后可以延迟翻译通过适当的目录。
    • 我不使用方法tn(gettext 处理复数的方式)。我建议使用更通用的 ICU 消息扩展库或类似的东西。

    【讨论】:

      【解决方案2】:

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

      可以用 Java 编写解析器,并使用最少的 Perl 样板代码。我在一篇博文Extending Xgettext With Locale::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 项目的提取器。

      【讨论】:

      • 非常感谢您的详细回答。我们将需要讨论努力是否值得,但至少我现在知道可以做些什么。非常感谢!
      猜你喜欢
      • 1970-01-01
      • 2012-01-21
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 2010-09-12
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多