Where to place i18n key strings in Java

前端 未结 8 2820
不思量自难忘°
不思量自难忘° 2021-02-20 04:10

When doing internationalization in Java, you assign a string key to each message. What\'s the best practice, on where to place those string keys. Goal is to allow easy refactori

8条回答
  •  抹茶落季
    2021-02-20 04:28

    Basically, it seems that we all agree that some kind of constant is needed. When it comes to constants, I strongly prefer Enums. Java Enums are very powerful and definitely underused:

    String title = Messages.getString(RunDialogMessages.TITLE);
    

    OK but what I had to do to make it look like this? A simple interface, an enum and slight modification to standard message access routine. Let's start with the interface:

    public interface MessageKeyProvider {
        String getKey();
    }
    

    The enum:

    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;
        }
    }
    

    And modified getString() method:

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

    Just to complete the picture, let us see RunDialog.properties (I will make a point about it soon):

    RunDialog.Title=Run
    RunDialog.Prompt.Label=Enter the name of the program to run:
    RunDialog.Run.Button=Run
    RunDialog.Cancel.Button=Cancel
    

    Obviously, you could use Enum to read from properties file (by embedding ResourceBundle), however it would probably violate Single Responsibility Principle (as well as Don't Repeat Yourself, as access code would need to be repeated).

    Going back to properties file, I had a feeling (I might be wrong here), that one of your goals was to avoid duplicating the translations. That's why I put two Runs in example above. You see, this word would be translated in a different way depending on the context (which is actually quite common). In this example, if I were to translate that to Polish it would look like this:

    RunDialog.Title=Uruchamianie
    RunDialog.Prompt.Label=Wpisz nazwę programu do uruchomienia:
    RunDialog.Run.Button=Uruchom
    RunDialog.Cancel.Button=Anuluj
    

    That is unfortunate problem of some strange language that have a concept of conjugation...

提交回复
热议问题