mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 17:22:09 +10:00
multi-language support
This commit is contained in:
@@ -90,7 +90,9 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
public static final String SNAP_TO_NONE = "None";
|
||||
public static final String SNAP_TO_GRID = "Grid";
|
||||
public static final String SNAP_TO_COMPONENTS = "Components";
|
||||
public static final String SNAP_TO_DEFAULT = SNAP_TO_GRID;
|
||||
public static final String SNAP_TO_DEFAULT = SNAP_TO_GRID;
|
||||
|
||||
public static final String LANGUAGE = "language";
|
||||
|
||||
public static final int DND_TOGGLE_STICKY = 0x1;
|
||||
public static final int DND_TOGGLE_SNAP = 0x40000000;
|
||||
@@ -101,7 +103,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
public static final int NOBUTTON = 0;
|
||||
public static final int BUTTON1 = 1;
|
||||
public static final int BUTTON2 = 2;
|
||||
public static final int BUTTON3 = 3;
|
||||
public static final int BUTTON3 = 3;
|
||||
|
||||
/**
|
||||
* Returns size of the canvas that takes project dimensions into account as well as zoom level.
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
* DIYLC 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.
|
||||
*
|
||||
* DIYLC 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 DIYLC. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.diylc.lang;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.appframework.miscutils.ConfigurationManager;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
|
||||
public class TranslateUtil {
|
||||
|
||||
private static final String LANG_DIR = "lang";
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(TranslateUtil.class);
|
||||
|
||||
private static Map<String, String> dict = null;
|
||||
private static List<String> missing;
|
||||
|
||||
public static String translate(String text) {
|
||||
if (text == null || text.length() <= 1)
|
||||
return text;
|
||||
|
||||
try {
|
||||
// don't translate numbers
|
||||
Double.parseDouble(text);
|
||||
return text;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
if (dict != null) {
|
||||
if (dict.containsKey(text.toLowerCase())) {
|
||||
return dict.get(text.toLowerCase());
|
||||
} else {
|
||||
if ("true".equalsIgnoreCase(System.getProperty("org.diylc.storeDict"))) {
|
||||
List<String> missing = getMissing();
|
||||
if (!missing.contains(text)) {
|
||||
missing.add(text);
|
||||
Collections.sort(missing);
|
||||
try (PrintWriter out = new PrintWriter("dict.txt")) {
|
||||
for (String m : missing) {
|
||||
out.println(m);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void configure() {
|
||||
String language = ConfigurationManager.getInstance().readString(IPlugInPort.LANGUAGE, "English");
|
||||
if (language != null)
|
||||
load(language);
|
||||
}
|
||||
|
||||
private static void load(String language) {
|
||||
LOG.info("Loading translation for " + language);
|
||||
dict = new HashMap<String, String>();
|
||||
try {
|
||||
try (Stream<String> stream = Files.lines(
|
||||
Paths.get(LANG_DIR + File.separator + language + ".txt"), StandardCharsets.UTF_8)) {
|
||||
stream.forEach(s -> {
|
||||
if (s.contains("|")) {
|
||||
String[] parts = s.split("\\|");
|
||||
if (parts.length == 2)
|
||||
dict.put(parts[0].toLowerCase().trim(), parts[1].trim());
|
||||
} else {
|
||||
dict.put(s.toLowerCase(), s);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error loading language file", e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error loading language file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> getMissing() {
|
||||
if (missing == null) {
|
||||
missing = new ArrayList<String>();
|
||||
try {
|
||||
try (Stream<String> stream = Files.lines(Paths.get("dict.txt"), StandardCharsets.UTF_8)) {
|
||||
stream.forEach(s -> missing.add(s));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
|
||||
public static List<String> getAvailableLanguages() {
|
||||
try (Stream<Path> walk = Files.walk(Paths.get(LANG_DIR))) {
|
||||
|
||||
return walk.filter(Files::isRegularFile).map(x -> x.toString()).collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error fetching available languages");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,8 @@ import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.annotations.BomPolicy;
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.annotations.KeywordPolicy;
|
||||
import org.diylc.core.annotations.KeywordPolicy;
|
||||
import org.diylc.lang.TranslateUtil;
|
||||
|
||||
/**
|
||||
* Utility class with component processing methods.
|
||||
@@ -173,7 +174,15 @@ public class ComponentProcessor {
|
||||
setterName = setter.getName();
|
||||
} catch (NoSuchMethodException e) {
|
||||
LOG.debug("No matching setter found for \"" + getter.getName() + "\". Skipping...");
|
||||
}
|
||||
}
|
||||
|
||||
TranslateUtil.translate(name); // temporary, just to make sure we catch it in the dict
|
||||
if (getter.getReturnType().isEnum()) {
|
||||
for(Object o : getter.getReturnType().getEnumConstants()) {
|
||||
TranslateUtil.translate(o.toString());
|
||||
}
|
||||
}
|
||||
|
||||
PropertyWrapper property =
|
||||
new PropertyWrapper(name, getter.getReturnType(), getter.getName(), setterName,
|
||||
annotation.defaultable(), validator, annotation.sortOrder());
|
||||
|
||||
@@ -81,6 +81,7 @@ import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.core.annotations.IAutoCreator;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.lang.TranslateUtil;
|
||||
import org.diylc.netlist.Group;
|
||||
import org.diylc.netlist.Netlist;
|
||||
import org.diylc.netlist.NetlistAnalyzer;
|
||||
@@ -102,6 +103,32 @@ import com.thoughtworks.xstream.io.xml.DomDriver;
|
||||
*/
|
||||
public class Presenter implements IPlugInPort {
|
||||
|
||||
private static final String REACHED_BOTTOM =
|
||||
TranslateUtil.translate("Selected component(s) have reached the bottom of their layer. Do you want to force the selection to the back?");
|
||||
private static final String SEND_SELECTION_TO_BACK = TranslateUtil.translate("Send Selection to Back");
|
||||
private static final String SAVE_AS_VARIANT = TranslateUtil.translate("Save as Variant");
|
||||
private static final String VARIANT_EXISTS = TranslateUtil.translate("A variant with that name already exists. Overwrite?");
|
||||
private static final String ROTATE_CHANGE =
|
||||
TranslateUtil.translate("Selection contains components that cannot be rotated. Do you want to exclude them?");
|
||||
private static final String MIRRORING_CHANGE =
|
||||
TranslateUtil.translate("Mirroring operation will change the circuit. Do you want to continue?");
|
||||
private static final String MIRROR_SELECTION = TranslateUtil.translate("Mirror Selection");
|
||||
private static final String ROTATE_SELECTION = TranslateUtil.translate("Rotate Selection");
|
||||
private static final String CANNOT_MIRROR =
|
||||
TranslateUtil.translate("Selection contains components that cannot be mirrored. Do you want to exclude them?");
|
||||
private static final String BRING_SELECTION_TO_FRONT = TranslateUtil.translate("Bring Selection to Front");
|
||||
private static final String REACHED_TOP =
|
||||
TranslateUtil.translate("Selected component(s) have reached the top of their layer. Do you want to force the selection to the top?");
|
||||
private static final String WARNING = TranslateUtil.translate("Warning");
|
||||
private static final String UNSAVED_CHANGES = TranslateUtil.translate("There are unsaved changes. Would you like to save them?");
|
||||
private static final String ERROR_SLOT = TranslateUtil.translate("Could not set component type slot. Check log for details.");
|
||||
private static final String ERROR_SAVE = TranslateUtil.translate("Could not save the project to file. Check the log for details.");
|
||||
private static final String ERROR_CREATE = TranslateUtil.translate("Could not create component. Check log for details.");
|
||||
private static final String ERROR_EDIT = TranslateUtil.translate("Error occured while editing selection. Check the log for details.");
|
||||
private static final String ERROR_NEW = TranslateUtil.translate("Could not create a new file. Check the log for details.");
|
||||
private static final String ERROR = TranslateUtil.translate("Error");
|
||||
private static final String APPLY_ERROR = "Could not apply changes. Check the log for details.";
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(Presenter.class);
|
||||
|
||||
public static VersionNumber CURRENT_VERSION = new VersionNumber(4, 0, 0);
|
||||
@@ -137,7 +164,7 @@ public class Presenter implements IPlugInPort {
|
||||
|
||||
public static final int ICON_SIZE = 32;
|
||||
|
||||
private static final int MAX_RECENT_FILES = 20;
|
||||
private static final int MAX_RECENT_FILES = 20;
|
||||
|
||||
private Project currentProject;
|
||||
private Map<String, List<ComponentType>> componentTypes;
|
||||
@@ -294,7 +321,7 @@ public class Presenter implements IPlugInPort {
|
||||
DrawingCache.Instance.clear();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not create new file", e);
|
||||
view.showMessage("Could not create a new file. Check the log for details.", "Error", IView.ERROR_MESSAGE);
|
||||
view.showMessage(ERROR_NEW, ERROR, IView.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +341,7 @@ public class Presenter implements IPlugInPort {
|
||||
builder.append("<br>");
|
||||
}
|
||||
builder.append("</html");
|
||||
view.showMessage(builder.toString(), "Warning", IView.WARNING_MESSAGE);
|
||||
view.showMessage(builder.toString(), WARNING, IView.WARNING_MESSAGE);
|
||||
}
|
||||
addToRecentFiles(fileName);
|
||||
DrawingCache.Instance.clear();
|
||||
@@ -328,7 +355,7 @@ public class Presenter implements IPlugInPort {
|
||||
errorMessage += "\n";
|
||||
}
|
||||
}
|
||||
view.showMessage(errorMessage, "Error", IView.ERROR_MESSAGE);
|
||||
view.showMessage(errorMessage, ERROR, IView.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +375,7 @@ public class Presenter implements IPlugInPort {
|
||||
public boolean allowFileAction() {
|
||||
if (projectFileManager.isModified()) {
|
||||
int response =
|
||||
view.showConfirmDialog("There are unsaved changes. Would you like to save them?", "Warning",
|
||||
view.showConfirmDialog(UNSAVED_CHANGES, WARNING,
|
||||
IView.YES_NO_CANCEL_OPTION, IView.WARNING_MESSAGE);
|
||||
if (response == IView.YES_OPTION) {
|
||||
if (this.getCurrentFileName() == null) {
|
||||
@@ -377,7 +404,7 @@ public class Presenter implements IPlugInPort {
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Could not save file", ex);
|
||||
if (!isBackup) {
|
||||
view.showMessage("Could not save file " + fileName + ". Check the log for details.", "Error",
|
||||
view.showMessage(ERROR_SAVE, ERROR,
|
||||
IView.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
@@ -417,6 +444,10 @@ public class Presenter implements IPlugInPort {
|
||||
ComponentProcessor.getInstance().extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) clazz);
|
||||
if (componentType == null)
|
||||
continue;
|
||||
|
||||
// just to store in the cache
|
||||
ComponentProcessor.getInstance().extractProperties(clazz);
|
||||
|
||||
List<ComponentType> nestedList;
|
||||
if (componentTypes.containsKey(componentType.getCategory())) {
|
||||
nestedList = componentTypes.get(componentType.getCategory());
|
||||
@@ -628,7 +659,7 @@ public class Presenter implements IPlugInPort {
|
||||
try {
|
||||
instantiationManager.instatiatePointByPoint(scaledPoint, currentProject);
|
||||
} catch (Exception e) {
|
||||
view.showMessage("Could not create component. Check log for details.", "Error", IView.ERROR_MESSAGE);
|
||||
view.showMessage(ERROR_CREATE, ERROR, IView.ERROR_MESSAGE);
|
||||
LOG.error("Could not create component", e);
|
||||
}
|
||||
messageDispatcher.dispatchMessage(EventType.SLOT_CHANGED, componentTypeSlot,
|
||||
@@ -827,7 +858,7 @@ public class Presenter implements IPlugInPort {
|
||||
try {
|
||||
applyPropertiesToSelection(properties);
|
||||
} catch (Exception e1) {
|
||||
view.showMessage("Error occured while editing selection. Check the log for details.", "Error",
|
||||
view.showMessage(ERROR_EDIT, ERROR,
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
LOG.error("Error applying properties", e1);
|
||||
}
|
||||
@@ -1395,8 +1426,8 @@ public class Presenter implements IPlugInPort {
|
||||
}
|
||||
|
||||
if (!canRotate)
|
||||
if (view.showConfirmDialog("Selection contains components that cannot be rotated. Do you want to exclude them?",
|
||||
"Mirror Selection", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) != IView.YES_OPTION)
|
||||
if (view.showConfirmDialog(ROTATE_CHANGE,
|
||||
ROTATE_SELECTION, IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) != IView.YES_OPTION)
|
||||
return;
|
||||
|
||||
for (IDIYComponent<?> component : selectedComponents) {
|
||||
@@ -1482,7 +1513,7 @@ public class Presenter implements IPlugInPort {
|
||||
mirrorComponents(selectedComponents, direction, isSnapToGrid());
|
||||
|
||||
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, currentProject.clone(),
|
||||
"Mirror Selection");
|
||||
MIRROR_SELECTION);
|
||||
messageDispatcher.dispatchMessage(EventType.REPAINT);
|
||||
drawingManager.clearContinuityArea();
|
||||
}
|
||||
@@ -1507,13 +1538,13 @@ public class Presenter implements IPlugInPort {
|
||||
}
|
||||
|
||||
if (!canMirror)
|
||||
if (view.showConfirmDialog("Selection contains components that cannot be mirrored. Do you want to exclude them?",
|
||||
"Mirror Selection", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) != IView.YES_OPTION)
|
||||
if (view.showConfirmDialog(CANNOT_MIRROR,
|
||||
MIRROR_SELECTION, IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) != IView.YES_OPTION)
|
||||
return;
|
||||
|
||||
if (changesCircuit)
|
||||
if (view.showConfirmDialog("Mirroring operation will change the circuit. Do you want to continue?",
|
||||
"Mirror Selection", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) != IView.YES_OPTION)
|
||||
if (view.showConfirmDialog(MIRRORING_CHANGE,
|
||||
MIRROR_SELECTION, IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) != IView.YES_OPTION)
|
||||
return;
|
||||
|
||||
for (IDIYComponent<?> component : components) {
|
||||
@@ -1821,8 +1852,8 @@ public class Presenter implements IPlugInPort {
|
||||
&& (forceConfirmation =
|
||||
this.view
|
||||
.showConfirmDialog(
|
||||
"Selected component(s) have reached the bottom of their layer. Do you want to force the selection to the back?",
|
||||
"Send Selection to Back", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE)) != IView.YES_OPTION)
|
||||
REACHED_BOTTOM,
|
||||
SEND_SELECTION_TO_BACK, IView.YES_NO_OPTION, IView.QUESTION_MESSAGE)) != IView.YES_OPTION)
|
||||
break;
|
||||
}
|
||||
Collections.swap(currentProject.getComponents(), index, index - 1);
|
||||
@@ -1874,8 +1905,8 @@ public class Presenter implements IPlugInPort {
|
||||
&& (forceConfirmation =
|
||||
this.view
|
||||
.showConfirmDialog(
|
||||
"Selected component(s) have reached the top of their layer. Do you want to force the selection to the top?",
|
||||
"Bring Selection to Front", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE)) != IView.YES_OPTION)
|
||||
REACHED_TOP,
|
||||
BRING_SELECTION_TO_FRONT, IView.YES_NO_OPTION, IView.QUESTION_MESSAGE)) != IView.YES_OPTION)
|
||||
break;
|
||||
}
|
||||
Collections.swap(currentProject.getComponents(), index, index + 1);
|
||||
@@ -2291,7 +2322,7 @@ public class Presenter implements IPlugInPort {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not apply selection properties", e);
|
||||
view.showMessage("Could not apply changes to the selection. Check the log for details.", "Error",
|
||||
view.showMessage("Could not apply changes to the selection. Check the log for details.", ERROR,
|
||||
IView.ERROR_MESSAGE);
|
||||
} finally {
|
||||
// Notify the listeners.
|
||||
@@ -2330,7 +2361,7 @@ public class Presenter implements IPlugInPort {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not apply properties", e);
|
||||
view.showMessage("Could not apply changes. Check the log for details.", "Error", IView.ERROR_MESSAGE);
|
||||
view.showMessage(APPLY_ERROR, ERROR, IView.ERROR_MESSAGE);
|
||||
} finally {
|
||||
// Notify the listeners.
|
||||
if (!oldProject.equals(currentProject)) {
|
||||
@@ -2353,7 +2384,7 @@ public class Presenter implements IPlugInPort {
|
||||
updateSelection(newSelection);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not apply editor", e);
|
||||
view.showMessage("Could not apply " + editor.getEditAction() + ". Check the log for details.", "Error", IView.ERROR_MESSAGE);
|
||||
view.showMessage("Could not apply " + editor.getEditAction() + ". Check the log for details.", ERROR, IView.ERROR_MESSAGE);
|
||||
} finally {
|
||||
// Notify the listeners.
|
||||
if (!oldProject.equals(currentProject)) {
|
||||
@@ -2425,7 +2456,7 @@ public class Presenter implements IPlugInPort {
|
||||
instantiationManager.getFirstControlPoint(), forceInstatiate);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Could not set component type slot", e);
|
||||
view.showMessage("Could not set component type slot. Check log for details.", "Error", IView.ERROR_MESSAGE);
|
||||
view.showMessage(ERROR_SLOT, ERROR, IView.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2486,7 +2517,7 @@ public class Presenter implements IPlugInPort {
|
||||
|
||||
if (exists) {
|
||||
int result =
|
||||
view.showConfirmDialog("A variant with that name already exists. Overwrite?", "Save as Variant",
|
||||
view.showConfirmDialog(VARIANT_EXISTS, SAVE_AS_VARIANT,
|
||||
IView.YES_NO_OPTION, IView.WARNING_MESSAGE);
|
||||
if (result != IView.YES_OPTION) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user