stringz
Make externalized Strings as easy accessible as inline Strings!
stringz makes it easy to access externalized strings which are stored in default Java Resource Bundles. It provides some additional features like properties file inheritance to include translation keys from other resource bundles and references to other keys within the same file.
License
stringz is distributed under the MIT License. See LICENSE.md
in this directory for detailed information.
Documentation
JavaDoc is available at www.stringz.skuzzle.de/0.2.0/doc/
Scroll down in this readme for a quick start guide and some advanced topics.
Further support can be found in IRC (irc.euirc.net, #pollyisawesome) or via Twitter (@ProjectPolly).
Building
Building stringz requires Apache Maven to be installed. You may then run mvn install
to build stringz and install it into your local repository. If you want to add stringz to your existing projects, declare the following dependency within your pom.xml
:
<dependency>
<groupId>de.skuzzle</groupId>
<artifactId>stringz</artifactId>
<version>0.2.0</version>
</dependency>
Basic Usage
Declare a class marked with @ResourceMapping
with public static String fields whose names conform to entries of the resource bundle which contains the translation.
@ResourceMapping
public class MSG {
static {
Stringz.init(MSG.class);
}
public static String next;
public static String back;
public static String cancel;
}
The following is a properties file named MSG.properties
contained in the same package as the MSG
class above (as by Stringz default look up procedure, which can be customized if needed):
next = Next
back = Back
cancel = Cancel
This is a properties file named MSG_De.properties
within the same package:
next = Weiter
back = Zurück
cancel = Abbrechen
Calling Stringz.init(Class)
will initialize all public static String fields with values read from a resource bundle using either a globally specified locale or a locale which can optionally be passed to the init method.
You can now easily access the externalized Strings:
public class MyWizard {
public MyWizard() {
createNextButton(MSG.next);
createBackButton(MSG.back);
createCancelButton(MSG.cancel);
}
// ...
}
Advanced Usage
ResourceBundles
This section describes how Java ResourceBundles
are referenced from within Stringz and which additional features it offers.
Look Up
ResourceBundles in Java should follow a specific naming scheme. This scheme consists of a so called base name or family name and an optional locale specific postfix. For details about ResourceBundles in Java please refer to the Sun Online Trail.
So ResourceBundle look up in Stringz is all about specifying the base name of the resource. All other magic is handled by the ResourceBundle.getResource(...)
method.
By default, Stringz uses the full qualified name of the class annotated with @ResourceMapping
as base name for resource look up. If your class's name is com.your.domain.MSG
, then Stringz will use that String as base name to find resources named MSG
within the same java package. So you would place a MSG.properties
into that package and additionally further files like MSG_de_De.properties
etc.
You can also explicitly specify a base name for a message class. The preferred way is to put it into the @ResourceMapping
annotation:
@ResourceMapping("com.your.domain.SomeResourceName")
public class MSG {
// ...
}
If you need some weird dynamic logic for specifying a bundle's base name, you can use a BundleFamilyLocator
. Please refer to the documentation of the Stringz class.
Control Customization
Control
instances are responsible for materializing a ResourceBundle
instance from a base name and locale. Thus they implement the actual logic of how a resource is resolved. Stringz uses a modification of Java's default Control for loading property resources. The modification allows the user to specify an optional charset which should be used when reading the property file.
If for any reason this does not suit your needs, you can specify a custom Control to be used for retrieving the ResourceBundle of a certain message class. The first step to do so is, to implement a ControlFactory
which is responsible for creating an instance of your Control implementation:
public class MyControlFactory implements ControlFactory {
@Override
public Control create(ResourceMapping mapping, String[] args) {
// process optional arguments and create a Control instance
if (args.length != 2) {
throw new ControlFactoryException("Wrong argument count");
}
return new MyControl(args[0], args[1]);
}
}
The second step is to advise Stringz to use that factory for a certain message class by using the @ResourceControl
annotation:
@ResourceMapping
@ResourceControl(value = MyControlFactory.class, args = {"string", "arguments"})
public class MSG {
// ...
}
Extended ResourceBundle Features
While Stringz uses normal Java ResourceBundles it brings some extra features for dealing with entries of a properties file. That is, inclusion and key references.
Property File Inclusion
Your property file which stores the resource strings, can specify a property with the special key @include
. The value is interpreted as a semicolon separated list of resource bundle base names which should be included into the current property file. All included values are then available for being mapped to a field or to be referenced by other properties (see key references below). If an included resource bundle contains a key which is also present in the current bundle, the current bundle takes precedence. Beyond this, the included bundles are searched in the order in which they were included.
Key References
From a resource string you can reference another resource string to be inserted at a certain point. This allows you to specify often used string parts atomically and then build the full string by referencing those parts.
userName = username
password = password
promptLogin = Please specify your ${userName} and ${password}
forgotPassword = Forgot your ${password}?
You can use references to any key from the same file and to keys from included files (see Property File Inclusion above). Key references are also resolved recursively. That is, if you reference a key which value references another key, that nested reference is resolved first.
Fieldmapping
This section describes the behavior applied to assign resource values to fields of a class.
Customize Resource Keys
By default, Stringz uses the name of the variable as key to find its resource. You can also specify an explicit key for a variable using @ResourceKey
:
@ResourceKey("someOtherKey")
public static String myResource;
The variable myResource
will get the value stored at the key someOtherKey
assigned.
Ignore Fields
If for any resason your message class contains a variable that should not be mapped to a resource value, you can mark it with @NoResource
:
@NoResource
public static String myResource;
Otherwise if Stringz tries to map the field and there exists no value for its key, it will throw a MissingResourceException
upon initialization.
Mapping Array Fields
Stringz will also attempt to automatically map values to String[] variables within your message class. Hence, it uses the semicolon as default delimiter to split the referenced resource. For example, your resource could look like this:
myResource = First column;Second column;Third column
and within your message class you would simply declare a String array with the resource's name:
public static String[] myResource;
The @ResourceKey
and @NoResource
annotations are used on String arrays in the same way they are used for normal Strings.
You can also define a custom delimiter pattern if the semicolon delimiter does not suit your needs using the @Delimiter
annotation:
@Delimiter("\\s+")
public static String[] myResource;
This will split the resource value at any sequence of whitespaces.
You may also instruct Stringz to create an array of arbitrary other resources referenced by their keys using @ResourceCollection
. Consider the following resource file:
first = First column
second = Second column
third = Third column
You can let Stringz create an array out of theses resources:
@ResourceCollection({"first", "second", "third"})
public static String[] myResource;