bcv-vf/src/main/java/the/bytecode/club/bytecodeviewer/translation/Language.java

167 lines
5.9 KiB
Java
Raw Normal View History

package the.bytecode.club.bytecodeviewer.translation;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.collections4.map.LinkedMap;
import org.apache.commons.io.IOUtils;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Resources;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
2021-07-07 05:56:29 +00:00
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
/**
* All of the supported languages
*
* @author Konloch
* @since 6/28/2021
*/
public enum Language
{
2021-07-07 09:00:14 +00:00
ARABIC("/translations/arabic.json", "عربى", "English", "ab"),
ENGLISH("/translations/english.json", "English", "English", "en"),
FRENCH("/translations/french.json", "Français", "English", "fr"),
GERMAN("/translations/german.json", "Deutsch", "German", "de"),
//HINDI("/translations/hindi.json", "हिंदी", "English", "hi"),
JAPANESE("/translations/japanese.json", "日本語", "English", "ja"),
MALAY("/translations/malay.json", "Bahasa Melayu", "English", "ms"),
MANDARIN("/translations/mandarin.json", "普通话", "Mandarin", "zh_cn", "zh"),
PORTUGUESE("/translations/portuguese.json", "Português", "English", "pt"),
RUSSIAN("/translations/russian.json", "русский", "English", "ru"),
SPANISH("/translations/spanish.json", "Español", "English", "es"),
;
private static final HashedMap<String, Language> languageCodeLookup;
static
{
languageCodeLookup = new HashedMap<>();
for(Language l : values())
l.languageCode.forEach((langCode)->
languageCodeLookup.put(langCode, l));
}
private final String resourcePath;
private final String readableName;
2021-07-07 09:00:14 +00:00
private final String htmlIdentifier;
private final HashSet<String> languageCode;
2021-07-07 09:00:14 +00:00
Language(String resourcePath, String readableName, String htmlIdentifier, String... languageCodes)
{
this.resourcePath = resourcePath;
this.readableName = readableName;
2021-07-07 09:00:14 +00:00
this.htmlIdentifier = htmlIdentifier.toLowerCase();
this.languageCode = new HashSet<>(Arrays.asList(languageCodes));
}
public void loadLanguage() throws IOException
{
printMissingLanguageKeys();
HashMap<String, String> translationMap = BytecodeViewer.gson.fromJson(
Resources.loadResourceAsString(resourcePath),
new TypeToken<HashMap<String, String>>(){}.getType());
for(Translation translation : Translation.values())
{
TranslatedComponent text = translation.getTranslatedComponent();
//skip translating if the language config is missing the translation key
if(!translationMap.containsKey(text.key))
continue;
//update translation text value
text.value = translationMap.get(text.key);
2021-07-07 09:00:14 +00:00
//translate constant strings
try {
TranslatedStrings str = TranslatedStrings.valueOf(text.key);
str.setText(text.value);
} catch (IllegalArgumentException e) { }
//check if translation key has been assigned to a component,
//on fail print an error alerting the devs
2021-07-07 09:00:14 +00:00
if(translation.getTranslatedComponent().runOnUpdate.isEmpty()
&& TranslatedStrings.nameSet.contains(translation.name()))
{
System.err.println("Translation Reference " + translation.name() + " is missing component attachment, skipping...");
continue;
}
//trigger translation event
translation.getTranslatedComponent().runOnUpdate.forEach(Runnable::run);
}
}
//TODO
// When adding new Translation Components:
// 1) start by adding the strings into the english.json
// 2) run this function to get the keys and add them into the Translation.java enum
// 3) replace the swing component (MainViewerGUI) with a translated component
// and reference the correct translation key
// 4) add the translation key to the rest of the translation files
public void printMissingLanguageKeys() throws IOException
{
if(this != ENGLISH)
return;
LinkedMap<String, String> translationMap = BytecodeViewer.gson.fromJson(
Resources.loadResourceAsString(resourcePath),
new TypeToken<LinkedMap<String, String>>(){}.getType());
HashSet<String> existingKeys = new HashSet<>();
for(Translation t : Translation.values())
existingKeys.add(t.name());
for(String key : translationMap.keySet())
2021-07-07 09:00:14 +00:00
if(!existingKeys.contains(key))
System.err.println(key + ",");
}
public String getResourcePath()
{
return resourcePath;
}
public HashSet<String> getLanguageCode()
{
return languageCode;
}
public String getReadableName()
{
return readableName;
}
2021-07-07 09:00:14 +00:00
public String getHTMLPath(String identifier)
{
return "translations/html/" + identifier + "." + htmlIdentifier + ".html";
}
public static HashedMap<String, Language> getLanguageCodeLookup()
{
return languageCodeLookup;
}
}