I'm trying to make a multi-language app with messages inside multiple *.properties
files. I've started working on something like this:
public Language(@NotNull Map<String, String> info) {
Validate.notNull(info, "Language information cannot be null");
this.PLUGIN_PREFIX = info.get("PLUGIN_PREFIX");
this.ARGUMENT_CODE = info.get("ARGUMENT_CODE");
// etc...
}
Now, there's a lot of messages, and I don't feel like typing the same thing each time (plus there could me typos which could be an issue...).
The first solution I thought of was to loop through all of the fields that are like that (in caps, final, not static, etc.) and then use reflection to use the field name as a key to set it as the value. Obviously the compiler won't let me because it thinks that the final field hasn't been initialized.
Something like this:
public Language(@NotNull Map<String, String> info) {
Validate.notNull(info, "Language information cannot be null");
Field[] fields = /* TODO get fields */ new Field[0];
for (Field f : fields) f.set(f.getName(), info.get(f.getName()));
}
Is there a way this can work? Or is there a better solution?
Edit: Quick naming conventions question, should these final "constants" be in upper case?
CodePudding user response:
Usually, you don't store text messages directly in constants, but rather just message keys. Then you use these keys to fetch the actual text messages in the map.
You can use a map directly, but in Java, there is ResourceBundle. A ResourceBundle can be loaded directly from a .properties file.
my-bundle_en.properties:
my.message=Hello, world!
my-bundle_fr.properties:
my.message=Bonjour tout le monde!
my-bundle_de.properties:
my.message=Hallo Welt!
Something.java:
public static final MY_MESSAGE = "my.message";
ResourceBundle bundle = ResourceBundle.getBundle("my-bundle");
String text = bundle.getMessage(MY_MESSAGE);
System.out.println(text);