Commit 2cf0fcc3 authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck
Browse files

move language features to all modules. Separate messages.properties

parent c4a56750
#Eclipse messages class
#Tue Sep 17 13:33:04 CEST 2013
include=i18n_simulation
AttributeFileView.btnChangeAttributeFile.text=Change attribute file...
AttributesFileView.btnSaveToFile.text=Save to file...
AttributesFileView.txtrAttributefiletextarea.text=attributeFileTextArea
......@@ -305,46 +307,6 @@ TopographyCreator.btnMakro.tooltip=Generate not set IDs.
select_shape_tooltip=Select Shape
# ScenarioChecker
ScenarioChecker.type.error=Error
ScenarioChecker.type.warning=Warning
ScenarioChecker.type.topography.error=Topography Error
ScenarioChecker.type.topography.warning=Topography Warning
ScenarioChecker.type.simulation.error=Simulations Attribute Error
ScenarioChecker.type.simulation.warning=Simulations Attribute Warning
ScenarioChecker.type.model.error=Model Attribute Error
ScenarioChecker.type.model.warning=Model Attribute Warning
ScenarioChecker.type.processor.error=Processor Error
ScenarioChecker.type.processor.warning=Processor Warning
ScenarioChecker.source.targetIdNotFound=The following target ids where not found in the scenario.
ScenarioChecker.source.noTargetIdSet=No Target Ids set for Source.
ScenarioChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error.
ScenarioChecker.source.idNotUnique=Multiple Sources have the same ID.
ScenarioChecker.stairs.wrongTreadDim=Stair treadDepth outside of allowed dimension. Change the thread numbers to compensate.
ScenarioChecker.target.unused=The target is not used in any source. Remove target to increase performance.
ScenarioChecker.pedestrian.speedsetup=speedDistributionMean must be within min/max range.
ScenarioChecker.pedestrian.speedNotLogical=Min or Max speed of pedestrian is bigger than world record.
ScenarioChecker.pedestrian.speedIsNegative=Min or Max speed is negative.
ScenarioChecker.overlap.stair.stair=Stairs cannot overlap.
ScenarioChecker.overlap.target.stair=A target and a stairs element overlap in scenario.
ScenarioChecker.overlap.source.stair=A source and a stairs element overlap in scenario.
ScenarioChecker.overlap.source.target=A source and a target element overlap in scenario.
ScenarioChecker.overlap.source.source=Two source overlap. This can cause overlapping when useFreeSpaceOnly is not set.
ScenarioChecker.overlap.target.target=Two targets overlap.
ScenarioChecker.overlap.obstacle.stairs.err=Stairs is completely contained in an obstacle.
ScenarioChecker.overlap.obstacle.stairs.warn=Stairs contains an obstacle. This setup works put is not tested. Split in two stairs.
ScenarioChecker.overlap.obstacle.target.err=Target is completely contained in an obstacle.
ScenarioChecker.overlap.obstacle.target.warn=Target contains an obstacle. This setup works but reduces the actual size of the target.
ScenarioChecker.overlap.obstacle.source=Obstacle overlaps with a source. This setup will spawn pedestrians within the obstacle.
ScenarioChecker.overlap.obstacle.obstacle=Two obstacles overlap / is enclosed completely. Delete one for better performance.
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep parameter outside of allowed range
ScenarioChecker.msg.ok=Scenario ok.
ScenarioChecker.msg.warn=Scenario contains warnings.
ScenarioChecker.msg.err=Scenario contains errors.
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
......
#Eclipse messages class
#Tue Sep 17 13:49:11 CEST 2013
include=i18n_simulation
AttributeFileView.btnChangeAttributeFile.text=Attributsdatei \u00E4ndern...
AttributesFileView.btnSaveToFile.text=In Datei speichern...
AttributesFileView.txtrAttributefiletextarea.text=attributeFileTextArea
......@@ -297,46 +299,6 @@ TopographyCreator.btnRectangle.label=Rechteck
TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnMakro.tooltip=Erzeuge nicht gesetzte IDs.
# ScenarioChecker
ScenarioChecker.type.error=Error
ScenarioChecker.type.warning=Warning
ScenarioChecker.type.topography.error=Topography Fehler
ScenarioChecker.type.topography.warning=Topography Warnung
ScenarioChecker.type.simulation.error=Simulations Attribut Fehler
ScenarioChecker.type.simulation.warning=Simulations Attribut Wahrnung
ScenarioChecker.type.model.error=Model Attribute Fehler
ScenarioChecker.type.model.warning=Model Attribute Warnung
ScenarioChecker.type.processor.error=Processor Fehler
ScenarioChecker.type.processor.warning=Procesor Warnung
ScenarioChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden.
ScenarioChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben.
ScenarioChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0.
ScenarioChecker.source.idNotUnique=Quellen haben keine eindeutige ID.
ScenarioChecker.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs. Passen Sie die Anzahl der Stufen entsprechend an.
ScenarioChecker.target.unused=Das Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen
ScenarioChecker.pedestrian.speedsetup=speedDistributionMean muss im Bereich min/max liegen.
ScenarioChecker.pedestrian.speedNotLogical=Min or Max Geschwindigkeit ist gr\u00f6\u00dfer als Weltrekord.
ScenarioChecker.pedestrian.speedIsNegative=Min or Max Geschwindigkeit ist negativ.
ScenarioChecker.overlap.stair.stair=Treppen d\u00fcrfen nicht \u00fcberlappen.
ScenarioChecker.overlap.target.stair=Ein Ziel und eine Treppen \u00fcberlappen im Scenario.
ScenarioChecker.overlap.source.stair=Eine Quelle und eine Treppe \u00fcberlappen im Scenario.
ScenarioChecker.overlap.source.target=Eine Quelle und eine Ziel \u00fcberappen im Scenario.
ScenarioChecker.overlap.source.source=Zwei Quellen \u00fcberlappen. Wenn useFreeSpaceOnly nicht gesetzt ist kann dies zu \u00fcberlappungen von Pedestrians f\u00fchren.
ScenarioChecker.overlap.target.target=Zwei Ziele \u00fcberlappen.
ScenarioChecker.overlap.obstacle.stairs.err=Treppe ist komplett in einem Hinderniss eingeschossen.
ScenarioChecker.overlap.obstacle.stairs.warn=Treppe hat ein Hinderiss in sich. Dies ist m\u00f6glich aber nicht getestet. Wenn m\u00f6glich in zwei treppen aufteilen.
ScenarioChecker.overlap.obstacle.target.err=Ziel ist komplett in einem Hinderniss eingeschlossen
ScenarioChecker.overlap.obstacle.target.warn=Ziel hat ein Hinderniss in sich. Dies ist m\u00f6glich reduziert aber die tats\u00c4chliche Fl\u00c4che des Ziels.
ScenarioChecker.overlap.obstacle.source=Hinderniss \u00fcberdeckt Quelle. Die f\u00fchrt dazu, dass Pedestrians im Hinderniss erzeugt werden.
ScenarioChecker.overlap.obstacle.obstacle=Zwei identische bzw. eingeschlossene Obstacles gefunden. L\u00f6sche eins f\u00fcr bessere Performance
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep Parameter au\u00dferhalb des Definitionsbereichs
ScenarioChecker.msg.ok=Scenario ok.
ScenarioChecker.msg.warn=Scenario hat Warnungen.
ScenarioChecker.msg.err=Scenario ist Fehlerhaft.
# tab titles Topography creator / postvis
Tab.Simulation.title=Simulation
......
package org.vadere.gui.components.utils;
import org.vadere.gui.projectview.VadereApplication;
import java.util.Locale;
import java.util.prefs.Preferences;
public class Language {
public static final Locale locale = Language.setLanguage();
/*
* The default language of this application is english.
*/
static {
Locale.setDefault(Locale.ENGLISH);
}
static Locale setLanguage() {
String language = Preferences.userNodeForPackage(VadereApplication.class).get("language", null);
if (language != null) {
switch (language) {
case "de":
return new Locale("de", "DE");
case "en":
default:
return new Locale("en");
}
}
return Locale.getDefault();
}
public static boolean languageIsGerman() {
return locale.getLanguage().equals(Locale.GERMAN.getLanguage());
}
}
package org.vadere.gui.components.utils;
import javax.swing.*;
import org.vadere.gui.projectview.VadereApplication;
import org.vadere.gui.projectview.view.ProjectView;
import org.vadere.util.lang.BundleManager;
import java.beans.Beans;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.prefs.Preferences;
import javax.swing.*;
/**
* Messages class used in localization.
*
*
*/
public abstract class Messages {
public class Messages {
private static final String BUNDLE_NAME = "messages";
private static final ResourceBundle RESOURCE_BUNDLE = loadBundle();
public static String getString(String key) {
try {
ResourceBundle bundle = Beans.isDesignTime() ? loadBundle() : RESOURCE_BUNDLE;
return bundle.getString(key);
} catch (MissingResourceException e) {
return "!" + key + "!";
}
return BundleManager.instance().getString(BUNDLE_NAME, key);
}
public static boolean languageIsGerman(){
return BundleManager.instance().languageIsGerman();
}
public static Locale getCurrentLocale(){
return BundleManager.instance().getCurrentLocale();
}
private static ResourceBundle loadBundle() {
return ResourceBundle.getBundle(BUNDLE_NAME, Language.locale);
public static void loadLanguageFromPreferences(Class<?> clazz){
BundleManager.instance().setLanguage(clazz);
}
public static void changeLanguage(Locale lang) {
Preferences.userNodeForPackage(VadereApplication.class).put("language", lang.getLanguage());
BundleManager.instance().setLanguage(lang);
JOptionPane.showMessageDialog(ProjectView.getMainWindow(), getString("Messages.changeLanguagePopup.text"),
getString("Messages.changeLanguagePopup.title"), JOptionPane.INFORMATION_MESSAGE);
}
......
......@@ -2,11 +2,10 @@ package org.vadere.gui.projectview;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.view.ProjectView;
import org.vadere.state.attributes.models.AttributesBHM;
import org.vadere.util.io.IOUtils;
import java.awt.*;
import java.io.IOException;
import java.util.prefs.BackingStoreException;
import java.util.prefs.InvalidPreferencesFormatException;
......@@ -26,6 +25,9 @@ public class VadereApplication {
// load settings
loadPreferences();
// set locale
Messages.loadLanguageFromPreferences(VadereApplication.class);
// start main gui
ProjectView.start();
}
......
......@@ -2,7 +2,6 @@ package org.vadere.gui.projectview.view;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.utils.Language;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.postvisualization.control.Player;
import org.vadere.gui.projectview.VadereApplication;
......@@ -446,7 +445,7 @@ public class ProjectView extends JFrame implements ProjectFinishedListener, Sing
ButtonGroup languageChoicesGroup = new ButtonGroup();
languageChoicesGroup.add(mntmEnglishLocale);
languageChoicesGroup.add(mntmGermanLocale);
if (Language.languageIsGerman())
if (Messages.languageIsGerman())
mntmGermanLocale.setSelected(true);
else
mntmEnglishLocale.setSelected(true);
......
# ScenarioChecker
ScenarioChecker.type.error=Error
ScenarioChecker.type.warning=Warning
ScenarioChecker.type.topography.error=Topography Error
ScenarioChecker.type.topography.warning=Topography Warning
ScenarioChecker.type.simulation.error=Simulations Attribute Error
ScenarioChecker.type.simulation.warning=Simulations Attribute Warning
ScenarioChecker.type.model.error=Model Attribute Error
ScenarioChecker.type.model.warning=Model Attribute Warning
ScenarioChecker.type.processor.error=Processor Error
ScenarioChecker.type.processor.warning=Processor Warning
ScenarioChecker.source.targetIdNotFound=The following target ids where not found in the scenario.
ScenarioChecker.source.noTargetIdSet=No Target Ids set for Source.
ScenarioChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error.
ScenarioChecker.source.idNotUnique=Multiple Sources have the same ID.
ScenarioChecker.stairs.wrongTreadDim=Stair treadDepth outside of allowed dimension. Change the thread numbers to compensate.
ScenarioChecker.target.unused=The target is not used in any source. Remove target to increase performance.
ScenarioChecker.pedestrian.speedsetup=speedDistributionMean must be within min/max range.
ScenarioChecker.pedestrian.speedNotLogical=Min or Max speed of pedestrian is bigger than world record.
ScenarioChecker.pedestrian.speedIsNegative=Min or Max speed is negative.
ScenarioChecker.overlap.stair.stair=Stairs cannot overlap.
ScenarioChecker.overlap.target.stair=A target and a stairs element overlap in scenario.
ScenarioChecker.overlap.source.stair=A source and a stairs element overlap in scenario.
ScenarioChecker.overlap.source.target=A source and a target element overlap in scenario.
ScenarioChecker.overlap.source.source=Two source overlap. This can cause overlapping when useFreeSpaceOnly is not set.
ScenarioChecker.overlap.target.target=Two targets overlap.
ScenarioChecker.overlap.obstacle.stairs.err=Stairs is completely contained in an obstacle.
ScenarioChecker.overlap.obstacle.stairs.warn=Stairs contains an obstacle. This setup works put is not tested. Split in two stairs.
ScenarioChecker.overlap.obstacle.target.err=Target is completely contained in an obstacle.
ScenarioChecker.overlap.obstacle.target.warn=Target contains an obstacle. This setup works but reduces the actual size of the target.
ScenarioChecker.overlap.obstacle.source=Obstacle overlaps with a source. This setup will spawn pedestrians within the obstacle.
ScenarioChecker.overlap.obstacle.obstacle=Two obstacles overlap / is enclosed completely. Delete one for better performance.
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep parameter outside of allowed range
ScenarioChecker.msg.ok=Scenario ok.
ScenarioChecker.msg.warn=Scenario contains warnings.
ScenarioChecker.msg.err=Scenario contains errors.
# ScenarioChecker
ScenarioChecker.type.error=Error
ScenarioChecker.type.warning=Warning
ScenarioChecker.type.topography.error=Topography Fehler
ScenarioChecker.type.topography.warning=Topography Warnung
ScenarioChecker.type.simulation.error=Simulations Attribut Fehler
ScenarioChecker.type.simulation.warning=Simulations Attribut Wahrnung
ScenarioChecker.type.model.error=Model Attribute Fehler
ScenarioChecker.type.model.warning=Model Attribute Warnung
ScenarioChecker.type.processor.error=Processor Fehler
ScenarioChecker.type.processor.warning=Procesor Warnung
ScenarioChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden.
ScenarioChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben.
ScenarioChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0.
ScenarioChecker.source.idNotUnique=Quellen haben keine eindeutige ID.
ScenarioChecker.stairs.wrongTreadDim=Stufentiefe ist au\u00dferhalb des Definitionsbereichs. Passen Sie die Anzahl der Stufen entsprechend an.
ScenarioChecker.target.unused=Das Ziel wird von keiner Quelle verwendet. Entferne das Ziel um die Performance zu erh\u00f6hen
ScenarioChecker.pedestrian.speedsetup=speedDistributionMean muss im Bereich min/max liegen.
ScenarioChecker.pedestrian.speedNotLogical=Min or Max Geschwindigkeit ist gr\u00f6\u00dfer als Weltrekord.
ScenarioChecker.pedestrian.speedIsNegative=Min or Max Geschwindigkeit ist negativ.
ScenarioChecker.overlap.stair.stair=Treppen d\u00fcrfen nicht \u00fcberlappen.
ScenarioChecker.overlap.target.stair=Ein Ziel und eine Treppen \u00fcberlappen im Scenario.
ScenarioChecker.overlap.source.stair=Eine Quelle und eine Treppe \u00fcberlappen im Scenario.
ScenarioChecker.overlap.source.target=Eine Quelle und eine Ziel \u00fcberappen im Scenario.
ScenarioChecker.overlap.source.source=Zwei Quellen \u00fcberlappen. Wenn useFreeSpaceOnly nicht gesetzt ist kann dies zu \u00fcberlappungen von Pedestrians f\u00fchren.
ScenarioChecker.overlap.target.target=Zwei Ziele \u00fcberlappen.
ScenarioChecker.overlap.obstacle.stairs.err=Treppe ist komplett in einem Hinderniss eingeschossen.
ScenarioChecker.overlap.obstacle.stairs.warn=Treppe hat ein Hinderiss in sich. Dies ist m\u00f6glich aber nicht getestet. Wenn m\u00f6glich in zwei treppen aufteilen.
ScenarioChecker.overlap.obstacle.target.err=Ziel ist komplett in einem Hinderniss eingeschlossen
ScenarioChecker.overlap.obstacle.target.warn=Ziel hat ein Hinderniss in sich. Dies ist m\u00f6glich reduziert aber die tats\u00c4chliche Fl\u00c4che des Ziels.
ScenarioChecker.overlap.obstacle.source=Hinderniss \u00fcberdeckt Quelle. Die f\u00fchrt dazu, dass Pedestrians im Hinderniss erzeugt werden.
ScenarioChecker.overlap.obstacle.obstacle=Zwei identische bzw. eingeschlossene Obstacles gefunden. L\u00f6sche eins f\u00fcr bessere Performance
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep Parameter au\u00dferhalb des Definitionsbereichs
ScenarioChecker.msg.ok=Scenario ok.
ScenarioChecker.msg.warn=Scenario hat Warnungen.
ScenarioChecker.msg.err=Scenario ist Fehlerhaft.
......@@ -157,6 +157,7 @@ public class Simulation {
private void postLoop() {
simulationState = new SimulationState(name, topography, scenarioStore, simTimeInSec, step, mainModel);
topographyController.postLoop(this.simTimeInSec);
for (Model m : models) {
m.postLoop(simTimeInSec);
......@@ -169,7 +170,7 @@ public class Simulation {
if (attributesSimulation.isWriteSimulationData()) {
processorManager.postLoop(this.simulationState);
}
topographyController.postLoop(this.simTimeInSec);
}
/**
......
package org.vadere.simulator.util;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.util.AbstractScenarioCheckerMessageFormatter;
import org.vadere.simulator.util.ScenarioCheckerMessage;
public class ConsoleScenarioCheckerMessageFormatter extends AbstractScenarioCheckerMessageFormatter {
private final Scenario scenario;
public ConsoleScenarioCheckerMessageFormatter(final Scenario scenario){
this.scenario = scenario;
}
@Override
protected void writeHeader(ScenarioCheckerMessage msg) {
// sb.append(Messages.getString(msg.getMsgType().getLocalTypeId())))
}
@Override
protected void writeMsg(ScenarioCheckerMessage msg) {
}
}
package org.vadere.util.lang;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.prefs.Preferences;
/**
* Manage all {@link java.util.ResourceBundle}s present in the application.
* Each module must use this Manager to allow easy inheritance of language keys.
* If the application language is changed this manager will propagate the new Locale
* to each Bundel.
*/
public class BundleManager {
private static final Locale defaultLocale = new Locale("en");
//good performance threadsafe Singletone. Sync block will only be used once
private static BundleManager instance;
public static BundleManager instance(){
if(instance == null){
synchronized (BundleManager.class){
if(instance == null){
instance = new BundleManager();
}
}
}
return instance;
}
private HashMap<String, ModuleResourceBundle> bundleMap;
private Locale currentLocale;
public Locale getCurrentLocale(){
return (Locale)currentLocale.clone();
}
public boolean languageIsGerman(){
return currentLocale.getLanguage().equals(Locale.GERMAN.getLanguage());
}
public String getString(String baseName, String key){
ModuleResourceBundle b = bundleMap.getOrDefault(baseName, loadBundle(baseName));
return b != null ? b.getString(key) : "!" +baseName + " Bundle Not Found!";
}
public void setLanguage(Locale locale){
currentLocale = locale;
reloadBundles();
}
public void setLanguage(Class<?> clazz){
String language = Preferences.userNodeForPackage(clazz).get("language", null);
Locale locale =defaultLocale;
if (language != null) {
switch (language) {
case "de":
locale = new Locale("de", "DE");
break;
case "en":
default:
locale = defaultLocale;
}
}
setLanguage(locale);
}
private BundleManager(){
bundleMap = new HashMap<>();
currentLocale = defaultLocale;
}
private void reloadBundles(){
for (Object o : bundleMap.entrySet()) {
Map.Entry pair = (Map.Entry) o;
String key = (String) pair.getKey();
bundleMap.put(key, new ModuleResourceBundle(key, currentLocale));
}
}
private ModuleResourceBundle loadBundle(@NotNull String baseName){
if (bundleMap.containsKey(baseName)){
return bundleMap.get(baseName);
} else {
ModuleResourceBundle bundle = new ModuleResourceBundle(baseName, currentLocale);
bundleMap.put(baseName, bundle);
return bundle;
}
}
}
package org.vadere.util.lang;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
/**
* Based StackOverflow post https://stackoverflow.com/a/4325119
*/
public class ModuleResourceBundle extends ResourceBundle {
protected static final Control CONTROL = new MultiResourceBundleControl();
private Properties properties;
public ModuleResourceBundle(String baseName, Locale locale){
setParent(ResourceBundle.getBundle(baseName, locale, CONTROL));
}
protected ModuleResourceBundle(Properties properties){
this.properties = properties;
}
@Override
protected Object handleGetObject(@NotNull String key) {
Object value = properties != null ? properties.get(key) : null;
if (value == null){
value = parent != null ? parent.getObject(key) : null;
if (value == null){
return "!" + key + "!";
}
}
return value;
}
@NotNull
@Override
@SuppressWarnings("unchecked")
public Enumeration<String> getKeys() {
return properties != null ? (Enumeration<String>) properties.propertyNames() : parent.getKeys();
}
protected static class MultiResourceBundleControl extends Control {
private static final String DEFAULT_LANG_TAG = "en";
@Override
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
return super.getCandidateLocales(baseName, locale);
}
@Override
public Locale getFallbackLocale(String baseName, Locale locale) {
return super.getFallbackLocale(baseName, locale);
}
@Override
public ResourceBundle newBundle(String baseName, Locale locale, String format,
ClassLoader loader, boolean reload)
throws IOException {
if (locale.getLanguage().isEmpty())
return null;
Properties properties = load(baseName, locale, loader);
String include = properties.getProperty("include");
if (include != null){
for (String includeBasename : include.split("\\s*,\\s*")){
properties.putAll(load(includeBasename, locale, loader));
}
}
return new ModuleResourceBundle(properties);
}
private Properties load(String baseName, Locale locale, ClassLoader loader) throws IOException {
Properties properties = new Properties();
String lang_tag = locale.getLanguage().endsWith(DEFAULT_LANG_TAG) ? "" : "_" + locale.getLanguage() + "_" + locale.getCountry();
InputStream stream = loader.getResourceAsStream(baseName + lang_tag +".properties");
properties.load(stream);
return properties;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment