diff --git a/.classpath b/.classpath index a680c63..4c9cb38 100644 --- a/.classpath +++ b/.classpath @@ -1,17 +1,18 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/lib/jsoup-1.10.2-sources.jar b/lib/jsoup-1.10.2-sources.jar new file mode 100644 index 0000000..bb3f4d3 Binary files /dev/null and b/lib/jsoup-1.10.2-sources.jar differ diff --git a/lib/jsoup-1.10.2.jar b/lib/jsoup-1.10.2.jar new file mode 100644 index 0000000..75f716b Binary files /dev/null and b/lib/jsoup-1.10.2.jar differ diff --git a/src/com/gpl/rpg/atcontentstudio/ui/Editor.java b/src/com/gpl/rpg/atcontentstudio/ui/Editor.java index 24cc9a7..28f5108 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/Editor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/Editor.java @@ -47,6 +47,7 @@ import javax.swing.event.DocumentListener; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.text.DefaultFormatter; +import javax.swing.text.JTextComponent; import com.gpl.rpg.atcontentstudio.ATContentStudio; 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.Quest; 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.JideBoxLayout; @@ -115,60 +116,66 @@ public abstract class Editor extends JPanel implements ProjectElementListener { return addTextField(pane, label, value, false, nullListener); } - public static JTextField addTranslatableTextField(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) { - final JTextField tfField = addTextField(pane, label, initialValue, editable, listener); - if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) { - 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); - tfField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void removeUpdate(DocumentEvent e) { - translateLinkLabel.setText(getWeblateLabelLink(tfField.getText())); - translateLinkLabel.revalidate(); - translateLinkLabel.repaint(); - } - @Override - public void insertUpdate(DocumentEvent e) { - translateLinkLabel.setText(getWeblateLabelLink(tfField.getText())); - translateLinkLabel.revalidate(); - translateLinkLabel.repaint(); - } - @Override - public void changedUpdate(DocumentEvent e) { - translateLinkLabel.setText(getWeblateLabelLink(tfField.getText())); - 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(tfField.getText()))); - } catch (IOException e1) { - e1.printStackTrace(); - } catch (URISyntaxException e1) { - e1.printStackTrace(); - } + public static void addTranslationPane(JPanel pane, final JTextComponent tfComponent, final String initialValue) {if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) { + JPanel labelPane = new JPanel(); + labelPane.setLayout(new JideBoxLayout(labelPane, JideBoxLayout.LINE_AXIS)); + final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue)); + labelPane.add(translateLinkLabel, JideBoxLayout.FIX); + 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); + tfComponent.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void removeUpdate(DocumentEvent e) { + translateLinkLabel.setText(getWeblateLabelLink(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n")))); + translateLinkLabel.revalidate(); + translateLinkLabel.repaint(); + } + @Override + public void insertUpdate(DocumentEvent e) { + translateLinkLabel.setText(getWeblateLabelLink(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n")))); + translateLinkLabel.revalidate(); + translateLinkLabel.repaint(); + } + @Override + public void changedUpdate(DocumentEvent e) { + translateLinkLabel.setText(getWeblateLabelLink(tfComponent.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(WeblateIntegration.getWeblateLabelURI(tfComponent.getText().replaceAll("\n", Matcher.quoteReplacement("\n"))))); + } catch (IOException e1) { + e1.printStackTrace(); + } catch (URISyntaxException e1) { + e1.printStackTrace(); } } - }); - } + } + }); + } + } + + 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; } public static String getWeblateLabelLink(String text) { - return "Translate on weblate"; - } - - 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, ""); + return "Translate on weblate"; } 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) { final JTextArea tfArea = addTextArea(pane, label, initialValue, editable, listener); - if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) { - 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(); - } - } - } - }); - } + addTranslationPane(pane, tfArea, initialValue); return tfArea; } diff --git a/src/com/gpl/rpg/atcontentstudio/utils/HashUtils.java b/src/com/gpl/rpg/atcontentstudio/utils/HashUtils.java index e044803..7d89d84 100644 --- a/src/com/gpl/rpg/atcontentstudio/utils/HashUtils.java +++ b/src/com/gpl/rpg/atcontentstudio/utils/HashUtils.java @@ -1,6 +1,5 @@ package com.gpl.rpg.atcontentstudio.utils; -import java.io.UnsupportedEncodingException; import java.util.LinkedHashMap; import java.util.Map; @@ -9,38 +8,9 @@ import com.zackehh.siphash.SipHashResult; public class HashUtils { - private static final String WEBLATE_SIPASH_KEY = "Weblate Sip Hash"; - private static final Map HASHER_CACHE = new LinkedHashMap(); - 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 siphash(WEBLATE_SIPASH_KEY, data); - } - - private static String siphash(String key, byte[] data) { + static String siphash(String key, byte[] data) { SipHash hasher = HASHER_CACHE.get(key); if (hasher == null) { hasher= new SipHash("Weblate Sip Hash".getBytes()); diff --git a/src/com/gpl/rpg/atcontentstudio/utils/WeblateIntegration.java b/src/com/gpl/rpg/atcontentstudio/utils/WeblateIntegration.java new file mode 100644 index 0000000..faeef11 --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/utils/WeblateIntegration.java @@ -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; + } + + +}