7

I'm using .properties files for message internationalization. For example:

HELLO_WORLD = Hello World
HELLO_UNIVERSE = Hello Universe

And then in Java code:

String foo = resourceBundle.getString("HELLO_WORLD");

String literals like "HELLO_WORLD" are problematic because they're error-prone and can't be autocompleted. I'd like to generate code from the keys in the properties file like this:

public interface Messages { // Or abstract class with private constructor
    public static final String HELLO_WORLD = "HELLO_WORLD";
    public static final String HELLO_UNIVERSE = "HELLO_UNIVERSE";
}

And then use it like this:

String foo = resourceBundle.getString(Messages.HELLO_WORLD);

Is there a standard way to do this? I prefer a Maven plugin, but any stand-alone tool that I can run manually would be good enough for my needs.

imgx64
  • 4,062
  • 5
  • 28
  • 44
  • This sounds a lot like the resource system in Android development... I wonder if it can be used for non-Android projects? – Adam Jul 06 '15 at 06:09
  • Would you want to use this http://owner.aeonbits.org/docs/welcome/ ? there are other useful features it provides which you maybe interested in such as the reload and hot reload stuff. – Aarjav Jan 20 '16 at 02:31

4 Answers4

3

Best the other way around:

public enum Message {
    HELLO_WORLD,
    HELLO_UNIVERSE;

    public String xlat(Locale locale) {
        resourceBundle.getString(toString(), locale);
    }
}

Generate from that enum a properties template. This can be repeated for new messages if your base language resides in a separate ..._en.properties.

The generation can be done using values() - without parsing. Though maybe you want to introduce some annotation for properties comments or such.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
2

Following code will generate interface MyProperties in your root directory of the project then after you can use that interface anywhere.

public class PropertiesToInterfaceGenerator {

    public static void main(String[] args) throws IOException {

        Properties properties = new Properties();
        InputStream inputStream =PropertiesToInterfaceGenerator.class.getClassLoader().getResourceAsStream("xyz.properties");
        if(null != inputStream ){
            properties.load(inputStream);
        }
        generate(properties);
    }


    public static void generate(Properties properties) {
        Enumeration e = properties.propertyNames();
        try {
            FileWriter aWriter = new FileWriter("MyProperties.java", true);
            aWriter.write("public interface MyProperties{\n");
            while (e.hasMoreElements()) {
                String key = (String) e.nextElement();
                String val =  properties.getProperty(key);
                aWriter.write("\tpublic static String "+key+" = \""+val+"\";\n");
            }
            aWriter.write(" }\n");
            aWriter.flush();      
            aWriter.close();
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
}
Shekhar Khairnar
  • 2,643
  • 3
  • 26
  • 44
2

No, nobody has ever written such sort of plugin that have all capabilities you have expexted, because:

  • Internationalization may have A LOT OF entries, and you will eventually got a gigantic class, interface, enum or whatever on the end, which is bad.
  • A maven/gradle plugin do generate classes for you, but only at compile time. I see you mentioned auto-completion, which means you will need an IDE plugin, too, meaning a plugin for a building tool(gradle/ant/...) is not enough. The interaction betweeen these plugins could be error-prone.
  • Later in project, if you, or your colleagues, want a new translation entry, and you will have to regenerate the classes. That's a bit tiring.

When dealing with internationalization, something like i18n is recommended. If you don't want a new library or your project is small, you can opt to use eclipse's externalize strings function, for that, see

Andriod: Externalize strings for Android project

Other: help.eclipse.org - Java development user guide > Reference > Wizards and Dialogs > Externalize Strings Wizard

Community
  • 1
  • 1
glee8e
  • 6,180
  • 4
  • 31
  • 51
  • It's only about the keys, which is a good idea to reference these keys in your code without a typo... – Ming Zhu May 10 '19 at 18:01
0

Yes, apparently people have already written such code.

Have a look at this project: https://github.com/kklisura/props-to-constants-generator

From its intro section:

props-to-constants-generator generates a constants class of keys in your properties file. This enables you to have compile time dependency of keys on a properties file.

Technically, props-to-constants-generator is an Java annotation processor that processes PropertySourceConstants annotations which contain information from which properties file you wish to generate constants and output constants class name. For every PropertySourceConstants annotation, it reads a specified properties file and outputs the class containing constants of property keys.

Maven supports Java annotation processor, so it should work with Maven - although I have not tried it myself (yet).

Update The props-to-constants-generator works well when used in a command-line Maven build. Unfortunately, when used in Eclipse, the problem seems to be that the annotation processor is invoked before the *.properties files are copied to target/classes causing the processor to fail when doing a fresh build (cf. https://stackoverflow.com/a/55992061/2511197).

rec
  • 10,340
  • 3
  • 29
  • 43