A resource bundle contains the local specific objects to be used by a program. It is a map with keys and values.
properties file |
For example, a program can consume English and French properties files. You just have to create two files named helloworld_en.properties and helloworld_fr.properties, and put the name value pair contents with text editor such as vi or emac, them put them in the class path of your java program:
OCPJP>cat helloworld_en.properties
hello=Hello
world=world
OCPJP>
OCPJP>cat helloworld_fr.properties
hello=Bonjour
world=le monde
OCPJP>
OCPJP>
OCPJP>cat HelloWorld.java
import java.util.*;
public class HelloWorld {
public static void main(String... args) {
Locale us = new Locale("en", "US");
Locale fr = new Locale("fr", "FR");
System.out.println(sayHello(us));
System.out.println();
System.out.println(sayHello(fr));
}
private static String sayHello(Locale locale) {
ResourceBundle rb = ResourceBundle.getBundle("helloworld", locale);
return rb.getString("hello") + " " + rb.getString("world");
}
}
OCPJP>
OCPJP>javac HelloWorld.java
OCPJP>java HelloWorld
Hello world
Bonjour le monde
OCPJP>
The properties file name need to follow convention, the .properties and bundleName are must have, the language and country are optional. The language has to be lower case letters and country has to be upper case letters.
bundleName_language_COUNTRY.properties
The following are valid properties file names:
- helloworld_en_US.properties
- helloworld_fr.properties
- helloworld.properteis
As for the contents, the syntax rules are:
- comment line begins with # or !
- key value pairs are delimited with =, or : or space
- space at beginning of the line is ignored
- space before and after delimiter is ignored
- escape characters \t and \n are not ignored
- space at end of line is not ignored
- \ glue lines together
the following lines are all valid:
- key=value
- key= value
- key = value
- key:value
- key value
- key : value
- key value
- key = value1\tvalue2\nvalue3\t\t\t
- key=valueline1\
- valueline2\
- valueline3
- # this is a comment
- ! this is also a comment
The above are basic syntax and usage of properties file. A properties file can be converted to Properties object.
Properties props = new Properties();
OCPJP>cat helloworld_fr.properties
hello=Bonjour
world=le monde
OCPJP>
OCPJP>cat PropertiesTest.java
import java.util.*;
public class PropertiesTest {
public static void main(String[] args) {
Locale us = new Locale("fr");
ResourceBundle rb = ResourceBundle.getBundle("helloworld", us);
Set<String> keys = rb.keySet();
Properties props = new Properties();
keys.stream().forEach(k -> props.put(k, rb.getString(k)));
String helloworld = props.getProperty("hello") + props.getProperty("nosuchvalue", " default ") + props.getProperty("world");
System.out.println(helloworld);
}
}
OCPJP>javac PropertiesTest.java
OCPJP>java PropertiesTest
Bonjour default le monde
OCPJP>
We can also create resource bundle in java by creating a class with the same class name that we would use for a property file.
For example, if the properties file is Helloworld_en.properties, the java class name must be Helloworld_en.java. The only difference is .properties and .java.
The Helloworld_en.java need to extends abstract class ListResourceBundle and override method protected Object[][] getContents().
OCPJP>cat helloworld_en.properties
hello=Hello
world=world000
OCPJP>
OCPJP>cat helloworld_fr.properties
hello=Bonjour
world=le monde
OCPJP>
OCPJP>
OCPJP>cat Helloworld_en_US.java
import java.util.*;
import java.time.*;
public class Helloworld_en_US extends ListResourceBundle {
public static void main(String[] args) {
Locale locale = new Locale.Builder().setLanguage("en").setRegion("US").build();
ResourceBundle rb = ResourceBundle.getBundle("Helloworld", locale);
String helloworld = rb.getString("hello") + " " + rb.getString("world") + " at " + rb.getObject("time");
System.out.println(helloworld);
}
protected Object[][] getContents() {
return new Object[][] {
{"time", LocalDateTime.now()},
{"hello", "Helloxx"}
};
}
}
OCPJP>
OCPJP>javac Helloworld_en_US.java
OCPJP>java Helloworld_en_US
Helloxx world000 at 2018-02-15T17:55:06.308
OCPJP>
The main advantages of using java class instead of property file is you can use a value type other than String.
Notice the key "world" has no key in the resource bundle defined in Helloworld_en_US.java, the jvm somehow still managed to find the mapping in properties file helloworld_en.properties. How to determine which resource bundle to use is the topic of next post Build a resource bundle for each locale and load a resource bundle in an application.