关于java:我应该在代码中使用英文消息还是消息名称进行国际化?

Should I use english messages or message names in the code for internationalization?

我和一个朋友正在启动一个新的软件项目(使用Java),我们正在考虑如何对GUI进行国际化。虽然我更喜欢在代码中使用带有占位符的英语字符串,如下所示:

1
gettext("$name invites you to join $room", invitation.whose, invitation.roomname)

,我的朋友希望代码中仅包含一个标识符,例如invitation_message。我的观点是,当英语字符串更改时,含义可能也会有所更改,因此旧的翻译不再有效。但是,他认为消息应该与代码分开。

那么,您首选哪种方法,为什么呢?还是您甚至有完全不同的建议?


这取决于。您的问题有很多事情,我不确定是否理解正确。

  • 您的朋友想将编程逻辑与可翻译字符串分开。嗯,这就是Java的标准I18n资源(通过ResourceBundle)的工作方式。如果要使用标准工具或命令(例如Eclipse中的Externalize Strings),坦率地说,这是唯一的方法。
    但是,有些人认为在源文件中包含密钥,并且许多rb.getString(key)都会破坏代码。当然,包含英文字符串的代码更具可读性。而且您已经有了它们,因此您不必冒着看到密钥而不是真实消息的风险。具有这种情况的所有利弊。
    如果您坚持使用gettext,某些工具可能会将这些字符串报告为硬编码...

  • 我想知道您的意思是"虽然我希望在这样的代码中使用带有占位符的英语字符串" \\ ...您的朋友是否更喜欢不使用占位符?那不是一个好主意。由于目标语言的语法规则,人们实际上可能需要在翻译过程中对句子重新排序,因此在您的示例中," $ room "可能位于" $ name "之前。

  • 回到代码-可翻译字符串的分离,标准的i18n Java编程指南是将可翻译字符串与编程逻辑完全分离。而且,除非有充分的理由,否则您应该遵循准则。


    我更喜欢gettext方法,我的理由在我自己的i18n库的github页上列出,标题为"为什么使用gettext而不是属性包" \\:

    • 为每个消息发明一个密钥的需要中断了程序员的流程。
      有时候,已经很难想到有意义的变量名了,
      不得不考虑一些与代码完全无关的东西,例如
      翻译进一步分散了程序员的注意力。

    • gettext中的复数处理对于某些具有更多功能的语言而言是优越的
      而不是两个复数形式。对于简单的情况,可以使用
      ChoiceFormat,但是像波兰语这样的语言需要更复杂的规则。
      另外,ChoiceFormat的语法可能会很复杂,因为
      非开发人员。

    • 有专门的编辑器来编辑gettext文件,这些编辑器也可以
      可供非程序员使用。这些编辑器具有广泛的功能来支持
      译者,例如记住已经翻译过的字符串或包含一个
      术语数据库。


    在Java生态系统中,GNU gettext并未得到广泛使用。它具有基于ResourceBundle类的自己的i18n机制,该机制有些抽象,并且不仅包含文本。

    为文本定义资源束的最常见方法是在属性文件中,并且这些属性中的键不能包含空格,这基本上排除了您的首选样式。

    我实际上喜欢GNU gettext样式,但是不使用平台标准是不值得的。


    您的朋友是正确的。如果您的消息是用Java源代码硬编码的,那么您要如何实现i18n?在代码中,您只能使用占位符:

    1
    gettext("invitation_message", invitation.whose, invitation.roomname)

    ,并且您应该在代码库之外的某个地方有单独的翻译文件:

    • messages_en.properties

      1
      invitation_message=$name invites you to join $room
    • messages_pl.properties

      1
      invitation_message=$name zaprasza ci? do wst?pienia do $room

    另请参见国际化官方教程。