Enhanced translation-related tools.

No UI, because there's limited interest for typical users, so it's a
beanshell-only tool for now.
This commit is contained in:
Zukero
2018-09-08 15:37:29 +02:00
parent 3800bf8ff0
commit 3e8d578474
7 changed files with 263 additions and 36 deletions

View File

@@ -38,7 +38,7 @@ public class WorkspaceSettings {
public static String DEFAULT_IMG_EDITOR_COMMAND = "gimp";
public Setting<String> imageEditorCommand = new PrimitiveSetting<String>("imageEditorCommand", DEFAULT_IMG_EDITOR_COMMAND);
public static String[] LANGUAGE_LIST = new String[]{null, "de", "ru", "pl", "fr", "it", "es", "nl", "uk", "ca", "sv", "pt", "pt_BR", "zh_Hant", "zh_Hans", "ja", "cs", "tr", "ko", "hu", "sl", "bg", "id", "fi", "th", "gl", "ms" ,"pa", "az"};
public static String[] LANGUAGE_LIST = new String[]{null, "de", "ru", "pl", "fr", "it", "es", "nl", "uk", "ca", "sv", "pt", "pt_BR", "zh_Hant", "zh_Hans", "ja", "cs", "tr", "ko", "hu", "sl", "bg", "id", "fi", "th", "gl", "ms" ,"pa", "az", "nb"};
public Setting<String> translatorLanguage = new NullDefaultPrimitiveSetting<String>("translatorLanguage");
public static Boolean DEFAULT_ALLOW_INTERNET = true;
public Setting<Boolean> useInternet = new PrimitiveSetting<Boolean>("useInternet", DEFAULT_ALLOW_INTERNET);

View File

@@ -132,6 +132,7 @@ public class AboutEditor extends Editor {
editorTabsHolder.add("BeanShell License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.LGPLv3.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("SipHash for Java License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.siphash-zackehh.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("jsoup License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.jsoup.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("General PO Parser License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.GPLv3.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
editorTabsHolder.add("ATCS License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.GPLv3.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
}

View File

@@ -0,0 +1,86 @@
package com.gpl.rpg.atcontentstudio.ui.tools.i18n;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class PoPotWriter {
Map<String, List<String>> stringsResources = new LinkedHashMap<String, List<String>>();
Map<String, String> translations = new LinkedHashMap<String, String>();
File f;
public static void writePoFile(Map<String, List<String>> stringsResources, Map<String, String> translations, File destination) {
try {
FileWriter fw = new FileWriter(destination);
if (translations.get("") != null) {
fw.write(translations.get(""));
writeEndOfEntry(fw);
}
if (translations.get("translator-credits") != null) {
List<String> refs = new LinkedList<String>();
refs.add("[none]");
writeReferences(fw, refs);
writeMsgId(fw, "translator-credits");
writeMsgStr(fw, translations.get("translator-credits"));
writeEndOfEntry(fw);
}
for (String msg : stringsResources.keySet()) {
writeReferences(fw, stringsResources.get(msg));
writeMsgId(fw, msg);
writeMsgStr(fw, translations.get(msg));
writeEndOfEntry(fw);
}
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writePotFile(Map<String, List<String>> stringsResources, File destination) {
try {
FileWriter fw = new FileWriter(destination);
for (String msg : stringsResources.keySet()) {
writeReferences(fw, stringsResources.get(msg));
writeMsgId(fw, msg);
writeMsgStr(fw, "");
writeEndOfEntry(fw);
}
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeReferences(Writer w, List<String> references) throws IOException {
for (String ref : references) {
w.write("#: ");
w.write(ref);
w.write("\n");
}
}
private static void writeMsgId(Writer w, String msg) throws IOException {
w.write("msgid \"");
w.write(msg);
w.write("\"\n");
}
private static void writeMsgStr(Writer w, String translation) throws IOException {
w.write("msgstr \"");
w.write(translation == null ? "" : translation);
w.write("\"\n");
}
private static void writeEndOfEntry(Writer w) throws IOException {
w.write("\n");
}
}

View File

@@ -1,18 +1,42 @@
package com.gpl.rpg.atcontentstudio.ui.tools.i18n;
import java.io.File;
import java.io.FileFilter;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.JOptionPane;
import com.gpl.rpg.atcontentstudio.model.Project;
import net.launchpad.tobal.poparser.POEntry;
import net.launchpad.tobal.poparser.POFile;
import net.launchpad.tobal.poparser.POParser;
/**
*
* @author Kevin
*
* To use this, paste the following script in the beanshell console of ATCS.
* Don't forget to change the project number to suit your needs.
*
* import com.gpl.rpg.atcontentstudio.model.Workspace;
* import com.gpl.rpg.atcontentstudio.ui.tools.i18n.PotGenerator;
* import com.gpl.rpg.atcontentstudio.ui.tools.i18n.PotComparator;
*
* proj = Workspace.activeWorkspace.projects.get(7);
* PotGenerator.generatePotFileForProject(proj);
* comp = new PotComparator(proj);
* comp.compare();
* comp.updatePoFiles(proj);
*
*
*
*/
public class PotComparator {
Map<String, List<String>> stringsResourcesNew = new LinkedHashMap<String, List<String>>();
@@ -20,6 +44,10 @@ public class PotComparator {
Map<String, List<String>> stringsResourcesOld = new LinkedHashMap<String, List<String>>();
Map<String, String> resourcesStringsOld = new LinkedHashMap<String, String>();
Map<String, String> msgIdToReplace = new LinkedHashMap<String, String>();
List<String> msgIdToReview = new LinkedList<String>();
List<String> msgIdOutdated = new LinkedList<String>();
public PotComparator(Project proj) {
@@ -47,10 +75,13 @@ public class PotComparator {
String msgid = msgids.get(0);
if (msgids.size() > 1) {
for (int i = 1; i < msgids.size(); i++) {
msgid += "\n";
msgid += msgids.get(i);
}
}
if (msgid.contains("\\n")) {
msgid = msgid.replaceAll("\\\\n", "\\\\n\"\n\"");
msgid = "\"\n\""+msgid;
}
for (String resLine : resources) {
String[] resArray = resLine.split(" ");
for (String res : resArray) {
@@ -72,27 +103,29 @@ public class PotComparator {
if (!newString.equals(oldString)) {
List<String> allOldResources = stringsResourcesOld.get(oldString);
List<String> allNewResources = stringsResourcesNew.get(oldString);
System.out.println("---------------------------------------------");
System.out.println("--- TYPO CHECK ------------------------------");
System.out.println("---------------------------------------------");
System.out.println("String at: "+oldRes);
StringBuffer sb = new StringBuffer();
sb.append("---------------------------------------------\n");
sb.append("--- TYPO CHECK ------------------------------\n");
sb.append("---------------------------------------------\n");
sb.append("String at: "+oldRes+"\n");
if (allOldResources.size() > 1) {
System.out.println("Also present at:");
sb.append("Also present at:\n");
for (String res : allOldResources) {
if (!res.equals(oldRes)) {
System.out.println("- "+res);
sb.append("- "+res+"\n");
}
}
}
if (allNewResources != null) {
System.out.println("Still present at: ");
sb.append("Still present at: \n");
for (String res : allNewResources) {
System.out.println("- "+res);
sb.append("- "+res+"\n");
}
}
System.out.println("Was : \""+oldString+"\"");
System.out.println("Now : \""+newString+"\"");
sb.append("Was : \""+oldString+"\"\n");
sb.append("Now : \""+newString+"\"\n");
System.out.println(sb.toString());
showTypoDialog(oldString, newString, sb.toString());
}
} else {
List<String> allOldResources = stringsResourcesOld.get(oldString);
@@ -151,4 +184,127 @@ public class PotComparator {
}
}
private void showTypoDialog(String oldMsg, String newMsg, String checkReport) {
String typo = "Typo";
String review = "Review";
String outdated = "Outdated";
String none = "None";
Object[] options = new Object[] {typo, review, outdated, none};
int result = JOptionPane.showOptionDialog(null, checkReport, "Choose action", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, typo);
if (result < 0 || result >= options.length) {
System.out.println("No decision");
return;
}
System.out.println("Decision: "+options[result]);
if (options[result] != none) {
msgIdToReplace.put(oldMsg, newMsg);
if (options[result] == review) {
msgIdToReview.add(newMsg);
} else if (options[result] == outdated) {
msgIdOutdated.add(newMsg);
}
}
}
public void updatePoFiles(Project proj) {
File poFolder = new File(proj.baseContent.baseFolder.getAbsolutePath()+File.separator+"assets"+File.separator+"translation");
File[] poFiles = poFolder.listFiles(new FileFilter() {
@Override
public boolean accept(File arg0) {
return arg0.isFile() && arg0.getName().endsWith(".po");
}
});
for (File f : poFiles) {
updatePoFile(proj, f);
}
}
private void updatePoFile(Project proj, File f) {
POParser parser = new POParser();
POFile poFile = parser.parseFile(f);
Map<String, String> translations = new LinkedHashMap<String, String>();
//Collect existing translations
if (poFile.getHeader() != null) {
Vector<String> msgstrs = poFile.getHeader().getStringsByType(POEntry.StringType.HEADER);
String header = "";
if (!msgstrs.isEmpty()) {
if (msgstrs.size() == 1) {
header = msgstrs.get(0);
} else {
for (String msgstr : msgstrs) {
header += msgstr;
header += "\n";
}
}
}
translations.put("", header);
}
for (POEntry entry : poFile.getEntryArray()) {
Vector<String> msgids = entry.getStringsByType(POEntry.StringType.MSGID);
Vector<String> msgstrs = entry.getStringsByType(POEntry.StringType.MSGSTR);
if (msgids == null || msgids.size() == 0) continue;
String msgid = msgids.get(0);
if (msgids.size() > 1) {
for (int i = 1; i < msgids.size(); i++) {
msgid += msgids.get(i);
}
}
if (msgid.contains("\\n")) {
msgid = msgid.replaceAll("\\\\n", "\\\\n\"\n\"");
msgid = "\"\n\""+msgid;
}
String translation = "";
if (!msgstrs.isEmpty()) {
if (msgstrs.size() == 1) {
translation = msgstrs.get(0);
} else {
for (String msgstr : msgstrs) {
translation += msgstr;
}
}
if (translation.contains("\\n")) {
translation = translation.replaceAll("\\\\n", "\\\\n\"\n\"");
translation = "\"\n\""+translation;
}
}
translations.put(msgid, translation);
}
//Patch data
for (String oldId : msgIdToReplace.keySet()) {
String newId = msgIdToReplace.get(oldId);
if (translations.containsKey(oldId)) {
String trans = translations.get(oldId);
translations.remove(oldId);
translations.put(newId, trans);
}
}
for (String msgid : msgIdToReview) {
if (translations.containsKey(msgid)) {
String trans = translations.get(msgid);
if (trans != null && trans.length() >= 1) translations.put(msgid, "[REVIEW]"+trans);
}
}
for (String msgid : msgIdOutdated) {
if (translations.containsKey(msgid)) {
String trans = translations.get(msgid);
if (trans != null && trans.length() >= 1) translations.put(msgid, "[OUTDATED]"+trans);
}
}
PoPotWriter.writePoFile(stringsResourcesNew, translations, new File(proj.alteredContent.baseFolder.getAbsolutePath()+File.separator+f.getName()));
}
}

View File

@@ -1,8 +1,6 @@
package com.gpl.rpg.atcontentstudio.ui.tools.i18n;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -69,30 +67,13 @@ public class PotGenerator {
}
File f = new File(proj.alteredContent.baseFolder, "english.pot");
try {
FileWriter fw = new FileWriter(f);
for (String msg : stringsResources.keySet()) {
for (String ctx : stringsResources.get(msg)) {
fw.write("#: ");
fw.write(ctx);
fw.write("\n");
}
fw.write("msgid \"");
fw.write(msg);
fw.write("\"\nmsgstr \"\"\n\n");
}
fw.flush();
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PoPotWriter.writePotFile(stringsResources, f);
}
private static void pushString (Map<String, List<String>> stringsResources, Map<String, String> resourcesStrings, String translatableString, String resourceIdentifier) {
if (translatableString == null) return;
if (translatableString.length() == 0) return;
if (translatableString.contains("\n")) {
translatableString = translatableString.replaceAll("\n", "\\\\n\"\n\"");
translatableString = "\"\n\""+translatableString;

View File

@@ -58,6 +58,10 @@ public class POFile
{
return entries.length;
}
public POEntry getHeader() {
return header;
}
/**
* Checks if the specified flag is set in the entry,

View File

@@ -8,11 +8,10 @@
*/
package net.launchpad.tobal.poparser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.BufferedReader;
import java.util.Vector;
public class POParser