de.rpgframework.MultiLanguageResourceBundle Maven / Gradle / Ivy
package de.rpgframework;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/**
* @author prelle
*
*/
public class MultiLanguageResourceBundle {
private final static Logger logger = System.getLogger("de.rpgframework");
private static PrintWriter MISSING_FILE;
private static List reportedFiles;
private static Path myPath;
private String key;
private String defaultLang;
private Map resources;
private Map MISSING = new HashMap<>();
private Map> reportedKeys = new HashMap<>();
//--------------------------------------------------------------------
static {
reportedFiles = new ArrayList();
try {
if (System.getProperty("logdir")==null) {
myPath = Files.createTempDirectory("rpgframework");
if (Files.notExists(myPath)) {
Files.createDirectories(myPath);
}
MISSING_FILE = new PrintWriter(myPath+System.getProperty("file.separator")+"/missing-files.txt");
myPath.toFile().deleteOnExit();
System.err.println("Missing keys written to "+myPath);
} else {
myPath = Paths.get(System.getProperty("logdir"));
if (Files.notExists(myPath)) {
Files.createDirectories(myPath);
}
MISSING_FILE = new PrintWriter(myPath+System.getProperty("file.separator")+"/missing-files.txt");
System.err.println("Missing keys written to "+System.getProperty("logdir")+System.getProperty("file.separator")+"/missing-keys.txt");
}
} catch (IOException e) {
logger.log(Level.ERROR,"Failed setting up file for missing keys",e);
}
}
//--------------------------------------------------------------------
static void reportFile(String id, String lang) {
String key = id+"_"+lang;
if (reportedFiles.contains(key))
return;
logger.log(Level.WARNING, "Missing file "+id+" for lang "+lang);
reportedFiles.add(key);
MISSING_FILE.println(key);
MISSING_FILE.flush();
}
//-------------------------------------------------------------------
public MultiLanguageResourceBundle(String id, String resourcePrefix, Locale... locales) {
this(resourcePrefix+"."+id.toLowerCase()+".i18n."+id.toLowerCase(), locales);
}
//-------------------------------------------------------------------
public MultiLanguageResourceBundle(String fullName, Locale... locales) {
/* Load all locales */
key = fullName;
resources = new HashMap();
for (Locale loc: locales) {
if (defaultLang==null) {
defaultLang = loc.getLanguage();
}
try {
ResourceBundle bundle = ResourceBundle.getBundle(key, loc);
if (!loc.getLanguage().equals(bundle.getLocale().getLanguage()) && !"en".equals(loc.getLanguage())) {
logger.log(Level.DEBUG, "Expected {0} but found {1}", key+"_"+loc.getLanguage()+".properties", key+".properties");
}
resources.put(loc.getLanguage(), bundle);
} catch (MissingResourceException e) {
logger.log(Level.ERROR, e.toString());
reportFile(key, loc.getLanguage());
}
}
if (resources.isEmpty()) {
try {
ResourceBundle bundle = ResourceBundle.getBundle(key);
resources.put(defaultLang, bundle);
} catch (MissingResourceException e) {
logger.log(Level.ERROR, e.toString());
System.exit(1);
}
}
}
//-------------------------------------------------------------------
public MultiLanguageResourceBundle(Path dir, String name, Locale... locales) {
/* Load all locales */
key = name;
resources = new HashMap();
for (Locale loc: locales) {
if (defaultLang==null) {
defaultLang = loc.getLanguage();
}
Path fullFile = dir.resolve(name+"_"+loc.getLanguage()+".properties");
if (!Files.exists(fullFile) && loc.getLanguage().equals(defaultLang)) {
fullFile = dir.resolve(name+".properties");
}
try {
if (!Files.exists(fullFile)) {
logger.log(Level.WARNING, "Missing resource file {0}", fullFile);
reportFile(key, loc.getLanguage());
} else {
PropertyResourceBundle bundle = new PropertyResourceBundle(new FileReader(fullFile.toFile()));
resources.put(loc.getLanguage(), bundle);
}
} catch (IOException e) {
logger.log(Level.ERROR, e.toString());
reportFile(key, loc.getLanguage());
}
}
if (resources.isEmpty()) {
try {
ResourceBundle bundle = ResourceBundle.getBundle(key);
resources.put(defaultLang, bundle);
} catch (MissingResourceException e) {
logger.log(Level.ERROR, e.toString());
throw new RuntimeException("Missing language file "+dir.resolve(name+".properties").toString());
// System.exit(1);
}
}
}
//-------------------------------------------------------------------
public MultiLanguageResourceBundle(Class> cls, Locale... locales) {
/* Load all locales */
key = cls.getName();
resources = new HashMap();
for (Locale loc: locales) {
if (defaultLang==null) {
defaultLang = loc.getLanguage();
}
ResourceBundle bundle;
try {
bundle = ResourceBundle.getBundle(cls.getName(), loc, cls.getModule());
if (!loc.getLanguage().equals(bundle.getLocale().getLanguage()) && !"en".equals(loc.getLanguage())) {
logger.log(Level.DEBUG, "Expected {0} but found {1}", key+"_"+loc.getLanguage()+".properties", key+".properties");
}
resources.put(loc.getLanguage(), bundle);
} catch (Exception e) {
logger.log(Level.ERROR,"Failed loading "+cls.getName()+".properties for module "+cls.getModule());
throw e;
}
}
}
//-------------------------------------------------------------------
public MultiLanguageResourceBundle(Class> cls, String name, Locale... locales) {
/* Load all locales */
key = cls.getPackageName()+"."+name;
resources = new HashMap();
//key = key.replaceAll("\\.", "/");
for (Locale loc: locales) {
if (defaultLang==null) {
defaultLang = loc.getLanguage();
}
try {
ResourceBundle bundle = ResourceBundle.getBundle(key, loc, cls.getModule());
if (!loc.getLanguage().equals(bundle.getLocale().getLanguage()) && !"en".equals(loc.getLanguage())) {
logger.log(Level.DEBUG, "Expected {0} but found {1}", key+"_"+loc.getLanguage()+".properties", key+".properties");
}
resources.put(loc.getLanguage(), bundle);
} catch (MissingResourceException e) {
logger.log(Level.ERROR, e.toString());
reportFile(key, loc.getLanguage());
}
}
}
//-------------------------------------------------------------------
private void reportKey(String key, String lang, ResourceBundle bundle) {
List reported = reportedKeys.get(lang);
if (reported==null) {
reported = new ArrayList<>();
reportedKeys.put(lang, reported);
}
if (reported.contains(key))
return;
reported.add(key);
PrintWriter out = MISSING.get(lang);
//System.out.println("Report "+key+" for "+lang);
try {
if (out==null) {
String filename = "keys-"+this.key+"_"+lang+".txt";
out = new PrintWriter(new FileWriter(myPath+System.getProperty("file.separator")+filename));
MISSING.put(lang, out);
}
out.println(key+"=");
out.flush();
} catch (IOException e) {
logger.log(Level.ERROR, "Failed creating missing keys file",e);
}
}
//-------------------------------------------------------------------
public ResourceBundle getDefault() {
return resources.get(defaultLang);
}
//-------------------------------------------------------------------
public String getBundleName() {
return key;
}
//-------------------------------------------------------------------
public String getString(String key) {
return getString(key, Locale.forLanguageTag(defaultLang));
}
//-------------------------------------------------------------------
public String format(String key, Object ...data) {
ResourceBundle res = resources.get(defaultLang);
if (res==null) {
System.err.println("Missing resourcebundle for language "+defaultLang+" for "+this.key);
throw new RuntimeException("Missing resourcebundle for language "+defaultLang+" for "+this.key+"\nAvailable translations: "+resources.keySet());
}
return ResourceI18N.format(resources.get(defaultLang),key, data);
}
//-------------------------------------------------------------------
public String format(String key, Locale loc, Object ...data) {
if (resources.get(loc.getLanguage())==null) {
return ResourceI18N.format(resources.get(defaultLang),key, data);
}
return ResourceI18N.format(resources.get(loc.getLanguage()), key, data);
}
//-------------------------------------------------------------------
public String getString(String key, Locale loc) {
if (key.endsWith(".null")) throw new IllegalArgumentException("I18N key contains Null");
ResourceBundle bundle = resources.get(loc.getLanguage());
if (bundle!=null) {
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
if (key.endsWith(".prodname"))
return key;
reportKey(key, loc.getLanguage(), bundle);
// Fallthrough to default language
}
}
// Now try default
bundle = resources.get(defaultLang);
if (bundle==null) {
String fileKey = this.key+"_"+loc.getLanguage();
reportFile(fileKey, loc.getLanguage());
}
try {
return resources.get(defaultLang).getString(key);
} catch (NullPointerException e) {
logger.log(Level.ERROR, "No Resource file for {0} language {1}",key,defaultLang);
return null;
} catch (MissingResourceException e) {
if (key.endsWith(".prodname"))
return key;
// reportKey(e.getKey(), defaultLang);
return key;
}
}
//-------------------------------------------------------------------
public String getString(List keys, Locale loc) {
ResourceBundle RES = resources.get(loc.getLanguage());
if (RES==null) {
RES = resources.get(defaultLang);
}
if (RES==null) {
logger.log(Level.ERROR, "Missing resource bundle {0} for language {1} or {2}", key, loc.getLanguage(), defaultLang);
throw new NullPointerException("Missing language instance for "+loc.getLanguage()+" of "+key);
}
for (String key : keys) {
if (RES.containsKey(key))
return RES.getString(key);
}
logger.log(Level.ERROR, "None of the following keys found: " + keys + " in " + key);
for (String tmp : keys) {
reportKey(tmp, loc.getLanguage(), RES);
}
return null;
}
//-------------------------------------------------------------------
public String getBaseBundleName() {
return resources.get(defaultLang).getBaseBundleName();
}
//-------------------------------------------------------------------
public void flushMissingKeys() {
MISSING.values().forEach(writer -> writer.flush());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy