All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.rpgframework.MultiLanguageResourceBundle Maven / Gradle / Ivy

There is a newer version: 5.3.0
Show newest version
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