在Java中放置i18n键字符串的位置

Phi*_*ipp 11 java internationalization

在Java中进行国际化时,为每条消息分配一个字符串键.什么是最佳实践,在哪里放置这些字符串键.目标是允许简单的重构(例如,密钥名称更改),清晰可读的代码,关注点的分离,但即使从代码的不同部分调用,仍然没有重复的密钥/消息.

//bad way, strings directly in code
messages.getString("hello_key");
Run Code Online (Sandbox Code Playgroud)

-

// better way, use String constants
public static final String HELLO_KEY = "hello_key";
...
messages.getString(HELLO_KEY);
Run Code Online (Sandbox Code Playgroud)

-

// other (better?) way, put all keys in one huge central class
public class AllMessageKeys {
  public static final String HELLO_KEY = "hello_key";
  ...
}

public class Foo {
  ...
  messages.getString(AllMessageKeys.HELLO_KEY);
}
Run Code Online (Sandbox Code Playgroud)

-

// other (better?) way, put all keys in neighbor class
public class FooMessageKeys {
  public static final String HELLO_KEY = "hello_key";
}

public class Foo {
  ...
  messages.getString(FooMessageKeys.HELLO_KEY);
}
Run Code Online (Sandbox Code Playgroud)

还有其他建议吗?哪个最好?我在Eclipse IDE上,如果这使得重构部分更清晰.

澄清:在上面的示例中,"messages"的类型为ResourceBundle.

Paw*_*yda 7

基本上,似乎我们都同意需要某种常数.说到常量,我更喜欢Enums.Java Enum功能非常强大,并且未得到充分利用:

String title = Messages.getString(RunDialogMessages.TITLE);
Run Code Online (Sandbox Code Playgroud)

好的,但我必须做些什么才能让它看起来像这样?简单的界面,枚举和对标准消息访问例程的轻微修改.让我们从界面开始:

public interface MessageKeyProvider {
    String getKey();
}
Run Code Online (Sandbox Code Playgroud)

枚举:

public enum RunDialogMessages implements MessageKeyProvider {
    TITLE("RunDialog.Title"),
    PROMPT("RunDialog.Prompt.Label"),
    RUN("RunDialog.Run.Button"),
    CANCEL("RunDialog.Cancel.Button");


    private RunDialogMessages(String key) {
        this.key = key;
    }

    private String key;

    @Override
    public String getKey() {
        return key;
    }
}
Run Code Online (Sandbox Code Playgroud)

并修改getString()方法:

public static String getString(MessageKeyProvider provider) {
    String key = provider.getKey();
    try {
        return RESOURCE_BUNDLE.getString(key);
    } catch (MissingResourceException e) {
        return '!' + key + '!';
    }
}
Run Code Online (Sandbox Code Playgroud)

只是为了完成图片,让我们看一下RunDialog.properties(我会尽快说明一下):

RunDialog.Title=Run
RunDialog.Prompt.Label=Enter the name of the program to run:
RunDialog.Run.Button=Run
RunDialog.Cancel.Button=Cancel
Run Code Online (Sandbox Code Playgroud)

显然,您可以使用Enum从属性文件中读取(通过嵌入ResourceBundle),但它可能违反单一责任原则(以及不要重复自己,因为访问代码需要重复).

回到属性文件,我有一种感觉(我可能在这里错了),你的目标之一是避免重复翻译.这就是为什么我在上面的例子中放两个运行.你看,这个词会根据上下文以不同的方式翻译(实际上很常见).在这个例子中,如果我要将其翻译为波兰语,它将如下所示:

RunDialog.Title=Uruchamianie
RunDialog.Prompt.Label=Wpisz nazw? programu do uruchomienia:
RunDialog.Run.Button=Uruchom
RunDialog.Cancel.Button=Anuluj
Run Code Online (Sandbox Code Playgroud)

这是一个有着共轭概念的奇怪语言的不幸问题......


moo*_*ooh 1

我总是使用列出我的密钥的界面来处理此类内容。Interace 的名称主要是 DESC=Issue/short description/topic 和键值。通过这种方式,您可以制作一些漂亮的界面和一些通用界面,例如用于确定或中止键的界面。

// other (better?) way, put all keys in neighbor class
public interface DESCMessage {
  public static final String HELLO_KEY = "hello_key";
}

public class Foo {
  ...
  messages.getString(DESCMessage.HELLO_KEY);
}
Run Code Online (Sandbox Code Playgroud)

  • 我对此的评论是它与“界面描述类型”“最佳实践”(Checkstyle,Bloch)背道而驰。 (3认同)