Sure @Kesper… Pasting my I18nProvider
implementation below. I did notice the pattern too and I had also tried to check the stacktrace only to understand how to fix if there is any mistakes from my part that offends the framework/addons. Of course i cannot fathom the framework with 3-4 days of exposure.
On the other hand, The LanguageSelect
issue was resolved when I use its constructor to populate the locale items. Earlier I had used setItems() which was directly handled by parent class Select<?>
.
Anyhow, here is the I18NProvider code…
@Component
public class MyI18NProvider implements I18NProvider {
private static final long serialVersionUID = 2758660919973343707L;
public static final String RB__BASE_NAME = "i18n/myapp";
private static final Locale LOCALE_MALAY = new Locale("ms");
private static final Locale LOCALE_INDONESIAN = new Locale("id");
private static final Locale LOCALE_TAMIZH = new Locale("ta");
private static final ResourceBundle RB__ENGLISH = getBundle(RB__BASE_NAME, Locale.ENGLISH);
private static final ResourceBundle RB__MALAY = getBundle(RB__BASE_NAME, LOCALE_MALAY);
private static final ResourceBundle RB__INDONESIAN = getBundle(RB__BASE_NAME, LOCALE_INDONESIAN);
private static final ResourceBundle RB__TAMILZH = getBundle(RB__BASE_NAME, LOCALE_TAMIZH);
private static final ResourceBundle RB__CHINESE = getBundle(RB__BASE_NAME, Locale.CHINESE);
private static final Map<Locale, ResourceBundle> translations = new LinkedHashMap<Locale, ResourceBundle>();
public static final List<Locale> locales = new ArrayList<Locale>();
@Autowired
@Qualifier("logging")
private LoggingService logging;
@PostConstruct
public void init() {
logging.info("My I18n Provider initializing...");
translations.put(Locale.ENGLISH, RB__ENGLISH);
translations.put(LOCALE_MALAY, RB__MALAY);
translations.put(LOCALE_INDONESIAN, RB__INDONESIAN);
translations.put(LOCALE_TAMIZH, RB__TAMILZH);
translations.put(Locale.CHINESE, RB__CHINESE);
logging.info("My I18n Translations loaded.");
locales.addAll(translations.keySet());
}
@Override
public List<Locale> getProvidedLocales() {
logging.info("Providing locales: " + locales);
return locales;
}
public Locale[] getLocalesAsArray() {
return locales.toArray(new Locale[locales.size()]
);
}
@Override
public String getTranslation(String key, Locale locale, Object... params) {
ResourceBundle bundle = translations.get(locale);
if (bundle == null) {
logging.warn(format("Requested locale: '%s' not found. Falling back to English...", locale.getDisplayName()));
bundle = RB__ENGLISH;
}
String translation = null;
try {
translation = bundle.getString(key);
} catch (MissingResourceException e) {
logging.error(format("Missing i18n.token: '%s' in locale: '%s'!!", key, locale.getDisplayName()));
}
if (translation == null) {
logging.warn(format("Translation for Key: '%s' in Locale: '%s' (or fallback) is missing!!", key, locale.getDisplayName()));
return key;
} else {
logging.info(format("Translation for key: '%s' in Locale: '%s' : '%s'.",
key, locale.getDisplayName(), (translation.length() > 64) ? translation.substring(0, 64) : translation));
return translation;
}
}
}
Some quick pointers… I am using linkedHashMap
and ArrayList
to ensure the insertion order is preserved. This is to ensure that Locale.en is always presented first (since the vaadin documentation describes the locale selection logic tree as (1) match <langCode>_<countryCode>
first, (2) failng which match <langCode>
only, (3) failing which use the first locale from getProvidedLocales()
, and finally (4) use Locale.getDefault()
. So I put in my implementation this way).
Thanks a ton for helping out