mirror of
https://github.com/OMGeeky/ATCS.git
synced 2026-02-23 15:38:23 +01:00
Level 2 of weblate integration. Rudimentary UI, but working well.
This commit is contained in:
@@ -13,5 +13,6 @@
|
|||||||
<classpathentry kind="lib" path="lib/ui.jar"/>
|
<classpathentry kind="lib" path="lib/ui.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
|
<classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.3.jar"/>
|
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.3.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/jsoup-1.10.2.jar" sourcepath="lib/jsoup-1.10.2-sources.jar"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|||||||
BIN
lib/jsoup-1.10.2-sources.jar
Normal file
BIN
lib/jsoup-1.10.2-sources.jar
Normal file
Binary file not shown.
BIN
lib/jsoup-1.10.2.jar
Normal file
BIN
lib/jsoup-1.10.2.jar
Normal file
Binary file not shown.
@@ -47,6 +47,7 @@ import javax.swing.event.DocumentListener;
|
|||||||
import javax.swing.event.ListDataEvent;
|
import javax.swing.event.ListDataEvent;
|
||||||
import javax.swing.event.ListDataListener;
|
import javax.swing.event.ListDataListener;
|
||||||
import javax.swing.text.DefaultFormatter;
|
import javax.swing.text.DefaultFormatter;
|
||||||
|
import javax.swing.text.JTextComponent;
|
||||||
|
|
||||||
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
import com.gpl.rpg.atcontentstudio.ATContentStudio;
|
||||||
import com.gpl.rpg.atcontentstudio.Notification;
|
import com.gpl.rpg.atcontentstudio.Notification;
|
||||||
@@ -63,7 +64,7 @@ import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
|
|||||||
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
|
||||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
|
||||||
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
|
||||||
import com.gpl.rpg.atcontentstudio.utils.HashUtils;
|
import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration;
|
||||||
import com.jidesoft.swing.ComboBoxSearchable;
|
import com.jidesoft.swing.ComboBoxSearchable;
|
||||||
import com.jidesoft.swing.JideBoxLayout;
|
import com.jidesoft.swing.JideBoxLayout;
|
||||||
|
|
||||||
@@ -115,31 +116,36 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
|
|||||||
return addTextField(pane, label, value, false, nullListener);
|
return addTextField(pane, label, value, false, nullListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JTextField addTranslatableTextField(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
public static void addTranslationPane(JPanel pane, final JTextComponent tfComponent, final String initialValue) {if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) {
|
||||||
final JTextField tfField = addTextField(pane, label, initialValue, editable, listener);
|
|
||||||
if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) {
|
|
||||||
JPanel labelPane = new JPanel();
|
JPanel labelPane = new JPanel();
|
||||||
labelPane.setLayout(new JideBoxLayout(labelPane, JideBoxLayout.LINE_AXIS));
|
labelPane.setLayout(new JideBoxLayout(labelPane, JideBoxLayout.LINE_AXIS));
|
||||||
final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue));
|
final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue));
|
||||||
labelPane.add(translateLinkLabel, JideBoxLayout.FIX);
|
labelPane.add(translateLinkLabel, JideBoxLayout.FIX);
|
||||||
labelPane.add(new JPanel(), JideBoxLayout.VARY);
|
final JLabel translationStatus = new JLabel(" - Status: unknown - Retrieving...");
|
||||||
|
labelPane.add(translationStatus, JideBoxLayout.VARY);
|
||||||
|
new Thread() {
|
||||||
|
public void run() {
|
||||||
|
WeblateIntegration.WeblateTranslationUnit unit = WeblateIntegration.getTranslationUnit(initialValue);
|
||||||
|
translationStatus.setText(" - Status: "+unit.status.toString()+" - "+unit.translatedText);
|
||||||
|
};
|
||||||
|
}.start();
|
||||||
pane.add(labelPane, JideBoxLayout.FIX);
|
pane.add(labelPane, JideBoxLayout.FIX);
|
||||||
tfField.getDocument().addDocumentListener(new DocumentListener() {
|
tfComponent.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
@Override
|
@Override
|
||||||
public void removeUpdate(DocumentEvent e) {
|
public void removeUpdate(DocumentEvent e) {
|
||||||
translateLinkLabel.setText(getWeblateLabelLink(tfField.getText()));
|
translateLinkLabel.setText(getWeblateLabelLink(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))));
|
||||||
translateLinkLabel.revalidate();
|
translateLinkLabel.revalidate();
|
||||||
translateLinkLabel.repaint();
|
translateLinkLabel.repaint();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void insertUpdate(DocumentEvent e) {
|
public void insertUpdate(DocumentEvent e) {
|
||||||
translateLinkLabel.setText(getWeblateLabelLink(tfField.getText()));
|
translateLinkLabel.setText(getWeblateLabelLink(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))));
|
||||||
translateLinkLabel.revalidate();
|
translateLinkLabel.revalidate();
|
||||||
translateLinkLabel.repaint();
|
translateLinkLabel.repaint();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void changedUpdate(DocumentEvent e) {
|
public void changedUpdate(DocumentEvent e) {
|
||||||
translateLinkLabel.setText(getWeblateLabelLink(tfField.getText()));
|
translateLinkLabel.setText(getWeblateLabelLink(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))));
|
||||||
translateLinkLabel.revalidate();
|
translateLinkLabel.revalidate();
|
||||||
translateLinkLabel.repaint();
|
translateLinkLabel.repaint();
|
||||||
}
|
}
|
||||||
@@ -150,7 +156,7 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
|
|||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().browse(new URI(getWeblateLabelURI(tfField.getText())));
|
Desktop.getDesktop().browse(new URI(WeblateIntegration.getWeblateLabelURI(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n")))));
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
} catch (URISyntaxException e1) {
|
} catch (URISyntaxException e1) {
|
||||||
@@ -160,15 +166,16 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JTextField addTranslatableTextField(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||||
|
final JTextField tfField = addTextField(pane, label, initialValue, editable, listener);
|
||||||
|
addTranslationPane(pane, tfField, initialValue);
|
||||||
return tfField;
|
return tfField;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getWeblateLabelLink(String text) {
|
public static String getWeblateLabelLink(String text) {
|
||||||
return "<html><a href=\""+getWeblateLabelURI(text)+"\">Translate on weblate</a></html>";
|
return "<html><a href=\""+WeblateIntegration.getWeblateLabelURI(text)+"\">Translate on weblate</a></html>";
|
||||||
}
|
|
||||||
|
|
||||||
public static String getWeblateLabelURI(String text) {
|
|
||||||
return "https://hosted.weblate.org/translate/andors-trail/game-content/"+Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue()+"/?checksum="+HashUtils.weblateHash(text, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JTextField addTextField(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
public static JTextField addTextField(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||||
@@ -217,49 +224,7 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
|
|||||||
|
|
||||||
public static JTextArea addTranslatableTextArea(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
public static JTextArea addTranslatableTextArea(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||||
final JTextArea tfArea = addTextArea(pane, label, initialValue, editable, listener);
|
final JTextArea tfArea = addTextArea(pane, label, initialValue, editable, listener);
|
||||||
if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) {
|
addTranslationPane(pane, tfArea, initialValue);
|
||||||
JPanel labelPane = new JPanel();
|
|
||||||
labelPane.setLayout(new JideBoxLayout(labelPane, JideBoxLayout.LINE_AXIS));
|
|
||||||
final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue));
|
|
||||||
labelPane.add(translateLinkLabel, JideBoxLayout.FIX);
|
|
||||||
labelPane.add(new JPanel(), JideBoxLayout.VARY);
|
|
||||||
pane.add(labelPane, JideBoxLayout.FIX);
|
|
||||||
tfArea.getDocument().addDocumentListener(new DocumentListener() {
|
|
||||||
@Override
|
|
||||||
public void removeUpdate(DocumentEvent e) {
|
|
||||||
translateLinkLabel.setText(getWeblateLabelLink(tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))));
|
|
||||||
translateLinkLabel.revalidate();
|
|
||||||
translateLinkLabel.repaint();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void insertUpdate(DocumentEvent e) {
|
|
||||||
translateLinkLabel.setText(getWeblateLabelLink(tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))));
|
|
||||||
translateLinkLabel.revalidate();
|
|
||||||
translateLinkLabel.repaint();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void changedUpdate(DocumentEvent e) {
|
|
||||||
translateLinkLabel.setText(getWeblateLabelLink(tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))));
|
|
||||||
translateLinkLabel.revalidate();
|
|
||||||
translateLinkLabel.repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
translateLinkLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
|
||||||
translateLinkLabel.addMouseListener(new MouseAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseClicked(MouseEvent e) {
|
|
||||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
|
||||||
try {
|
|
||||||
Desktop.getDesktop().browse(new URI(getWeblateLabelURI(tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n")))));
|
|
||||||
} catch (IOException e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
} catch (URISyntaxException e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return tfArea;
|
return tfArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.gpl.rpg.atcontentstudio.utils;
|
package com.gpl.rpg.atcontentstudio.utils;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -9,38 +8,9 @@ import com.zackehh.siphash.SipHashResult;
|
|||||||
|
|
||||||
public class HashUtils {
|
public class HashUtils {
|
||||||
|
|
||||||
private static final String WEBLATE_SIPASH_KEY = "Weblate Sip Hash";
|
|
||||||
|
|
||||||
private static final Map<String, SipHash> HASHER_CACHE = new LinkedHashMap<String, SipHash>();
|
private static final Map<String, SipHash> HASHER_CACHE = new LinkedHashMap<String, SipHash>();
|
||||||
|
|
||||||
public static String weblateHash(String str, String ctx) {
|
static String siphash(String key, byte[] data) {
|
||||||
|
|
||||||
byte[] data = null;
|
|
||||||
|
|
||||||
if (str != null) {
|
|
||||||
byte[] strBytes;
|
|
||||||
try {
|
|
||||||
strBytes = str.getBytes("UTF-8");
|
|
||||||
byte[] ctxBytes = ctx.getBytes("UTF-8");
|
|
||||||
data = new byte[strBytes.length + ctxBytes.length];
|
|
||||||
System.arraycopy(strBytes, 0, data, 0, strBytes.length);
|
|
||||||
System.arraycopy(ctxBytes, 0, data, strBytes.length, ctxBytes.length);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
data = ctx.getBytes("UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return siphash(WEBLATE_SIPASH_KEY, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String siphash(String key, byte[] data) {
|
|
||||||
SipHash hasher = HASHER_CACHE.get(key);
|
SipHash hasher = HASHER_CACHE.get(key);
|
||||||
if (hasher == null) {
|
if (hasher == null) {
|
||||||
hasher= new SipHash("Weblate Sip Hash".getBytes());
|
hasher= new SipHash("Weblate Sip Hash".getBytes());
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.gpl.rpg.atcontentstudio.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
|
||||||
|
import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||||
|
import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration.WeblateTranslationUnit.Status;
|
||||||
|
|
||||||
|
public class WeblateIntegration {
|
||||||
|
|
||||||
|
static final String WEBLATE_SIPASH_KEY = "Weblate Sip Hash";
|
||||||
|
|
||||||
|
public static String weblateHash(String str, String ctx) {
|
||||||
|
|
||||||
|
byte[] data = null;
|
||||||
|
|
||||||
|
if (str != null) {
|
||||||
|
byte[] strBytes;
|
||||||
|
try {
|
||||||
|
strBytes = str.getBytes("UTF-8");
|
||||||
|
byte[] ctxBytes = ctx.getBytes("UTF-8");
|
||||||
|
data = new byte[strBytes.length + ctxBytes.length];
|
||||||
|
System.arraycopy(strBytes, 0, data, 0, strBytes.length);
|
||||||
|
System.arraycopy(ctxBytes, 0, data, strBytes.length, ctxBytes.length);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
data = ctx.getBytes("UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HashUtils.siphash(WEBLATE_SIPASH_KEY, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWeblateLabelURI(String text) {
|
||||||
|
return "https://hosted.weblate.org/translate/andors-trail/game-content/"+Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue()+"/?checksum="+weblateHash(text, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WeblateTranslationUnit {
|
||||||
|
public enum Status {
|
||||||
|
absent, notTranslated, warning, fuzzy, done
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status status;
|
||||||
|
public String translatedText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WeblateTranslationUnit getTranslationUnit(String text) {
|
||||||
|
WeblateTranslationUnit unit = new WeblateTranslationUnit();
|
||||||
|
unit.status = Status.absent;
|
||||||
|
unit.translatedText = "Cannot find this translated on weblate";
|
||||||
|
String hash = weblateHash(text, "");
|
||||||
|
try {
|
||||||
|
Document wlDoc = Jsoup.connect(getWeblateLabelURI(text)).get();
|
||||||
|
Element textArea = wlDoc.getElementById("id_"+hash+"_0");
|
||||||
|
if (textArea != null) {
|
||||||
|
String trans = textArea.text();
|
||||||
|
if (trans != null) {
|
||||||
|
unit.translatedText = trans.trim();
|
||||||
|
if (unit.translatedText.isEmpty()) {
|
||||||
|
unit.translatedText = "Not yet translated";
|
||||||
|
unit.status = Status.notTranslated;
|
||||||
|
} else {
|
||||||
|
unit.status = Status.done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Element fuzzyBox = wlDoc.getElementById("id_"+hash+"_fuzzy");
|
||||||
|
if (fuzzyBox != null && fuzzyBox.hasAttr("checked")) {
|
||||||
|
if ("checked".equals(fuzzyBox.attr("checked"))) {
|
||||||
|
unit.status = Status.fuzzy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Elements dangerZone = wlDoc.getElementsByAttributeValue("class", "panel panel-danger");
|
||||||
|
if (dangerZone != null && !dangerZone.isEmpty()) {
|
||||||
|
unit.status = Status.warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user