/* * Copyright [2014] [Christian Loehnert, krampenschiesser@gmail.com] * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.ks.i18n; import de.ks.eventsystem.bus.EventBus; import de.ks.i18n.event.LanguageChangedEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.enterprise.inject.spi.CDI; import java.lang.reflect.Field; import java.net.URL; import java.util.Locale; import java.util.ResourceBundle; import java.util.concurrent.atomic.AtomicBoolean; /** * Main interface to the i18n facilities. */ public class Localized { private static final Logger log = LoggerFactory.getLogger(Localized.class); protected static final AtomicBoolean initialized = new AtomicBoolean(false); protected static volatile ResourceBundleWrapper bundle; public static final String FILENAME = "Translation"; public static final String BASENAME = "de.ks.i18n." + FILENAME; /** * Use this method in order to notify possible listeners and replace the resource bundle. * * @param locale */ public static void changeLocale(Locale locale) { Locale oldLocale = Locale.getDefault(); Locale.setDefault(locale); initialize(); CDI.current().select(EventBus.class).get().post(new LanguageChangedEvent(oldLocale, locale)); } protected synchronized static void initialize() { Locale locale = Locale.getDefault(); String path = BASENAME + "_" + locale.getLanguage() + ".properties"; bundle = new ResourceBundleWrapper(ResourceBundle.getBundle(BASENAME, locale, new UTF8Control()), null, path); initialized.set(true); } /** * @return the currently used bundle to use for eg. JavaFX loaders etc. */ public static ResourceBundleWrapper getBundle() { if (!initialized.get()) { initialize(); } return bundle; } public static ResourceBundleWrapper getBundle(Class callerClass) { if (!initialized.get()) { initialize(); } Locale locale = Locale.getDefault(); String substring = callerClass.getName().substring(0, callerClass.getName().lastIndexOf('.') + 1); UTF8Control control = new UTF8Control(); String baseName = substring + Localized.FILENAME; URL resource = callerClass.getResource("/" + control.getResourceName(baseName, locale)); if (resource == null) { resource = callerClass.getResource("/" + control.getResourceName(baseName, control.getFallbackLocale(baseName, locale))); } if (resource != null) { log.debug("Found local bundle {}", baseName); ResourceBundle localBundle = ResourceBundle.getBundle(baseName, locale, control); return new ResourceBundleWrapper(localBundle, bundle.getBundle(), baseName + "_" + locale.getLanguage() + ".properties"); } return bundle; } /** * Use this method to get a translation for a key. * The key "hello.world" is stored like that: * hello.world=Hello {0}{1} * And the corresponding method parameters will be: * "hello.world", "world", "!" * Which will result in: * Hello world! * If you add a colon ":" to the end of the string it is ignored. * This is quite useful for input fields. * * @param key * @param args * @return */ public static String get(String key, Object... args) { String string = getBundle().getString(key); if (args == null) { return string; } else { for (int i = 0; i < args.length; i++) { Object arg = args[i]; if (arg == null) { string = string.replace("{" + i + "}", "null"); } else { string = string.replace("{" + i + "}", arg.toString()); } } return string; } } public static String get(Field field) { String key = field.getDeclaringClass().getName(); key += field.getName(); return get(key); } }