有没有一种半自动的方法来执行i18n的字符串提取?

2022-09-04 22:41:15

我们有一个Java项目,其中包含大量用于用户提示,错误消息等的英语字符串。我们希望将所有可翻译的字符串提取到属性文件中,以便以后可以翻译它们。

例如,我们希望替换:

傅.java

String msg = "Hello, " + name + "! Today is " + dayOfWeek;

跟:

傅.java

String msg = Language.getString("foo.hello", name, dayOfWeek);

语言.属性

foo.hello = Hello, {0}! Today is {1}

我知道以完全自动化的方式做到这一点几乎是不可能的,因为不是每个字符串都应该被翻译。但是,我们想知道是否有一种半自动化的方法可以消除一些费力。


答案 1

您需要的是一个工具,它将涉及字符串串联的每个表达式替换为库调用,而表达式的明显特例仅涉及单个文本字符串。

一个程序转换系统,您可以在其中表达所需的模式可以做到这一点。这种制度接受以下形式的规则:

         lhs_pattern -> rhs_pattern  if condition ;

其中,模式是对模式变量具有语法类别约束的代码片段。这会导致工具查找与lhs_pattern匹配的语法,如果找到,则替换为rhs_pattern,其中模式匹配基于语言结构而不是文本。因此,无论代码格式,缩进,注释等如何,它都可以工作。

按照示例的样式草绘一些规则(并过度简化以保持简短):

  domain Java;

  nationalize_literal(s1:literal_string):
    " \s1 " -> "Language.getString1(\s1 )";

  nationalize_single_concatenation(s1:literal_string,s2:term):
    " \s1 + \s2 " -> "Language.getString1(\s1) + \s2"; 

  nationalize_double_concatenation(s1:literal_string,s2:term,s3:literal_string): 
      " \s1 + \s2 + \s3 " -> 
      "Language.getString3(\generate_template1\(\s1 + "{1}" +\s3\, s2);"
   if IsNotLiteral(s2);

这些模式本身被括在“...”中;这些不是Java字符串文字,而是一种对多计算机语言模式匹配引擎说“...”内部的suff的方式。是(域)Java 代码。元事物用 \ 标记,例如,元变量 \s1、\s2、\s3 和嵌入式模式调用 \generate with ( and ) 以表示其元参数列表 :-}

请注意在元变量 s1 和 s3 上使用语法类别约束,以确保仅匹配字符串文本。元变量在左侧模式上匹配的内容在右侧被替换。

子模式generate_template是一个过程,该过程在转换时(例如,当规则触发时)将其已知为常量的第一个参数计算到您建议的模板字符串中并插入到库中,并返回库字符串索引。请注意,生成模式的第一个参数是此示例完全由串联的文本字符串组成。

显然,有人将不得不手动处理最终进入库中的模板化字符串,以生成外语等效项。
你是对的,因为这可能会过度模板化代码,因为某些字符串不应该放在国有化的字符串库中。只要您可以为这些情况编写编程检查,就可以将它们作为条件包含在规则中以防止触发它们。(只需稍加努力,您就可以将未转换的文本放入注释中,从而使以后更容易撤消各个转换)。

实际上,我想你必须像这样编写大约100条规则来涵盖组合学和兴趣的特殊情况。好处是您的代码会自动增强。如果操作正确,您可以在代码经历多个版本时重复将此转换应用于代码;它将把以前国有化的表达方式单独留下来,而只是修改那些快乐的幸运程序员插入的新表达方式。

可以做到这一点的系统是DMS软件再造工具包。DMS可以解析/模式匹配/转换/漂亮打印许多语言,包括Java和C#。


答案 2

Eclipse 将外部化每个单独的字符串,并且不会像您正在寻找的那样自动构建替换。如果你对如何构建字符串有一个非常一致的约定,你可以编写一个perl脚本来对.java文件进行一些智能替换。但是,如果您想处理,此脚本将变得非常复杂

  • String msg = new String(“Hello”);
  • 字符串 msg2 = “Hello2”;
  • String msg3 = new StringBuffer().append(“Hello3”).toString();
  • 字符串 msg4 = “Hello” + 4;
  • 等。

我认为有一些付费工具可以帮助解决这个问题。我记得评估过一个,但我不记得它的名字。我也不知道它是否可以处理外部字符串中的变量替换。我将尝试查找信息并使用详细信息编辑此帖子。

编辑:该工具是Lingport的Globodyzer。该网站说它支持字符串外部化,但没有具体说明如何。不确定它是否支持变量替换。有一个免费的试用版,所以你可以尝试一下,看看。