mirror of
https://github.com/OMGeeky/ATCS.git
synced 2025-12-26 23:57:25 +01:00
Added link to Weblate from translatable strings once the translator mode
is activated in the workspace settings. This required the addition of a new lib (in source form) for a SipHash implementation.
This commit is contained in:
@@ -19,6 +19,8 @@ import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||
import com.gpl.rpg.atcontentstudio.ui.StudioFrame;
|
||||
import com.gpl.rpg.atcontentstudio.ui.WorkerDialog;
|
||||
import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector;
|
||||
import com.gpl.rpg.atcontentstudio.utils.HashUtils;
|
||||
import com.zackehh.siphash.SipHash;
|
||||
|
||||
|
||||
public class ATContentStudio {
|
||||
|
||||
@@ -11,6 +11,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
@@ -39,8 +41,11 @@ public class WorkspaceSettings {
|
||||
public static Boolean DEFAULT_USE_SYS_IMG_EDITOR = false;
|
||||
public Setting<Boolean> useSystemDefaultImageEditor = new PrimitiveSetting<Boolean>("useSystemDefaultImageEditor", DEFAULT_USE_SYS_IMG_EDITOR);
|
||||
public static String DEFAULT_IMG_EDITOR_COMMAND = "gimp";
|
||||
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 Setting<String> imageEditorCommand = new PrimitiveSetting<String>("imageEditorCommand", DEFAULT_IMG_EDITOR_COMMAND);
|
||||
|
||||
public Setting<String> translatorLanguage = new NullDefaultPrimitiveSetting<String>("translatorLanguage");
|
||||
|
||||
public List<Setting<? extends Object>> settings = new ArrayList<Setting<? extends Object>>();
|
||||
|
||||
public WorkspaceSettings(Workspace parent) {
|
||||
@@ -50,6 +55,7 @@ public class WorkspaceSettings {
|
||||
settings.add(useSystemDefaultImageViewer);
|
||||
settings.add(useSystemDefaultImageEditor);
|
||||
settings.add(imageEditorCommand);
|
||||
settings.add(translatorLanguage);
|
||||
file = new File(parent.baseFolder, FILENAME);
|
||||
if (file.exists()) {
|
||||
load(file);
|
||||
@@ -174,6 +180,18 @@ public class WorkspaceSettings {
|
||||
|
||||
}
|
||||
|
||||
public class NullDefaultPrimitiveSetting<X extends Object> extends PrimitiveSetting<X> {
|
||||
|
||||
public NullDefaultPrimitiveSetting(String id) {
|
||||
super(id, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToJson(Map json) {
|
||||
if (value != null) json.put(id, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class ListSetting<X extends Object> extends Setting<List<X>> {
|
||||
|
||||
public ListSetting(String id, List<X> defaultValue) {
|
||||
|
||||
@@ -72,6 +72,9 @@ public class AboutEditor extends Editor {
|
||||
"<a href=\"http://www.beanshell.org/\">BeanShell</a> by Pat Niemeyer.<br/>" +
|
||||
"License: <a href=\"http://www.beanshell.org/license.html\">LGPL v3</a><br/>" +
|
||||
"<br/>" +
|
||||
"A slightly modified version of <a href=\"https://github.com/zackehh/siphash-java\">SipHash for Java</a> by Isaac Whitfield.<br/>" +
|
||||
"License: <a href=\"https://github.com/zackehh/siphash-java/blob/master/LICENSE\">MIT License</a><br/>" +
|
||||
"<br/>" +
|
||||
"See the tabs below to find the full license text for each of these.<br/>" +
|
||||
"<br/>" +
|
||||
"The Windows installer was created with:<br/>" +
|
||||
@@ -121,6 +124,7 @@ public class AboutEditor extends Editor {
|
||||
editorTabsHolder.add("libtiled-java License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.libtiled.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
editorTabsHolder.add("prefuse License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/license-prefuse.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
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("ATCS License", getInfoPane(new Scanner(ATContentStudio.class.getResourceAsStream("/LICENSE.GPLv3.txt"), "UTF-8").useDelimiter("\\A").next(), "text/text"));
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.gpl.rpg.atcontentstudio.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
@@ -10,6 +12,9 @@ import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -48,6 +53,7 @@ import com.gpl.rpg.atcontentstudio.Notification;
|
||||
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
|
||||
import com.gpl.rpg.atcontentstudio.model.Project;
|
||||
import com.gpl.rpg.atcontentstudio.model.ProjectElementListener;
|
||||
import com.gpl.rpg.atcontentstudio.model.Workspace;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
|
||||
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
|
||||
@@ -57,6 +63,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.jidesoft.swing.ComboBoxSearchable;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
|
||||
@@ -108,6 +115,58 @@ 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) {
|
||||
final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue));
|
||||
pane.add(translateLinkLabel, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return tfField;
|
||||
}
|
||||
|
||||
public static String getWeblateLabelLink(String text) {
|
||||
return "<html><a href=\""+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) {
|
||||
JPanel tfPane = new JPanel();
|
||||
tfPane.setLayout(new JideBoxLayout(tfPane, JideBoxLayout.LINE_AXIS, 6));
|
||||
@@ -151,6 +210,51 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
|
||||
return tfField;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue));
|
||||
pane.add(translateLinkLabel, 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;
|
||||
}
|
||||
|
||||
public static JTextArea addTextArea(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
|
||||
String text= initialValue == null ? "" : initialValue.replaceAll("\\n", "\n");
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
@@ -28,6 +31,9 @@ public class WorkspaceSettingsEditor extends JDialog {
|
||||
JRadioButton useSystemDefaultImageViewerButton, useSystemDefaultImageEditorButton, useCustomImageEditorButton;
|
||||
JTextField imageEditorCommandField;
|
||||
|
||||
JCheckBox translatorModeBox;
|
||||
JComboBox<String> translatorLanguagesBox;
|
||||
|
||||
|
||||
|
||||
public WorkspaceSettingsEditor(WorkspaceSettings settings) {
|
||||
@@ -46,6 +52,7 @@ public class WorkspaceSettingsEditor extends JDialog {
|
||||
|
||||
|
||||
pane.add(getExternalToolsPane(), JideBoxLayout.FIX);
|
||||
pane.add(getTranslatorModePane(), JideBoxLayout.FIX);
|
||||
pane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
|
||||
buttonPane.add(new JPanel(), JideBoxLayout.VARY);
|
||||
@@ -147,6 +154,32 @@ public class WorkspaceSettingsEditor extends JDialog {
|
||||
return pane;
|
||||
}
|
||||
|
||||
public JPanel getTranslatorModePane() {
|
||||
CollapsiblePanel pane = new CollapsiblePanel("Translator options");
|
||||
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS));
|
||||
|
||||
translatorModeBox = new JCheckBox("Activate translator mode");
|
||||
pane.add(translatorModeBox, JideBoxLayout.FIX);
|
||||
|
||||
JPanel langPane = new JPanel();
|
||||
langPane.setLayout(new JideBoxLayout(langPane, JideBoxLayout.LINE_AXIS));
|
||||
langPane.add(new JLabel("Language code: "), JideBoxLayout.FIX);
|
||||
translatorLanguagesBox = new JComboBox<String>(WorkspaceSettings.LANGUAGE_LIST);
|
||||
langPane.add(translatorLanguagesBox);
|
||||
pane.add(langPane, JideBoxLayout.FIX);
|
||||
|
||||
translatorModeBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
translatorLanguagesBox.setEnabled(translatorModeBox.isSelected());
|
||||
}
|
||||
});
|
||||
|
||||
pane.add(new JLabel("If your language isn't here, complain on the forums at https://andorstrail.com/"), JideBoxLayout.FIX);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
public void loadFromModel() {
|
||||
//Tiled
|
||||
useSystemDefaultMapEditorButton.setSelected(settings.useSystemDefaultMapEditor.getCurrentValue());
|
||||
@@ -157,6 +190,14 @@ public class WorkspaceSettingsEditor extends JDialog {
|
||||
useSystemDefaultImageEditorButton.setSelected(settings.useSystemDefaultImageEditor.getCurrentValue());
|
||||
useCustomImageEditorButton.setSelected(!(settings.useSystemDefaultImageViewer.getCurrentValue() || settings.useSystemDefaultImageEditor.getCurrentValue()));
|
||||
imageEditorCommandField.setText(settings.imageEditorCommand.getCurrentValue());
|
||||
//Translator
|
||||
if (settings.translatorLanguage.getCurrentValue() != null) {
|
||||
translatorModeBox.setSelected(true);
|
||||
translatorLanguagesBox.setSelectedItem(settings.translatorLanguage.getCurrentValue());
|
||||
} else {
|
||||
translatorModeBox.setSelected(false);
|
||||
translatorLanguagesBox.setSelectedItem(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void pushToModel() {
|
||||
@@ -167,7 +208,12 @@ public class WorkspaceSettingsEditor extends JDialog {
|
||||
settings.useSystemDefaultImageViewer.setCurrentValue(useSystemDefaultImageViewerButton.isSelected());
|
||||
settings.useSystemDefaultImageEditor.setCurrentValue(useSystemDefaultImageEditorButton.isSelected());
|
||||
settings.imageEditorCommand.setCurrentValue(imageEditorCommandField.getText());
|
||||
|
||||
//Translator
|
||||
if (translatorModeBox.isSelected()) {
|
||||
settings.translatorLanguage.setCurrentValue((String)translatorLanguagesBox.getSelectedItem());
|
||||
} else {
|
||||
settings.translatorLanguage.resetDefault();
|
||||
}
|
||||
settings.save();
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public class ActorConditionEditor extends JSONElementEditor {
|
||||
acIcon = createButtonPane(pane, ac.getProject(), ac, ActorCondition.class, ac.getImage(), Spritesheet.Category.actorcondition, listener);
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", ac.id, ac.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", ac.display_name, ac.writable, listener);
|
||||
nameField = addTranslatableTextField(pane, "Display name: ", ac.display_name, ac.writable, listener);
|
||||
categoryBox = addEnumValueBox(pane, "Category: ", ActorCondition.ACCategory.values(), ac.category, ac.writable, listener);
|
||||
positiveBox = addIntegerBasedCheckBox(pane, "Positive", ac.positive, ac.writable, listener);
|
||||
stackingBox = addIntegerBasedCheckBox(pane, "Stacking", ac.stacking, ac.writable, listener);
|
||||
|
||||
@@ -165,7 +165,7 @@ public class DialogueEditor extends JSONElementEditor {
|
||||
createButtonPane(pane, dialogue.getProject(), dialogue, Dialogue.class, dialogue.getImage(), null, listener);
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", dialogue.id, dialogue.writable, listener);
|
||||
messageField = addTextArea(pane, "Message: ", dialogue.message, dialogue.writable, listener);
|
||||
messageField = addTranslatableTextArea(pane, "Message: ", dialogue.message, dialogue.writable, listener);
|
||||
switchToNpcBox = addNPCBox(pane, dialogue.getProject(), "Switch active NPC to: ", dialogue.switch_to_npc, dialogue.writable, listener);
|
||||
|
||||
CollapsiblePanel rewards = new CollapsiblePanel("Reaching this phrase gives the following rewards: ");
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ItemCategoryEditor extends JSONElementEditor {
|
||||
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", ic.id, ic.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", ic.name, ic.writable, listener);
|
||||
nameField = addTranslatableTextField(pane, "Display name: ", ic.name, ic.writable, listener);
|
||||
typeBox = addEnumValueBox(pane, "Action type: ", ItemCategory.ActionType.values(), ic.action_type, ic.writable, listener);
|
||||
slotBox = addEnumValueBox(pane, "Inventory slot: ", ItemCategory.InventorySlot.values(), ic.slot, ic.writable, listener);
|
||||
sizeBox = addEnumValueBox(pane, "Item size: ", ItemCategory.Size.values(), ic.size, ic.writable, listener);
|
||||
|
||||
@@ -149,8 +149,8 @@ public class ItemEditor extends JSONElementEditor {
|
||||
itemIcon = createButtonPane(pane, item.getProject(), item, Item.class, item.getImage(), Spritesheet.Category.item, listener);
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", item.id, item.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", item.name, item.writable, listener);
|
||||
descriptionField = addTextField(pane, "Description: ", item.description, item.writable, listener);
|
||||
nameField = addTranslatableTextField(pane, "Display name: ", item.name, item.writable, listener);
|
||||
descriptionField = addTranslatableTextField(pane, "Description: ", item.description, item.writable, listener);
|
||||
typeBox = addEnumValueBox(pane, "Type: ", Item.DisplayType.values(), item.display_type, item.writable, listener);
|
||||
manualPriceBox = addIntegerBasedCheckBox(pane, "Has manual price", item.has_manual_price, item.writable, listener);
|
||||
baseManualPrice = item.base_market_cost;
|
||||
|
||||
@@ -171,7 +171,7 @@ public class NPCEditor extends JSONElementEditor {
|
||||
npcIcon = createButtonPane(pane, npc.getProject(), npc, NPC.class, npc.getImage(), Spritesheet.Category.monster, listener);
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", npc.id, npc.writable, listener);
|
||||
nameField = addTextField(pane, "Display name: ", npc.name, npc.writable, listener);
|
||||
nameField = addTranslatableTextField(pane, "Display name: ", npc.name, npc.writable, listener);
|
||||
spawnGroupField = addTextField(pane, "Spawn group ID: ", npc.spawngroup_id, npc.writable, listener);
|
||||
experienceField = addIntegerField(pane, "Experience reward: ", npc.getMonsterExperience(), false, false, listener);
|
||||
dialogueBox = addDialogueBox(pane, npc.getProject(), "Initial phrase: ", npc.dialogue, npc.writable, listener);
|
||||
|
||||
@@ -69,7 +69,7 @@ public class QuestEditor extends JSONElementEditor {
|
||||
|
||||
|
||||
idField = addTextField(pane, "Internal ID: ", quest.id, quest.writable, listener);
|
||||
nameField = addTextField(pane, "Quest Name: ", quest.name, quest.writable, listener);
|
||||
nameField = addTranslatableTextField(pane, "Quest Name: ", quest.name, quest.writable, listener);
|
||||
visibleBox = addIntegerBasedCheckBox(pane, "Visible in quest log", quest.visible_in_log, quest.writable, listener);
|
||||
|
||||
JPanel stagesPane = new JPanel();
|
||||
|
||||
60
src/com/gpl/rpg/atcontentstudio/utils/HashUtils.java
Normal file
60
src/com/gpl/rpg/atcontentstudio/utils/HashUtils.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.gpl.rpg.atcontentstudio.utils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.zackehh.siphash.SipHash;
|
||||
import com.zackehh.siphash.SipHashResult;
|
||||
|
||||
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>();
|
||||
|
||||
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) {
|
||||
SipHash hasher = HASHER_CACHE.get(key);
|
||||
if (hasher == null) {
|
||||
hasher= new SipHash("Weblate Sip Hash".getBytes());
|
||||
HASHER_CACHE.put(key, hasher);
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
SipHashResult result = hasher.hash(data);
|
||||
return result.getHex();
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user