I'm programming an application which uses translation strings (.properties files); those strings are also made of non-latin characters (actually, they are copypastas like lenny smiles and stuff like this). My problem is, when I launch it inside my IDE Netbeans clicking on "clean and build" and then "run", everything goes fine and all the strings are displayed properly... the program acts as intended; but when I export my project as a fat jar (I use Maven shade plugin which also includes my properties files) and when I launch it double-clicking on its icon (still being on Windows) everything is messed up as some strings are not displayed:
inside my program, I use the class LocalisationService
(code follows) to load strings inside different ArrayList. Running my project using Netbeans, strings are all loaded correctly (that's the supposed behaviour). Running my jar outside Netbeans, only 1/5 are loaded properly. I have a huge number of "String not found" entries in my arraylists and this means that, inside my LocalisationService
class, method getString
catches MissingResourceException
exception. But actually those resources aren't missing, I mean, I include them properly in my Jar and Netbeans runs my project straight as it is supposed to do, so...
I have totally no idea on what could cause this issue: my IDE project encoding is set on UTF-8 so there shouldn't be any problems... Maven runs my project using:
cd C:\Users\utente\Documents\NetBeansProjects\mavenproject1; "JAVA_HOME=C:\\Program Files\\Java\\jdk1.8.0_40" cmd /c "\"\"C:\\Program Files\\NetBeans 8.0.2\\java\\maven\\bin\\mvn.bat\" -Dexec.args=\"-classpath %classpath bot.Main\" -Dexec.executable=\"C:\\Program Files\\Java\\jdk1.8.0_40\\bin\\java.exe\" -Dmaven.ext.class.path=\"C:\\Program Files\\NetBeans 8.0.2\\java\\maven-nblib\\netbeans-eventspy.jar\" -Dfile.encoding=UTF-8 org.codehaus.mojo:exec-maven-plugin:1.2.1:exec\""
I have the same problem on Ubuntu, strings are messed up launching my file from terminal with
/usr/bin/java -jar myproject.jar
Here is the class LocalisationService I use to retrieve the correct localisation string using a key:
public class LocalisationService {
private static LocalisationService instance = null;
private final HashMap<String, String> supportedLanguages = new HashMap<>();
private ResourceBundle english;
private ResourceBundle italian;
private class CustomClassLoader extends ClassLoader {
public CustomClassLoader(ClassLoader parent) {
super(parent);
}
public InputStream getResourceAsStream(String name) {
InputStream utf8in = getParent().getResourceAsStream(name);
if (utf8in != null) {
try {
byte[] utf8Bytes = new byte[utf8in.available()];
utf8in.read(utf8Bytes, 0, utf8Bytes.length);
byte[] iso8859Bytes = new String(utf8Bytes, "UTF-8").getBytes("ISO-8859-1");
return new ByteArrayInputStream(iso8859Bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
utf8in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
/**
* Singleton
* @return Instance of localisation service
*/
public static LocalisationService getInstance() {
if (instance == null) {
synchronized (LocalisationService.class) {
if (instance == null) {
instance = new LocalisationService();
}
}
}
return instance;
}
/**
* Private constructor due to singleton
*/
private LocalisationService() {
CustomClassLoader loader = new CustomClassLoader(Thread.currentThread().getContextClassLoader());
english = ResourceBundle.getBundle("localisation.strings", new Locale("en", "US"), loader);
supportedLanguages.put("en", "English");
italian = ResourceBundle.getBundle("localisation.strings", new Locale("it", "IT"), loader);
supportedLanguages.put("it", "Italiano");
}
/**
* Get a string in default language (en)
* @param key key of the resource to fetch
* @return fetched string or error message otherwise
*/
public String getString(String key) {
String result;
try {
result = english.getString(key);
} catch (MissingResourceException e) {
System.out.println("not found key... "+key);
result = "String not found";
}
return result;
}
/**
* Get a string in default language
* @param key key of the resource to fetch from localisations
* @param language code key for language (such as "EN" for english)
* @return fetched string or error message otherwise
*/
public String getString(String key, String language) {
String result;
try {
switch (language.toLowerCase()) {
case "en":
result = english.getString(key);
break;
case "it":
result = italian.getString(key);
break;
default:
result = english.getString(key);
break;
}
} catch (MissingResourceException e) {
result = english.getString(key);
}
return result;
}
public HashMap<String, String> getSupportedLanguages() {
return supportedLanguages;
}
public String getLanguageCodeByName(String language) {
return supportedLanguages.entrySet().stream().filter(x -> x.getValue().equals(language)).findFirst().get().getKey();
}
}
My project has no errors at all, neither warnings... I also tried running my jar file using, on Ubuntu:
/usr/bin/java -Dfile.encoding=UTF-8 -jar myproject.jar
but still with no luck.
I really hope you guys may help me, I'm stuck on this issue since 2 days with no solutions at all...