Merging message resources recursively


(Marco Schmidt) #1

Hi,

I want to use Gradle to merge message resource files recursively as part of a Java build. Self-contained example at GitHub, see below. I have an application myapp which requires a library lib1 which in turn requires lib2: myapp -> lib1 -> lib2

All are part of a composite build, file system:
root
±- lib1
±- lib2
±- myapp

All three artifacts have src/main/resources directories with files xy_en.properties and xy_de.properties (texts in English and German). Replace xy with each of the three names lib1, lib2, myapp. Each file contains key value pairs in Java’s “.properties” format. Examples:

lib1_en.properties
welcome=Welcome!

lib1_de.properties
welcome=Willkommen!

For each of the languages I want to create a single merged file, e.g. merged_en.properties and merged_de.properties, to be used in myapp.

Those merged files are supposed to contain the combined key value pairs of all three artifacts involved. If a key is defined in more than one properties file, the one closest to the app (in terms of the dependency graph) is supposed to “win”. So if all three artifacts define the same key name=myapp, name=lib1, name=lib2 in their respective messages_en.properties files, the merged file is supposed to contain name=myapp. If only lib1 and lib2 contain name, lib1 is supposed to win.

I use English as the primary natural language. All keys must exist for English and may be missing in the other files like myapp_de.properties. In the final merge step I would like to

  1. learn about missing key value pairs (simple println)
  2. use the English message in the resulting file whenever a translation is missing.

In reality it’s more than two languages, several applications and and a more complex dependency tree of libraries.

When running myapp https://github.com/marco-schmidt/gradle-message-resource-merge (just “gradlew”) the current output is like this. Loading local resource files works (first line), but there is no merged file yet from which to load the name key, so there is an exception.

myapp deutsch/lib1 deutsch/lib2 deutsch
Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name merged, locale de
        at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1564)
        at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1387)
        at java.util.ResourceBundle.getBundle(ResourceBundle.java:1082)
        at myapp.MyApp.main(MyApp.java:17)

I have no idea how to determine the list of input resource files. I would need to collect all the resource directories of dependencies and look for files that are named like the subproject itself followed by “_” followed by the language code and then “.properties”. The list of files has to be in the correct order. I could then load all files into Properties objects, do the actual merging, write the merged files, this last part should be rather easy.

(In the future some of the dependencies may not be part of the same root project, so the properties will be in the root of some jar retrieved from a binary repository. But I would first like to get the above case working.)

Thanks in advance for reading this far and any hints
Marco