Java ResourceBundle Class: Loading Localized Resources - Quiz
Total: 6 questions
1. What is a ResourceBundle in Java, and what does a properties file for it look like?
What is a ResourceBundle in Java, and what does a properties file for it look like?
java.util.ResourceBundle is a set of localized resources (strings and objects) that Java loads for the required locale by a base name. UI texts live outside the code, and a new language is added with a new file, without recompiling.
A properties file is a text file where each line defines a key = value pair:
- lines starting with
#or!are comments; - spaces around
=are ignored, and:can be used instead of=; - a long value continues on the next line if the line ends with
; - keys are usually grouped with dots:
label.button,message.welcome.
Every file of a bundle contains the same keys, translated for its own locale.
2. How are the files of one bundle named, and how do you load them with ResourceBundle.getBundle()?
How are the files of one bundle named, and how do you load them with ResourceBundle.getBundle()?
All files of a bundle share a base name, followed by a language code and a country code joined with underscores: text.properties (the base file), text_de_DE.properties, text_fr_CA.properties.
The static method ResourceBundle.getBundle(baseName, locale) loads the bundle, where baseName is the base name without suffixes and without the extension:
ResourceBundle rb = ResourceBundle.getBundle("text", Locale.of("fr", "CA"));
Files are looked up on the classpath, not in the working directory: in Maven or Gradle, in src/main/resources. If a file is in a package, the base name is the fully qualified name with dots: getBundle("com.example.i18n.text", locale). Calling getBundle("text") without a locale uses Locale.getDefault().
3. In what order does ResourceBundle.getBundle() look for files, and why can a request for Locale.US return German texts?
In what order does ResourceBundle.getBundle() look for files, and why can a request for Locale.US return German texts?
The search goes from the most specific name to the most general one. For a request for fr_CA with the JVM default locale de_DE, the candidates are:
text_fr_CA,text_fr: the requested locale;text_de_DE,text_de: the default locale;text: the base file.
The first file found is used, and the more general files become its parents for missing keys. So if there are no text_en_US and text_en files but there is text_de, a request for Locale.US on a machine with a German default locale returns the German bundle, not text.properties. The one exception is a request for Locale.ROOT: it goes straight to the base file.
The default-locale step is turned off with ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT), which is useful on a server where the JVM locale has nothing to do with the language of the user. In named modules the overloads with a Control throw UnsupportedOperationException.
4. Which encoding does ResourceBundle use to read properties files in Java 8 and in Java 9+?
Which encoding does ResourceBundle use to read properties files in Java 8 and in Java 9+?
In Java 8 and earlier, ISO-8859-1: every character outside that charset (Japanese, Chinese, Cyrillic, Greek) had to be written as a uXXXX escape (with the native2ascii tool or an IDE setting), otherwise the user saw garbled text.
Since Java 9 (JEP 226), PropertyResourceBundle reads files as UTF-8, so such text can be written as is. If a file is not valid UTF-8, it is re-read as ISO-8859-1. uXXXX escapes work in all versions, and the old behavior is restored with -Djava.util.PropertyResourceBundle.encoding=ISO-8859-1. The native2ascii tool was removed in JDK 9.
The move to UTF-8 applies only to ResourceBundle: Properties.load(InputStream) still reads ISO-8859-1. To read UTF-8 with Properties, pass a Reader: props.load(new InputStreamReader(in, StandardCharsets.UTF_8)).
5. When is a MissingResourceException thrown, and how do you avoid it?
When is a MissingResourceException thrown, and how do you avoid it?
MissingResourceException is an unchecked exception (a subclass of RuntimeException). ResourceBundle throws it in two cases:
getBundle()found no file of the bundle at all, including the base file:Can't find bundle for base name labels, locale fr_CA;getString()orgetObject()found the key neither in the file nor in its parents:Can't find resource for bundle java.util.PropertyResourceBundle, key str9. Nonullis returned.
To avoid it, ship a base file without suffixes (text.properties) with all keys and check a key with containsKey(). If the file exists and the exception still appears, the location is usually to blame: the file did not get onto the classpath, or the base name was given without the package.
6. What is the difference between ListResourceBundle and PropertyResourceBundle?
What is the difference between ListResourceBundle and PropertyResourceBundle?
They are the two standard implementations of the abstract ResourceBundle class:
PropertyResourceBundlereads resources from a properties file (text_fr.properties), and the values areStringonly. It suits UI texts: translators edit the files without a programmer.ListResourceBundletakes resources from a Java class (class text_fr extends ListResourceBundle, whosegetContents()returnsObject[][]) and holds objects of any type: numbers, arrays, icons. Non-string values are read withgetObject().
For each candidate name getBundle() looks for a class first and then for a properties file, so if both a Messages_fr class and a Messages_fr.properties file exist, the class is loaded. getStringArray() does not work with a properties file: a value there is always a string, so you get a ClassCastException.