Reputation: 825
I am developing a jsp web app that was not intended to be multilanguage, but now they wanted it to be able to change the user interface language depending on browser locale.
So, to implement i18n for labels and other fixed elements is easy enough, but there is a dashboard framework we did that have some standard reports which titles, column headers and other elements are fixed too, but retrieved from DB, and not all of them will be translated.
I was thinking of solving this problem using some notation to indicate which field value is a translatable element. By example, maybe using some #{resource.bundle.key.element}
notation.
Well, the dashboards entities uses JPA. So, I want to know if is it possible to do the i18n translation using resource bundles and do the locale translation after retrieving values from DB without do an intrusive coding, maybe using annotations or AOP implementations.
Is such thing possible? or there is another approach I could use?
Upvotes: 0
Views: 631
Reputation: 67317
Internationalisation is a cross-cutting concern and as such a good candidate for AOP. With AspectJ you can do something like this (simple, naive example, just as a proof of concept):
Driver application:
package de.scrum_master.app;
public class Application {
public enum Language { EN, DE, FR };
public final Language language;
public Application(Language language) {
this.language = language;
}
public static void main(String[] args) {
for (Language language : Language.values())
new Application(language).printStuff();
}
private void printStuff() {
System.out.println("Hello world");
System.out.println("This error message will not be translated.");
System.out.println("one");
System.out.println("two");
System.out.println("three");
System.out.println("This error message will also not be translated.");
System.out.println("Goodbye");
System.out.println();
}
}
Translation aspect:
Please note: The static translation stuff should be stored in property files or so. I know it is ugly this way.
package de.scrum_master.aspect;
import java.util.HashMap;
import java.util.Map;
import de.scrum_master.app.Application;
import de.scrum_master.app.Application.Language;
public aspect TranslationAspect {
private static final Map<String, Map<Language, String>> dictionary = new HashMap<>();
static {
Map<Language, String> translations = new HashMap<>();
translations.put(Language.EN, "Hello world");
translations.put(Language.DE, "Hallo Welt");
translations.put(Language.FR, "Bonjour tout le monde");
dictionary.put("Hello world", translations);
translations = new HashMap<>();
translations.put(Language.EN, "Goodbye");
translations.put(Language.DE, "Auf Wiedersehen");
translations.put(Language.FR, "Au revoir");
dictionary.put("Goodbye", translations);
translations = new HashMap<>();
translations.put(Language.EN, "one");
translations.put(Language.DE, "eins");
translations.put(Language.FR, "un");
dictionary.put("one", translations);
translations = new HashMap<>();
translations.put(Language.EN, "two");
translations.put(Language.DE, "zwei");
translations.put(Language.FR, "deux");
dictionary.put("two", translations);
translations = new HashMap<>();
translations.put(Language.EN, "three");
translations.put(Language.DE, "drei");
translations.put(Language.FR, "trois");
dictionary.put("three", translations);
}
void around(Application application, String text) :
call(* *.println(String)) && this(application) && args(text)
{
proceed(
application,
dictionary.get(text) == null ? text : dictionary.get(text).get(application.language)
);
}
}
Console output:
Hello world
This error message will not be translated.
one
two
three
This error message will also not be translated.
Goodbye
Hallo Welt
This error message will not be translated.
eins
zwei
drei
This error message will also not be translated.
Auf Wiedersehen
Bonjour tout le monde
This error message will not be translated.
un
deux
trois
This error message will also not be translated.
Au revoir
Enjoy!
Upvotes: 1