rewrite i18n key handling
- Translation keys are now based on KeyPath type which is simply a string list - Handling delimiter character within a section layer is now easier - Only the presentation layer has to deal with displaying the correct concatenated key
This commit is contained in:
parent
44310d5459
commit
c0e385000a
@ -5,12 +5,14 @@
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### BREAKING CHANGES
|
### BREAKING CHANGES
|
||||||
- Translation file pattern matcher needs to be updated to <kbd>\*.*</kbd> or equivalent wildcard rule
|
- Translation file pattern matcher needs to be updated to <kbd>\*.*</kbd> or equivalent wildcard rule
|
||||||
|
- I18n key nesting will now escape every delimiter within a section layer (can be inverted via option)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Full keyboard shortcut support inside tool-window
|
- Full keyboard shortcut support inside tool-window
|
||||||
- Support for dots within key nodes in YAML files
|
- Support for dots within key nodes in YAML files
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Key completion inside editor suggests all keys without any logic
|
||||||
- Translation file pattern uses wildcard matcher instead of regex
|
- Translation file pattern uses wildcard matcher instead of regex
|
||||||
- Improve exception handling on IO operations
|
- Improve exception handling on IO operations
|
||||||
- Update Qodana to latest version
|
- Update Qodana to latest version
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package de.marhali.easyi18n;
|
package de.marhali.easyi18n;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.bus.BusListener;
|
import de.marhali.easyi18n.model.bus.BusListener;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ public class DataBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFocusKey(@Nullable String key) {
|
public void onFocusKey(@Nullable KeyPath key) {
|
||||||
listener.forEach(li -> li.onFocusKey(key));
|
listener.forEach(li -> li.onFocusKey(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class DataStore {
|
|||||||
|
|
||||||
protected DataStore(@NotNull Project project) {
|
protected DataStore(@NotNull Project project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
this.data = new TranslationData(true, true); // Initialize with hard-coded configuration
|
this.data = new TranslationData(true); // Initialize with hard-coded configuration
|
||||||
this.changeListener = new FileChangeListener(project);
|
this.changeListener = new FileChangeListener(project);
|
||||||
|
|
||||||
VirtualFileManager.getInstance().addAsyncFileListener(
|
VirtualFileManager.getInstance().addAsyncFileListener(
|
||||||
@ -63,7 +63,7 @@ public class DataStore {
|
|||||||
String localesPath = state.getLocalesPath();
|
String localesPath = state.getLocalesPath();
|
||||||
|
|
||||||
if(localesPath == null || localesPath.isEmpty()) { // Populate empty instance
|
if(localesPath == null || localesPath.isEmpty()) { // Populate empty instance
|
||||||
this.data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
this.data = new TranslationData(state.isSortKeys());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ public class DataStore {
|
|||||||
|
|
||||||
strategy.read(this.project, localesPath, state, (data) -> {
|
strategy.read(this.project, localesPath, state, (data) -> {
|
||||||
this.data = data == null
|
this.data = data == null
|
||||||
? new TranslationData(state.isSortKeys(), state.isNestedKeys())
|
? new TranslationData(state.isSortKeys())
|
||||||
: data;
|
: data;
|
||||||
|
|
||||||
successResult.accept(data != null);
|
successResult.accept(data != null);
|
||||||
|
@ -3,15 +3,20 @@ package de.marhali.easyi18n.action;
|
|||||||
import com.intellij.icons.AllIcons;
|
import com.intellij.icons.AllIcons;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.ui.content.Content;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.KeyPathConverter;
|
||||||
import de.marhali.easyi18n.service.WindowManager;
|
import de.marhali.easyi18n.service.WindowManager;
|
||||||
import de.marhali.easyi18n.dialog.AddDialog;
|
import de.marhali.easyi18n.dialog.AddDialog;
|
||||||
import de.marhali.easyi18n.util.PathUtil;
|
|
||||||
import de.marhali.easyi18n.util.TreeUtil;
|
import de.marhali.easyi18n.util.TreeUtil;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,32 +32,33 @@ public class AddAction extends AnAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
new AddDialog(e.getProject(), detectPreKey()).showAndHandle();
|
new AddDialog(Objects.requireNonNull(e.getProject()), detectPreKey(e.getProject())).showAndHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String detectPreKey() {
|
private @Nullable KeyPath detectPreKey(@NotNull Project project) {
|
||||||
WindowManager manager = WindowManager.getInstance();
|
KeyPathConverter converter = new KeyPathConverter(project);
|
||||||
|
WindowManager window = WindowManager.getInstance();
|
||||||
|
Content manager = window.getToolWindow().getContentManager().getSelectedContent();
|
||||||
|
|
||||||
if(manager == null) {
|
if(manager == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(manager.getToolWindow().getContentManager().getSelectedContent()
|
if(manager.getDisplayName().equals(
|
||||||
.getDisplayName().equals(ResourceBundle.getBundle("messages").getString("view.tree.title"))) {
|
ResourceBundle.getBundle("messages").getString("view.tree.title"))) { // Tree View
|
||||||
|
|
||||||
TreePath path = manager.getTreeView().getTree().getSelectionPath();
|
TreePath path = window.getTreeView().getTree().getSelectionPath();
|
||||||
|
|
||||||
if(path != null) {
|
if(path != null) {
|
||||||
return TreeUtil.getFullPath(path) + PathUtil.DELIMITER;
|
return TreeUtil.getFullPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // Table View
|
} else { // Table View
|
||||||
|
int row = window.getTableView().getTable().getSelectedRow();
|
||||||
int row = manager.getTableView().getTable().getSelectedRow();
|
|
||||||
|
|
||||||
if(row >= 0) {
|
if(row >= 0) {
|
||||||
String fullPath = String.valueOf(manager.getTableView().getTable().getValueAt(row, 0));
|
String path = String.valueOf(window.getTableView().getTable().getValueAt(row, 0));
|
||||||
return fullPath + ".";
|
return converter.split(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,10 @@ import com.intellij.ui.components.JBScrollPane;
|
|||||||
import com.intellij.ui.components.JBTextField;
|
import com.intellij.ui.components.JBTextField;
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
import de.marhali.easyi18n.model.*;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
import de.marhali.easyi18n.model.TranslationCreate;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EtchedBorder;
|
import javax.swing.border.EtchedBorder;
|
||||||
@ -25,19 +26,23 @@ import java.util.ResourceBundle;
|
|||||||
*/
|
*/
|
||||||
public class AddDialog {
|
public class AddDialog {
|
||||||
|
|
||||||
private final Project project;
|
private final @NotNull Project project;
|
||||||
private String preKey;
|
private final @NotNull KeyPathConverter converter;
|
||||||
|
|
||||||
|
private @NotNull KeyPath preKey;
|
||||||
|
|
||||||
private JBTextField keyTextField;
|
private JBTextField keyTextField;
|
||||||
private Map<String, JBTextField> valueTextFields;
|
private Map<String, JBTextField> valueTextFields;
|
||||||
|
|
||||||
public AddDialog(Project project, String preKey) {
|
public AddDialog(@NotNull Project project, @Nullable KeyPath preKey) {
|
||||||
this(project);
|
this(project);
|
||||||
this.preKey = preKey;
|
this.preKey = preKey == null ? new KeyPath() : preKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddDialog(Project project) {
|
public AddDialog(@NotNull Project project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
|
this.converter = new KeyPathConverter(project);
|
||||||
|
this.preKey = new KeyPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showAndHandle() {
|
public void showAndHandle() {
|
||||||
@ -57,7 +62,8 @@ public class AddDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
TranslationCreate creation = new TranslationCreate(new KeyedTranslation(keyTextField.getText(), translation));
|
KeyedTranslation keyedTranslation = new KeyedTranslation(converter.split(keyTextField.getText()), translation);
|
||||||
|
TranslationCreate creation = new TranslationCreate(keyedTranslation);
|
||||||
InstanceManager.get(project).processUpdate(creation);
|
InstanceManager.get(project).processUpdate(creation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,13 +73,17 @@ public class AddDialog {
|
|||||||
|
|
||||||
JPanel keyPanel = new JPanel(new GridLayout(0, 1, 2, 2));
|
JPanel keyPanel = new JPanel(new GridLayout(0, 1, 2, 2));
|
||||||
JBLabel keyLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("translation.key"));
|
JBLabel keyLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("translation.key"));
|
||||||
keyTextField = new JBTextField(this.preKey);
|
keyTextField = new JBTextField(this.converter.concat(this.preKey));
|
||||||
keyLabel.setLabelFor(keyTextField);
|
keyLabel.setLabelFor(keyTextField);
|
||||||
keyPanel.add(keyLabel);
|
keyPanel.add(keyLabel);
|
||||||
keyPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
|
keyPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
|
||||||
keyPanel.add(keyTextField);
|
keyPanel.add(keyTextField);
|
||||||
rootPanel.add(keyPanel);
|
rootPanel.add(keyPanel);
|
||||||
|
|
||||||
|
if(!this.preKey.isEmpty()) { // Add delimiter if pre key is defined
|
||||||
|
keyTextField.setText(keyTextField.getText() + KeyPath.DELIMITER);
|
||||||
|
}
|
||||||
|
|
||||||
JPanel valuePanel = new JPanel(new GridLayout(0, 1, 2, 2));
|
JPanel valuePanel = new JPanel(new GridLayout(0, 1, 2, 2));
|
||||||
valueTextFields = new HashMap<>();
|
valueTextFields = new HashMap<>();
|
||||||
|
|
||||||
|
@ -6,12 +6,10 @@ import com.intellij.openapi.ui.DialogWrapper;
|
|||||||
import com.intellij.ui.components.JBLabel;
|
import com.intellij.ui.components.JBLabel;
|
||||||
import com.intellij.ui.components.JBScrollPane;
|
import com.intellij.ui.components.JBScrollPane;
|
||||||
import com.intellij.ui.components.JBTextField;
|
import com.intellij.ui.components.JBTextField;
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
import de.marhali.easyi18n.model.*;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
import de.marhali.easyi18n.model.TranslationDelete;
|
|
||||||
import de.marhali.easyi18n.dialog.descriptor.DeleteActionDescriptor;
|
import de.marhali.easyi18n.dialog.descriptor.DeleteActionDescriptor;
|
||||||
import de.marhali.easyi18n.model.TranslationUpdate;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EtchedBorder;
|
import javax.swing.border.EtchedBorder;
|
||||||
@ -27,6 +25,8 @@ import java.util.ResourceBundle;
|
|||||||
public class EditDialog {
|
public class EditDialog {
|
||||||
|
|
||||||
private final Project project;
|
private final Project project;
|
||||||
|
private final KeyPathConverter converter;
|
||||||
|
|
||||||
private final KeyedTranslation origin;
|
private final KeyedTranslation origin;
|
||||||
|
|
||||||
private JBTextField keyTextField;
|
private JBTextField keyTextField;
|
||||||
@ -34,6 +34,7 @@ public class EditDialog {
|
|||||||
|
|
||||||
public EditDialog(Project project, KeyedTranslation origin) {
|
public EditDialog(Project project, KeyedTranslation origin) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
|
this.converter = new KeyPathConverter(project);
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ public class EditDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return new KeyedTranslation(keyTextField.getText(), translation);
|
return new KeyedTranslation(converter.split(keyTextField.getText()), translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DialogBuilder prepare() {
|
private DialogBuilder prepare() {
|
||||||
@ -65,7 +66,7 @@ public class EditDialog {
|
|||||||
|
|
||||||
JPanel keyPanel = new JPanel(new GridLayout(0, 1, 2,2));
|
JPanel keyPanel = new JPanel(new GridLayout(0, 1, 2,2));
|
||||||
JBLabel keyLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("translation.key"));
|
JBLabel keyLabel = new JBLabel(ResourceBundle.getBundle("messages").getString("translation.key"));
|
||||||
keyTextField = new JBTextField(this.origin.getKey());
|
keyTextField = new JBTextField(this.converter.concat(this.origin.getKey()));
|
||||||
keyLabel.setLabelFor(keyTextField);
|
keyLabel.setLabelFor(keyTextField);
|
||||||
keyPanel.add(keyLabel);
|
keyPanel.add(keyLabel);
|
||||||
keyPanel.add(keyTextField);
|
keyPanel.add(keyTextField);
|
||||||
|
@ -51,9 +51,8 @@ public class SettingsDialog {
|
|||||||
|
|
||||||
// Reload instance
|
// Reload instance
|
||||||
InstanceManager manager = InstanceManager.get(project);
|
InstanceManager manager = InstanceManager.get(project);
|
||||||
manager.store().loadFromPersistenceLayer((success) -> {
|
manager.store().loadFromPersistenceLayer((success) ->
|
||||||
manager.bus().propagate().onUpdateData(manager.store().getData());
|
manager.bus().propagate().onUpdateData(manager.store().getData()));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@ import com.intellij.lang.annotation.HighlightSeverity;
|
|||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.KeyPathConverter;
|
||||||
|
import de.marhali.easyi18n.model.SettingsState;
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
import de.marhali.easyi18n.model.TranslationNode;
|
||||||
import de.marhali.easyi18n.service.SettingsService;
|
import de.marhali.easyi18n.service.SettingsService;
|
||||||
|
|
||||||
@ -28,18 +31,21 @@ public class KeyAnnotator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String previewLocale = SettingsService.getInstance(project).getState().getPreviewLocale();
|
SettingsState state = SettingsService.getInstance(project).getState();
|
||||||
String pathPrefix = SettingsService.getInstance(project).getState().getPathPrefix();
|
String pathPrefix = state.getPathPrefix();
|
||||||
|
String previewLocale = state.getPreviewLocale();
|
||||||
|
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(project);
|
||||||
|
|
||||||
String searchKey = key.length() >= pathPrefix.length()
|
String searchKey = key.length() >= pathPrefix.length()
|
||||||
? key.substring(pathPrefix.length())
|
? key.substring(pathPrefix.length())
|
||||||
: key;
|
: key;
|
||||||
|
|
||||||
if(searchKey.startsWith(".")) {
|
if(searchKey.startsWith(KeyPath.DELIMITER)) {
|
||||||
searchKey = searchKey.substring(1);
|
searchKey = searchKey.substring(KeyPath.DELIMITER.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationNode node = InstanceManager.get(project).store().getData().getNode(searchKey);
|
TranslationNode node = InstanceManager.get(project).store().getData().getNode(converter.split(searchKey));
|
||||||
|
|
||||||
if(node == null) { // Unknown translation. Just ignore it
|
if(node == null) { // Unknown translation. Just ignore it
|
||||||
return;
|
return;
|
||||||
|
@ -5,11 +5,13 @@ import com.intellij.codeInsight.lookup.*;
|
|||||||
import com.intellij.icons.AllIcons;
|
import com.intellij.icons.AllIcons;
|
||||||
import com.intellij.openapi.project.*;
|
import com.intellij.openapi.project.*;
|
||||||
import com.intellij.util.*;
|
import com.intellij.util.*;
|
||||||
|
|
||||||
import de.marhali.easyi18n.DataStore;
|
import de.marhali.easyi18n.DataStore;
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
import de.marhali.easyi18n.model.Translation;
|
||||||
import de.marhali.easyi18n.service.*;
|
import de.marhali.easyi18n.service.*;
|
||||||
import de.marhali.easyi18n.util.PathUtil;
|
|
||||||
import org.jetbrains.annotations.*;
|
import org.jetbrains.annotations.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -32,58 +34,29 @@ public class KeyCompletionProvider extends CompletionProvider<CompletionParamete
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataStore store = InstanceManager.get(project).store();
|
DataStore store = InstanceManager.get(project).store();
|
||||||
PathUtil pathUtil = new PathUtil(project);
|
|
||||||
String previewLocale = SettingsService.getInstance(project).getState().getPreviewLocale();
|
String previewLocale = SettingsService.getInstance(project).getState().getPreviewLocale();
|
||||||
String pathPrefix = SettingsService.getInstance(project).getState().getPathPrefix();
|
String pathPrefix = SettingsService.getInstance(project).getState().getPathPrefix();
|
||||||
|
|
||||||
String path = result.getPrefixMatcher().getPrefix();
|
if(pathPrefix.length() > 0 && !pathPrefix.endsWith(KeyPath.DELIMITER)) {
|
||||||
|
pathPrefix += KeyPath.DELIMITER;
|
||||||
if(path.startsWith(pathPrefix)) {
|
|
||||||
path = path.substring(pathPrefix.length());
|
|
||||||
|
|
||||||
if(path.startsWith(".")) { // Remove leading dot
|
|
||||||
path = path.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
path = ""; // Show suggestions for root view
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pathPrefix.length() > 0 && !pathPrefix.endsWith(".")) {
|
Set<KeyPath> fullKeys = store.getData().getFullKeys();
|
||||||
pathPrefix += ".";
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> fullKeys = store.getData().getFullKeys();
|
for(KeyPath currentKey : fullKeys) {
|
||||||
|
result.addElement(createElement(
|
||||||
int sections = path.split("\\.").length;
|
pathPrefix,
|
||||||
int maxSectionForwardLookup = 5;
|
currentKey,
|
||||||
|
previewLocale,
|
||||||
for(String key : fullKeys) {
|
Objects.requireNonNull(store.getData().getTranslation(currentKey))
|
||||||
// Path matches
|
));
|
||||||
if(key.startsWith(path)) {
|
|
||||||
String[] keySections = key.split("\\.");
|
|
||||||
|
|
||||||
if(keySections.length > sections + maxSectionForwardLookup) { // Key is too deep nested
|
|
||||||
String shrinkKey = pathUtil.concat(Arrays.asList(
|
|
||||||
Arrays.copyOf(keySections, sections + maxSectionForwardLookup)
|
|
||||||
));
|
|
||||||
|
|
||||||
result.addElement(LookupElementBuilder.create(pathPrefix + shrinkKey)
|
|
||||||
.appendTailText(" I18n([])", true));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Translation translation = store.getData().getTranslation(key);
|
|
||||||
|
|
||||||
if(translation != null) {
|
|
||||||
String content = translation.get(previewLocale);
|
|
||||||
|
|
||||||
result.addElement(LookupElementBuilder.create(pathPrefix + key)
|
|
||||||
.withIcon(AllIcons.Actions.PreserveCaseHover)
|
|
||||||
.appendTailText(" I18n(" + previewLocale + ": " + content + ")", true)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LookupElement createElement(String prefix, KeyPath path, String locale, Translation translation) {
|
||||||
|
return LookupElementBuilder.create(prefix + path.toSimpleString())
|
||||||
|
.withIcon(AllIcons.Actions.PreserveCaseHover)
|
||||||
|
.appendTailText(" I18n(" + locale + ": " + translation.get(locale) + ")", true);
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,12 +7,18 @@ import com.intellij.psi.impl.FakePsiElement;
|
|||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
import de.marhali.easyi18n.dialog.AddDialog;
|
import de.marhali.easyi18n.dialog.AddDialog;
|
||||||
import de.marhali.easyi18n.dialog.EditDialog;
|
import de.marhali.easyi18n.dialog.EditDialog;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
import de.marhali.easyi18n.model.KeyPathConverter;
|
||||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
import de.marhali.easyi18n.model.KeyedTranslation;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
import de.marhali.easyi18n.model.Translation;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go to declaration reference for i18n keys.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
public class KeyReference extends PsiReferenceBase<PsiElement> {
|
public class KeyReference extends PsiReferenceBase<PsiElement> {
|
||||||
|
|
||||||
@Nullable private final String myKey;
|
@Nullable private final String myKey;
|
||||||
@ -52,12 +58,14 @@ public class KeyReference extends PsiReferenceBase<PsiElement> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void navigate(boolean requestFocus) {
|
public void navigate(boolean requestFocus) {
|
||||||
Translation translation = InstanceManager.get(getProject()).store().getData().getTranslation(getKey());
|
KeyPathConverter converter = new KeyPathConverter(getProject());
|
||||||
|
KeyPath path = converter.split(getKey());
|
||||||
|
Translation translation = InstanceManager.get(getProject()).store().getData().getTranslation(path);
|
||||||
|
|
||||||
if(translation != null) {
|
if(translation != null) {
|
||||||
new EditDialog(getProject(), new KeyedTranslation(getKey(), translation)).showAndHandle();
|
new EditDialog(getProject(), new KeyedTranslation(path, translation)).showAndHandle();
|
||||||
} else {
|
} else {
|
||||||
new AddDialog(getProject(), getKey()).showAndHandle();
|
new AddDialog(getProject(), path).showAndHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.DataStore;
|
import de.marhali.easyi18n.DataStore;
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
|
import de.marhali.easyi18n.model.KeyPathConverter;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
import de.marhali.easyi18n.model.Translation;
|
||||||
import de.marhali.easyi18n.service.SettingsService;
|
import de.marhali.easyi18n.service.SettingsService;
|
||||||
|
|
||||||
@ -37,12 +38,13 @@ public class GenericFoldingBuilder extends FoldingBuilderEx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataStore store = InstanceManager.get(root.getProject()).store();
|
DataStore store = InstanceManager.get(root.getProject()).store();
|
||||||
|
KeyPathConverter converter = new KeyPathConverter(root.getProject());
|
||||||
|
|
||||||
for(final PsiLiteralValue literalValue : literalValues) {
|
for(final PsiLiteralValue literalValue : literalValues) {
|
||||||
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
String value = literalValue.getValue() instanceof String ? (String) literalValue.getValue() : null;
|
||||||
|
|
||||||
// Undefined string literal or not a translation
|
// Undefined string literal or not a translation
|
||||||
if(value == null || store.getData().getTranslation(value) == null) {
|
if(value == null || store.getData().getTranslation(converter.split(value)) == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +67,9 @@ public class GenericFoldingBuilder extends FoldingBuilderEx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataStore store = InstanceManager.get(literalValue.getProject()).store();
|
DataStore store = InstanceManager.get(literalValue.getProject()).store();
|
||||||
Translation translation = store.getData().getTranslation(value);
|
KeyPathConverter converter = new KeyPathConverter(literalValue.getProject());
|
||||||
|
|
||||||
|
Translation translation = store.getData().getTranslation(converter.split(value));
|
||||||
|
|
||||||
if(translation == null) {
|
if(translation == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -6,6 +6,7 @@ import com.intellij.util.ProcessingContext;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
import de.marhali.easyi18n.editor.KeyReference;
|
import de.marhali.easyi18n.editor.KeyReference;
|
||||||
|
import de.marhali.easyi18n.model.KeyPathConverter;
|
||||||
import de.marhali.easyi18n.service.SettingsService;
|
import de.marhali.easyi18n.service.SettingsService;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -38,7 +39,9 @@ public class GenericKeyReferenceContributor extends PsiReferenceContributor {
|
|||||||
return PsiReference.EMPTY_ARRAY;
|
return PsiReference.EMPTY_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(InstanceManager.get(element.getProject()).store().getData().getTranslation(value) == null) {
|
KeyPathConverter converter = new KeyPathConverter(element.getProject());
|
||||||
|
|
||||||
|
if(InstanceManager.get(element.getProject()).store().getData().getTranslation(converter.split(value)) == null) {
|
||||||
if(!KeyReference.isReferencable(value)) { // Creation policy
|
if(!KeyReference.isReferencable(value)) { // Creation policy
|
||||||
return PsiReference.EMPTY_ARRAY;
|
return PsiReference.EMPTY_ARRAY;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.intellij.util.ProcessingContext;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
import de.marhali.easyi18n.editor.KeyReference;
|
import de.marhali.easyi18n.editor.KeyReference;
|
||||||
|
import de.marhali.easyi18n.model.KeyPathConverter;
|
||||||
import de.marhali.easyi18n.service.SettingsService;
|
import de.marhali.easyi18n.service.SettingsService;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -45,7 +46,9 @@ public class KotlinKeyReferenceContributor extends PsiReferenceContributor {
|
|||||||
return PsiReference.EMPTY_ARRAY;
|
return PsiReference.EMPTY_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(InstanceManager.get(element.getProject()).store().getData().getNode(value) == null) {
|
KeyPathConverter converter = new KeyPathConverter(element.getProject());
|
||||||
|
|
||||||
|
if(InstanceManager.get(element.getProject()).store().getData().getNode(converter.split(value)) == null) {
|
||||||
return PsiReference.EMPTY_ARRAY;
|
return PsiReference.EMPTY_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public class JsonIOStrategy implements IOStrategy {
|
|||||||
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationData data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
TranslationData data = new TranslationData(state.isSortKeys());
|
||||||
|
|
||||||
for(VirtualFile file : directory.getChildren()) {
|
for(VirtualFile file : directory.getChildren()) {
|
||||||
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
||||||
|
@ -9,6 +9,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
|||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
import de.marhali.easyi18n.io.IOStrategy;
|
import de.marhali.easyi18n.io.IOStrategy;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.SettingsState;
|
import de.marhali.easyi18n.model.SettingsState;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
import de.marhali.easyi18n.model.TranslationNode;
|
||||||
@ -80,7 +81,7 @@ public class ModularizedJsonIOStrategy implements IOStrategy {
|
|||||||
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationData data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
TranslationData data = new TranslationData(state.isSortKeys());
|
||||||
VirtualFile[] localeDirectories = directory.getChildren();
|
VirtualFile[] localeDirectories = directory.getChildren();
|
||||||
|
|
||||||
for(VirtualFile localeDir : localeDirectories) {
|
for(VirtualFile localeDir : localeDirectories) {
|
||||||
@ -95,8 +96,8 @@ public class ModularizedJsonIOStrategy implements IOStrategy {
|
|||||||
|
|
||||||
String moduleName = module.getNameWithoutExtension();
|
String moduleName = module.getNameWithoutExtension();
|
||||||
|
|
||||||
TranslationNode moduleNode = data.getNode(moduleName) != null
|
TranslationNode moduleNode = data.getNode(KeyPath.of(moduleName)) != null
|
||||||
? data.getNode(moduleName)
|
? data.getNode(KeyPath.of(moduleName))
|
||||||
: new TranslationNode(state.isSortKeys() ? new TreeMap<>() : new LinkedHashMap<>());
|
: new TranslationNode(state.isSortKeys() ? new TreeMap<>() : new LinkedHashMap<>());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -59,7 +59,7 @@ public class PropertiesIOStrategy implements IOStrategy {
|
|||||||
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationData data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
TranslationData data = new TranslationData(state.isSortKeys());
|
||||||
|
|
||||||
for(VirtualFile file : directory.getChildren()) {
|
for(VirtualFile file : directory.getChildren()) {
|
||||||
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package de.marhali.easyi18n.io.properties;
|
package de.marhali.easyi18n.io.properties;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
import de.marhali.easyi18n.model.Translation;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
|
||||||
import de.marhali.easyi18n.util.StringUtil;
|
import de.marhali.easyi18n.util.StringUtil;
|
||||||
|
|
||||||
import org.apache.commons.lang.math.NumberUtils;
|
import org.apache.commons.lang.math.NumberUtils;
|
||||||
@ -17,7 +17,7 @@ public class PropertiesMapper {
|
|||||||
|
|
||||||
public static void read(String locale, SortableProperties properties, TranslationData data) {
|
public static void read(String locale, SortableProperties properties, TranslationData data) {
|
||||||
for(Map.Entry<Object, Object> entry : properties.entrySet()) {
|
for(Map.Entry<Object, Object> entry : properties.entrySet()) {
|
||||||
String key = String.valueOf(entry.getKey());
|
KeyPath key = new KeyPath(String.valueOf(entry.getKey()));
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
|
|
||||||
Translation translation = data.getTranslation(key);
|
Translation translation = data.getTranslation(key);
|
||||||
@ -36,18 +36,19 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void write(String locale, SortableProperties properties, TranslationData data) {
|
public static void write(String locale, SortableProperties properties, TranslationData data) {
|
||||||
for(String key : data.getFullKeys()) {
|
for(KeyPath key : data.getFullKeys()) {
|
||||||
Translation translation = data.getTranslation(key);
|
Translation translation = data.getTranslation(key);
|
||||||
|
|
||||||
if(translation != null && translation.containsKey(locale)) {
|
if(translation != null && translation.containsKey(locale)) {
|
||||||
|
String simpleKey = key.toSimpleString();
|
||||||
String content = translation.get(locale);
|
String content = translation.get(locale);
|
||||||
|
|
||||||
if(PropertiesArrayMapper.isArray(content)) {
|
if(PropertiesArrayMapper.isArray(content)) {
|
||||||
properties.put(key, PropertiesArrayMapper.write(content));
|
properties.put(simpleKey, PropertiesArrayMapper.write(content));
|
||||||
} else if(NumberUtils.isNumber(content)) {
|
} else if(NumberUtils.isNumber(content)) {
|
||||||
properties.put(key, NumberUtils.createNumber(content));
|
properties.put(simpleKey, NumberUtils.createNumber(content));
|
||||||
} else {
|
} else {
|
||||||
properties.put(key, content);
|
properties.put(simpleKey, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public class YamlIOStrategy implements IOStrategy {
|
|||||||
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationData data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
TranslationData data = new TranslationData(state.isSortKeys());
|
||||||
|
|
||||||
for(VirtualFile file : directory.getChildren()) {
|
for(VirtualFile file : directory.getChildren()) {
|
||||||
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
||||||
|
@ -2,7 +2,6 @@ package de.marhali.easyi18n.io.yaml;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.model.Translation;
|
import de.marhali.easyi18n.model.Translation;
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
import de.marhali.easyi18n.model.TranslationNode;
|
||||||
import de.marhali.easyi18n.util.PathUtil;
|
|
||||||
import de.marhali.easyi18n.util.StringUtil;
|
import de.marhali.easyi18n.util.StringUtil;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
@ -23,10 +22,6 @@ public class YamlMapper {
|
|||||||
public static void read(String locale, Section section, TranslationNode node) {
|
public static void read(String locale, Section section, TranslationNode node) {
|
||||||
for(String key : section.getKeys()) {
|
for(String key : section.getKeys()) {
|
||||||
Object value = section.getInScope(key).get();
|
Object value = section.getInScope(key).get();
|
||||||
|
|
||||||
key = StringUtil.escapeControls(
|
|
||||||
key.replace(PathUtil.DELIMITER, "\\" + PathUtil.DELIMITER), true);
|
|
||||||
|
|
||||||
TranslationNode childNode = node.getOrCreateChildren(key);
|
TranslationNode childNode = node.getOrCreateChildren(key);
|
||||||
|
|
||||||
if(value instanceof MapSection) {
|
if(value instanceof MapSection) {
|
||||||
@ -47,9 +42,7 @@ public class YamlMapper {
|
|||||||
|
|
||||||
public static void write(String locale, Section section, TranslationNode node) {
|
public static void write(String locale, Section section, TranslationNode node) {
|
||||||
for(Map.Entry<String, TranslationNode> entry : node.getChildren().entrySet()) {
|
for(Map.Entry<String, TranslationNode> entry : node.getChildren().entrySet()) {
|
||||||
String key = StringEscapeUtils.unescapeJava(
|
String key = entry.getKey();
|
||||||
entry.getKey().replace("\\" + PathUtil.DELIMITER, PathUtil.DELIMITER));
|
|
||||||
|
|
||||||
TranslationNode childNode = entry.getValue();
|
TranslationNode childNode = entry.getValue();
|
||||||
|
|
||||||
if(!childNode.isLeaf()) {
|
if(!childNode.isLeaf()) {
|
||||||
|
@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a full translation key with all sections.
|
* Represents a full translation key with all sections.
|
||||||
@ -16,7 +17,7 @@ public class KeyPath extends ArrayList<String> {
|
|||||||
|
|
||||||
public static final String DELIMITER = ".";
|
public static final String DELIMITER = ".";
|
||||||
|
|
||||||
public static KeyPath of(String... path) {
|
public static KeyPath of(@NotNull String... path) {
|
||||||
return new KeyPath(List.of(path));
|
return new KeyPath(List.of(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,34 @@ public class KeyPath extends ArrayList<String> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KeyPath(@NotNull KeyPath path, String... pathToAppend) {
|
||||||
|
this(path);
|
||||||
|
this.addAll(List.of(pathToAppend));
|
||||||
|
}
|
||||||
|
|
||||||
public KeyPath(@NotNull Collection<? extends String> c) {
|
public KeyPath(@NotNull Collection<? extends String> c) {
|
||||||
super(c);
|
super(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KeyPath(@NotNull String simplePath) {
|
||||||
|
this(List.of(simplePath.split(Pattern.quote(DELIMITER))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b>Note: </b>Use {@link KeyPathConverter} if you want to keep hierarchy.
|
||||||
|
* @return simple path representation by adding delimiter between the secton nodes
|
||||||
|
*/
|
||||||
|
public String toSimpleString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
for(String section : this) {
|
||||||
|
if(builder.length() > 0) {
|
||||||
|
builder.append(DELIMITER);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,19 +9,19 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class KeyedTranslation {
|
public class KeyedTranslation {
|
||||||
|
|
||||||
private @NotNull String key;
|
private @NotNull KeyPath key;
|
||||||
private @Nullable Translation translation;
|
private @Nullable Translation translation;
|
||||||
|
|
||||||
public KeyedTranslation(@NotNull String key, @Nullable Translation translation) {
|
public KeyedTranslation(@NotNull KeyPath key, @Nullable Translation translation) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.translation = translation;
|
this.translation = translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String getKey() {
|
public KeyPath getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKey(@NotNull String key) {
|
public void setKey(KeyPath key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package de.marhali.easyi18n.model;
|
package de.marhali.easyi18n.model;
|
||||||
|
|
||||||
import de.marhali.easyi18n.util.PathUtil;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -11,21 +9,21 @@ import java.util.*;
|
|||||||
* Cached translation data. The data is stored in a tree structure.
|
* Cached translation data. The data is stored in a tree structure.
|
||||||
* Tree behaviour (sorted, non-sorted) can be specified via constructor.
|
* Tree behaviour (sorted, non-sorted) can be specified via constructor.
|
||||||
* For more please see {@link TranslationNode}. Example tree view:
|
* For more please see {@link TranslationNode}. Example tree view:
|
||||||
* <br/>
|
* <pre>
|
||||||
* user: <br/>
|
* {@code
|
||||||
* -- principal: 'Principal' <br/>
|
* user:
|
||||||
* -- username: <br/>
|
* principal: 'Principal'
|
||||||
* -- -- title: 'Username' <br/>
|
* username:
|
||||||
* auth: <br/>
|
* title: 'Username'
|
||||||
* -- logout: 'Logout' <br/>
|
* auth:
|
||||||
* -- login: 'Login' <br/>
|
* logout: 'Logout'
|
||||||
*
|
* login: 'Login'
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class TranslationData {
|
public class TranslationData {
|
||||||
|
|
||||||
private final PathUtil pathUtil;
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Set<String> locales;
|
private final Set<String> locales;
|
||||||
|
|
||||||
@ -36,17 +34,15 @@ public class TranslationData {
|
|||||||
* Creates an empty instance.
|
* Creates an empty instance.
|
||||||
* @param sort Should the translation keys be sorted alphabetically
|
* @param sort Should the translation keys be sorted alphabetically
|
||||||
*/
|
*/
|
||||||
public TranslationData(boolean sort, boolean nestKeys) {
|
public TranslationData(boolean sort) {
|
||||||
this(nestKeys, new HashSet<>(), new TranslationNode(sort ? new TreeMap<>() : new LinkedHashMap<>()));
|
this(new HashSet<>(), new TranslationNode(sort ? new TreeMap<>() : new LinkedHashMap<>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nestKeys Apply key nesting. See {@link PathUtil}
|
|
||||||
* @param locales Languages which can be used for translation
|
* @param locales Languages which can be used for translation
|
||||||
* @param rootNode Translation tree structure
|
* @param rootNode Translation tree structure
|
||||||
*/
|
*/
|
||||||
public TranslationData(boolean nestKeys, @NotNull Set<String> locales, @NotNull TranslationNode rootNode) {
|
public TranslationData(@NotNull Set<String> locales, @NotNull TranslationNode rootNode) {
|
||||||
this.pathUtil = new PathUtil(nestKeys);
|
|
||||||
this.locales = locales;
|
this.locales = locales;
|
||||||
this.rootNode = rootNode;
|
this.rootNode = rootNode;
|
||||||
}
|
}
|
||||||
@ -76,15 +72,14 @@ public class TranslationData {
|
|||||||
* @param fullPath Absolute translation path
|
* @param fullPath Absolute translation path
|
||||||
* @return Translation node which leads to translations or nested child's
|
* @return Translation node which leads to translations or nested child's
|
||||||
*/
|
*/
|
||||||
public @Nullable TranslationNode getNode(@NotNull String fullPath) {
|
public @Nullable TranslationNode getNode(@NotNull KeyPath fullPath) {
|
||||||
List<String> sections = this.pathUtil.split(fullPath);
|
|
||||||
TranslationNode node = this.rootNode;
|
TranslationNode node = this.rootNode;
|
||||||
|
|
||||||
if(fullPath.isEmpty()) { // Return root node if empty path was supplied
|
if(fullPath.isEmpty()) { // Return root node if empty path was supplied
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(String section : sections) {
|
for(String section : fullPath) {
|
||||||
if(node == null) {
|
if(node == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -98,7 +93,7 @@ public class TranslationData {
|
|||||||
* @param fullPath Absolute translation key path
|
* @param fullPath Absolute translation key path
|
||||||
* @return Found translation. Can be null if path is empty or is not a leaf element
|
* @return Found translation. Can be null if path is empty or is not a leaf element
|
||||||
*/
|
*/
|
||||||
public @Nullable Translation getTranslation(@NotNull String fullPath) {
|
public @Nullable Translation getTranslation(@NotNull KeyPath fullPath) {
|
||||||
TranslationNode node = this.getNode(fullPath);
|
TranslationNode node = this.getNode(fullPath);
|
||||||
|
|
||||||
if(node == null || !node.isLeaf()) {
|
if(node == null || !node.isLeaf()) {
|
||||||
@ -109,50 +104,52 @@ public class TranslationData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Create / Update or Delete a specific translation.
|
||||||
|
* The parent path of the translation will be changed if necessary.
|
||||||
* @param fullPath Absolute translation key path
|
* @param fullPath Absolute translation key path
|
||||||
* @param translation Translation to set. Can be null to delete the corresponding node
|
* @param translation Translation to set. Can be null to delete the corresponding node
|
||||||
*/
|
*/
|
||||||
public void setTranslation(@NotNull String fullPath, @Nullable Translation translation) {
|
public void setTranslation(@NotNull KeyPath fullPath, @Nullable Translation translation) {
|
||||||
List<String> sections = this.pathUtil.split(fullPath);
|
|
||||||
String nodeKey = sections.remove(sections.size() - 1); // Edge case last section
|
|
||||||
TranslationNode node = this.rootNode;
|
|
||||||
|
|
||||||
if(fullPath.isEmpty()) {
|
if(fullPath.isEmpty()) {
|
||||||
throw new IllegalArgumentException("Path cannot be empty");
|
throw new IllegalArgumentException("Key path cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
for(String section : sections) { // Go to the level of the key (@nodeKey)
|
fullPath = new KeyPath(fullPath);
|
||||||
|
String leafKey = fullPath.remove(fullPath.size() - 1); // Extract edge section as children key of parent
|
||||||
|
TranslationNode node = this.rootNode;
|
||||||
|
|
||||||
|
for(String section : fullPath) { // Go to nested level at @leafKey
|
||||||
TranslationNode childNode = node.getChildren().get(section);
|
TranslationNode childNode = node.getChildren().get(section);
|
||||||
|
|
||||||
if(childNode == null) {
|
if(childNode == null) {
|
||||||
if(translation == null) { // Path should not be empty for delete
|
if(translation == null) { // Path must not be empty on delete
|
||||||
throw new IllegalArgumentException("Delete action on empty path");
|
throw new IllegalArgumentException("Delete action on empty path");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Created nested section
|
|
||||||
childNode = node.setChildren(section);
|
childNode = node.setChildren(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
node = childNode;
|
node = childNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(translation == null) { // Delete
|
if(translation == null) { // Delete action
|
||||||
node.removeChildren(nodeKey);
|
node.removeChildren(leafKey);
|
||||||
|
|
||||||
if(node.getChildren().isEmpty() && !node.isRoot()) { // Parent is empty now. Run delete recursively
|
if(node.getChildren().isEmpty() && !node.isRoot()) { // Node is empty now. Run delete recursively
|
||||||
this.setTranslation(this.pathUtil.concat(sections), null);
|
this.setTranslation(fullPath, null);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
} else { // Create or overwrite
|
|
||||||
node.setChildren(nodeKey, translation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create or overwrite
|
||||||
|
node.setChildren(leafKey, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return All translation keys as absolute paths (full-key)
|
* @return All translation keys as absolute paths (full-key)
|
||||||
*/
|
*/
|
||||||
public @NotNull Set<String> getFullKeys() {
|
public @NotNull Set<KeyPath> getFullKeys() {
|
||||||
return this.getFullKeys("", this.rootNode); // Just use root node
|
return this.getFullKeys(new KeyPath(), this.rootNode); // Just use root node
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,15 +157,15 @@ public class TranslationData {
|
|||||||
* @param node Node section to begin with
|
* @param node Node section to begin with
|
||||||
* @return All translation keys where the path contains the specified @parentPath
|
* @return All translation keys where the path contains the specified @parentPath
|
||||||
*/
|
*/
|
||||||
public @NotNull Set<String> getFullKeys(String parentPath, TranslationNode node) {
|
public @NotNull Set<KeyPath> getFullKeys(KeyPath parentPath, TranslationNode node) {
|
||||||
Set<String> keys = new LinkedHashSet<>();
|
Set<KeyPath> keys = new LinkedHashSet<>();
|
||||||
|
|
||||||
if(node.isLeaf()) { // This node does not lead to child's - just add the key
|
if(node.isLeaf()) { // This node does not lead to child's - just add the key
|
||||||
keys.add(parentPath);
|
keys.add(parentPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Map.Entry<String, TranslationNode> children : node.getChildren().entrySet()) {
|
for(Map.Entry<String, TranslationNode> children : node.getChildren().entrySet()) {
|
||||||
keys.addAll(this.getFullKeys(this.pathUtil.append(parentPath, children.getKey()), children.getValue()));
|
keys.addAll(this.getFullKeys(new KeyPath(parentPath, children.getKey()), children.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return keys;
|
return keys;
|
||||||
@ -178,7 +175,6 @@ public class TranslationData {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "TranslationData{" +
|
return "TranslationData{" +
|
||||||
"mapClass=" + rootNode.getChildren().getClass().getSimpleName() +
|
"mapClass=" + rootNode.getChildren().getClass().getSimpleName() +
|
||||||
", pathUtil=" + pathUtil +
|
|
||||||
", locales=" + locales +
|
", locales=" + locales +
|
||||||
", rootNode=" + rootNode +
|
", rootNode=" + rootNode +
|
||||||
'}';
|
'}';
|
||||||
|
@ -7,14 +7,13 @@ import java.util.Map;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Translation tree node. Manages child nodes which can be translations or also
|
* Translation tree node. Manages child nodes which can be translations or also
|
||||||
* nodes which can lead to another translation or node.
|
* nodes which can lead to another translation or node.<br>
|
||||||
* Navigation inside a node can be upward and downward. To construct the full
|
* Navigation inside a node can be upward and downward. To construct the full
|
||||||
* translation key (full-key) every parent needs to be resolved recursively.
|
* translation key (full-key) every parent needs to be resolved recursively. <br>
|
||||||
* -
|
* <br>
|
||||||
* Whether the children nodes should be sorted is determined by the parent node.
|
* Whether the children nodes should be sorted is determined by the parent node.
|
||||||
* For root nodes (empty parent) the {@link java.util.Map}-Type must be specified
|
* For root nodes (empty parent) the {@link java.util.Map}-Type must be specified
|
||||||
* to determine which sorting should be applied.
|
* to determine which sorting should be applied.
|
||||||
*
|
|
||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class TranslationNode {
|
public class TranslationNode {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package de.marhali.easyi18n.model.bus;
|
package de.marhali.easyi18n.model.bus;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Single event listener.
|
* Single event listener.
|
||||||
@ -11,5 +13,5 @@ public interface FocusKeyListener {
|
|||||||
* Move the specified translation key (full-key) into focus.
|
* Move the specified translation key (full-key) into focus.
|
||||||
* @param key Absolute translation key
|
* @param key Absolute translation key
|
||||||
*/
|
*/
|
||||||
void onFocusKey(@Nullable String key);
|
void onFocusKey(@NotNull KeyPath key);
|
||||||
}
|
}
|
@ -28,15 +28,16 @@ import java.util.ResourceBundle;
|
|||||||
*/
|
*/
|
||||||
public class TableView implements BusListener {
|
public class TableView implements BusListener {
|
||||||
|
|
||||||
|
private final JBTable table;
|
||||||
|
|
||||||
private final Project project;
|
private final Project project;
|
||||||
|
|
||||||
private TableModelMapper currentMapper;
|
private TableModelMapper currentMapper;
|
||||||
|
private KeyPathConverter converter;
|
||||||
|
|
||||||
private JPanel rootPanel;
|
private JPanel rootPanel;
|
||||||
private JPanel containerPanel;
|
private JPanel containerPanel;
|
||||||
|
|
||||||
private JBTable table;
|
|
||||||
|
|
||||||
public TableView(Project project) {
|
public TableView(Project project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ public class TableView implements BusListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fullPath = String.valueOf(table.getValueAt(row, 0));
|
KeyPath fullPath = this.converter.split(String.valueOf(this.table.getValueAt(row, 0)));
|
||||||
Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
|
Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
|
||||||
|
|
||||||
if (translation != null) {
|
if (translation != null) {
|
||||||
@ -65,7 +66,7 @@ public class TableView implements BusListener {
|
|||||||
|
|
||||||
private void deleteSelectedRows() {
|
private void deleteSelectedRows() {
|
||||||
for (int selectedRow : table.getSelectedRows()) {
|
for (int selectedRow : table.getSelectedRows()) {
|
||||||
String fullPath = String.valueOf(table.getValueAt(selectedRow, 0));
|
KeyPath fullPath = this.converter.split(String.valueOf(table.getValueAt(selectedRow, 0)));
|
||||||
|
|
||||||
InstanceManager.get(project).processUpdate(
|
InstanceManager.get(project).processUpdate(
|
||||||
new TranslationDelete(new KeyedTranslation(fullPath, null))
|
new TranslationDelete(new KeyedTranslation(fullPath, null))
|
||||||
@ -75,16 +76,19 @@ public class TableView implements BusListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateData(@NotNull TranslationData data) {
|
public void onUpdateData(@NotNull TranslationData data) {
|
||||||
table.setModel(this.currentMapper = new TableModelMapper(data, update ->
|
this.converter = new KeyPathConverter(project);
|
||||||
|
|
||||||
|
table.setModel(this.currentMapper = new TableModelMapper(data, this.converter, update ->
|
||||||
InstanceManager.get(project).processUpdate(update)));
|
InstanceManager.get(project).processUpdate(update)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFocusKey(@Nullable String key) {
|
public void onFocusKey(@NotNull KeyPath key) {
|
||||||
|
String concatKey = this.converter.concat(key);
|
||||||
int row = -1;
|
int row = -1;
|
||||||
|
|
||||||
for (int i = 0; i < table.getRowCount(); i++) {
|
for (int i = 0; i < table.getRowCount(); i++) {
|
||||||
if (String.valueOf(table.getValueAt(i, 0)).equals(key)) {
|
if (table.getValueAt(i, 0).equals(concatKey)) {
|
||||||
row = i;
|
row = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,7 @@ import com.intellij.ui.treeStructure.Tree;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.InstanceManager;
|
import de.marhali.easyi18n.InstanceManager;
|
||||||
import de.marhali.easyi18n.listener.ReturnKeyListener;
|
import de.marhali.easyi18n.listener.ReturnKeyListener;
|
||||||
import de.marhali.easyi18n.model.KeyedTranslation;
|
import de.marhali.easyi18n.model.*;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
|
||||||
import de.marhali.easyi18n.model.TranslationDelete;
|
|
||||||
import de.marhali.easyi18n.model.bus.BusListener;
|
import de.marhali.easyi18n.model.bus.BusListener;
|
||||||
import de.marhali.easyi18n.action.treeview.CollapseTreeViewAction;
|
import de.marhali.easyi18n.action.treeview.CollapseTreeViewAction;
|
||||||
import de.marhali.easyi18n.action.treeview.ExpandTreeViewAction;
|
import de.marhali.easyi18n.action.treeview.ExpandTreeViewAction;
|
||||||
@ -40,6 +37,8 @@ import java.util.ResourceBundle;
|
|||||||
*/
|
*/
|
||||||
public class TreeView implements BusListener {
|
public class TreeView implements BusListener {
|
||||||
|
|
||||||
|
private final Tree tree;
|
||||||
|
|
||||||
private final Project project;
|
private final Project project;
|
||||||
|
|
||||||
private TreeModelMapper currentMapper;
|
private TreeModelMapper currentMapper;
|
||||||
@ -48,8 +47,6 @@ public class TreeView implements BusListener {
|
|||||||
private JPanel toolBarPanel;
|
private JPanel toolBarPanel;
|
||||||
private JPanel containerPanel;
|
private JPanel containerPanel;
|
||||||
|
|
||||||
private Tree tree;
|
|
||||||
|
|
||||||
public TreeView(Project project) {
|
public TreeView(Project project) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
|
|
||||||
@ -87,8 +84,8 @@ public class TreeView implements BusListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFocusKey(@Nullable String key) {
|
public void onFocusKey(@NotNull KeyPath key) {
|
||||||
if (key != null && currentMapper != null) {
|
if (currentMapper != null) {
|
||||||
TreePath path = currentMapper.findTreePath(key);
|
TreePath path = currentMapper.findTreePath(key);
|
||||||
|
|
||||||
this.tree.getSelectionModel().setSelectionPath(path);
|
this.tree.getSelectionModel().setSelectionPath(path);
|
||||||
@ -120,7 +117,7 @@ public class TreeView implements BusListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fullPath = TreeUtil.getFullPath(path);
|
KeyPath fullPath = TreeUtil.getFullPath(path);
|
||||||
Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
|
Translation translation = InstanceManager.get(project).store().getData().getTranslation(fullPath);
|
||||||
|
|
||||||
if (translation == null) {
|
if (translation == null) {
|
||||||
@ -138,7 +135,7 @@ public class TreeView implements BusListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (TreePath path : tree.getSelectionPaths()) {
|
for (TreePath path : tree.getSelectionPaths()) {
|
||||||
String fullPath = TreeUtil.getFullPath(path);
|
KeyPath fullPath = TreeUtil.getFullPath(path);
|
||||||
|
|
||||||
InstanceManager.get(project).processUpdate(
|
InstanceManager.get(project).processUpdate(
|
||||||
new TranslationDelete(new KeyedTranslation(fullPath, null))
|
new TranslationDelete(new KeyedTranslation(fullPath, null))
|
||||||
|
@ -20,13 +20,18 @@ import java.util.function.Consumer;
|
|||||||
public class TableModelMapper implements TableModel, SearchQueryListener {
|
public class TableModelMapper implements TableModel, SearchQueryListener {
|
||||||
|
|
||||||
private final @NotNull TranslationData data;
|
private final @NotNull TranslationData data;
|
||||||
|
private final @NotNull KeyPathConverter converter;
|
||||||
|
|
||||||
private final @NotNull List<String> locales;
|
private final @NotNull List<String> locales;
|
||||||
private @NotNull List<String> fullKeys;
|
private @NotNull List<KeyPath> fullKeys;
|
||||||
|
|
||||||
private final @NotNull Consumer<TranslationUpdate> updater;
|
private final @NotNull Consumer<TranslationUpdate> updater;
|
||||||
|
|
||||||
public TableModelMapper(@NotNull TranslationData data, @NotNull Consumer<TranslationUpdate> updater) {
|
public TableModelMapper(@NotNull TranslationData data, @NotNull KeyPathConverter converter,
|
||||||
|
@NotNull Consumer<TranslationUpdate> updater) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.converter = converter;
|
||||||
|
|
||||||
this.locales = new ArrayList<>(data.getLocales());
|
this.locales = new ArrayList<>(data.getLocales());
|
||||||
this.fullKeys = new ArrayList<>(data.getFullKeys());
|
this.fullKeys = new ArrayList<>(data.getFullKeys());
|
||||||
|
|
||||||
@ -41,10 +46,10 @@ public class TableModelMapper implements TableModel, SearchQueryListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
List<String> matches = new ArrayList<>();
|
List<KeyPath> matches = new ArrayList<>();
|
||||||
|
|
||||||
for(String key : this.data.getFullKeys()) {
|
for(KeyPath key : this.data.getFullKeys()) {
|
||||||
if(key.toLowerCase().contains(query)) {
|
if(this.converter.concat(key).toLowerCase().contains(query)) {
|
||||||
matches.add(key);
|
matches.add(key);
|
||||||
} else {
|
} else {
|
||||||
for(String content : this.data.getTranslation(key).values()) {
|
for(String content : this.data.getTranslation(key).values()) {
|
||||||
@ -90,11 +95,12 @@ public class TableModelMapper implements TableModel, SearchQueryListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||||
|
KeyPath key = this.fullKeys.get(rowIndex);
|
||||||
|
|
||||||
if(columnIndex == 0) { // Keys
|
if(columnIndex == 0) { // Keys
|
||||||
return this.fullKeys.get(rowIndex);
|
return this.converter.concat(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = this.fullKeys.get(rowIndex);
|
|
||||||
String locale = this.locales.get(columnIndex - 1);
|
String locale = this.locales.get(columnIndex - 1);
|
||||||
Translation translation = this.data.getTranslation(key);
|
Translation translation = this.data.getTranslation(key);
|
||||||
|
|
||||||
@ -103,14 +109,14 @@ public class TableModelMapper implements TableModel, SearchQueryListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||||
String key = String.valueOf(this.getValueAt(rowIndex, 0));
|
KeyPath key = this.fullKeys.get(rowIndex);
|
||||||
Translation translation = this.data.getTranslation(key);
|
Translation translation = this.data.getTranslation(key);
|
||||||
|
|
||||||
if(translation == null) { // Unknown cell
|
if(translation == null) { // Unknown cell
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String newKey = columnIndex == 0 ? String.valueOf(aValue) : key;
|
KeyPath newKey = columnIndex == 0 ? this.converter.split(String.valueOf(aValue)) : key;
|
||||||
|
|
||||||
// Translation content update
|
// Translation content update
|
||||||
if(columnIndex > 0) {
|
if(columnIndex > 0) {
|
||||||
|
@ -3,12 +3,8 @@ package de.marhali.easyi18n.tabs.mapper;
|
|||||||
import com.intellij.ide.projectView.PresentationData;
|
import com.intellij.ide.projectView.PresentationData;
|
||||||
import com.intellij.ui.JBColor;
|
import com.intellij.ui.JBColor;
|
||||||
|
|
||||||
import de.marhali.easyi18n.model.SettingsState;
|
import de.marhali.easyi18n.model.*;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
|
||||||
import de.marhali.easyi18n.model.bus.SearchQueryListener;
|
import de.marhali.easyi18n.model.bus.SearchQueryListener;
|
||||||
import de.marhali.easyi18n.util.PathUtil;
|
|
||||||
import de.marhali.easyi18n.util.UiUtil;
|
import de.marhali.easyi18n.util.UiUtil;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -26,12 +22,14 @@ import java.util.Map;
|
|||||||
public class TreeModelMapper extends DefaultTreeModel implements SearchQueryListener {
|
public class TreeModelMapper extends DefaultTreeModel implements SearchQueryListener {
|
||||||
|
|
||||||
private final TranslationData data;
|
private final TranslationData data;
|
||||||
|
private final KeyPathConverter converter;
|
||||||
private final SettingsState state;
|
private final SettingsState state;
|
||||||
|
|
||||||
public TreeModelMapper(TranslationData data, SettingsState state) {
|
public TreeModelMapper(TranslationData data, SettingsState state) {
|
||||||
super(null);
|
super(null);
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.converter = new KeyPathConverter(state.isNestedKeys());
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
|
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
|
||||||
@ -42,7 +40,7 @@ public class TreeModelMapper extends DefaultTreeModel implements SearchQueryList
|
|||||||
@Override
|
@Override
|
||||||
public void onSearchQuery(@Nullable String query) {
|
public void onSearchQuery(@Nullable String query) {
|
||||||
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
|
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
|
||||||
TranslationData shadow = new TranslationData(this.state.isSortKeys(), this.state.isNestedKeys());
|
TranslationData shadow = new TranslationData(this.state.isSortKeys());
|
||||||
|
|
||||||
if(query == null) {
|
if(query == null) {
|
||||||
this.generateNodes(rootNode, this.data.getRootNode());
|
this.generateNodes(rootNode, this.data.getRootNode());
|
||||||
@ -52,9 +50,9 @@ public class TreeModelMapper extends DefaultTreeModel implements SearchQueryList
|
|||||||
|
|
||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
|
|
||||||
for(String currentKey : this.data.getFullKeys()) {
|
for(KeyPath currentKey : this.data.getFullKeys()) {
|
||||||
Translation translation = this.data.getTranslation(currentKey);
|
Translation translation = this.data.getTranslation(currentKey);
|
||||||
String loweredKey = currentKey.toLowerCase();
|
String loweredKey = this.converter.concat(currentKey).toLowerCase();
|
||||||
|
|
||||||
if(query.contains(loweredKey) || loweredKey.contains(query)) {
|
if(query.contains(loweredKey) || loweredKey.contains(query)) {
|
||||||
shadow.setTranslation(currentKey, translation);
|
shadow.setTranslation(currentKey, translation);
|
||||||
@ -100,14 +98,13 @@ public class TreeModelMapper extends DefaultTreeModel implements SearchQueryList
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull TreePath findTreePath(@NotNull String fullPath) {
|
public @NotNull TreePath findTreePath(@NotNull KeyPath fullPath) {
|
||||||
List<String> sections = new PathUtil(this.state.isNestedKeys()).split(fullPath);
|
|
||||||
List<Object> nodes = new ArrayList<>();
|
List<Object> nodes = new ArrayList<>();
|
||||||
|
|
||||||
TreeNode currentNode = (TreeNode) this.getRoot();
|
TreeNode currentNode = (TreeNode) this.getRoot();
|
||||||
nodes.add(currentNode);
|
nodes.add(currentNode);
|
||||||
|
|
||||||
for(String section : sections) {
|
for(String section : fullPath) {
|
||||||
currentNode = this.findNode(currentNode, section);
|
currentNode = this.findNode(currentNode, section);
|
||||||
|
|
||||||
if(currentNode == null) {
|
if(currentNode == null) {
|
||||||
@ -120,7 +117,7 @@ public class TreeModelMapper extends DefaultTreeModel implements SearchQueryList
|
|||||||
return new TreePath(nodes.toArray());
|
return new TreePath(nodes.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable DefaultMutableTreeNode findNode(@NotNull TreeNode parent, @NotNull String key) {
|
private @Nullable DefaultMutableTreeNode findNode(@NotNull TreeNode parent, @NotNull String key) {
|
||||||
for(int i = 0; i < parent.getChildCount(); i++) {
|
for(int i = 0; i < parent.getChildCount(); i++) {
|
||||||
TreeNode child = parent.getChildAt(i);
|
TreeNode child = parent.getChildAt(i);
|
||||||
|
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
package de.marhali.easyi18n.util;
|
|
||||||
|
|
||||||
import de.marhali.easyi18n.service.SettingsService;
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility tool for split and merge translation key paths.
|
|
||||||
* Some i18n implementations require to NOT nest the translation keys.
|
|
||||||
* This util takes care of this and checks the configured setting for this case.
|
|
||||||
* @author marhali
|
|
||||||
* @deprecated Replaced by KeyPathConverter
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class PathUtil {
|
|
||||||
|
|
||||||
public static final String DELIMITER = ".";
|
|
||||||
|
|
||||||
private final boolean nestKeys;
|
|
||||||
|
|
||||||
public PathUtil(boolean nestKeys) {
|
|
||||||
this.nestKeys = nestKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PathUtil(Project project) {
|
|
||||||
this.nestKeys = SettingsService.getInstance(project).getState().isNestedKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull List<String> split(@NotNull String path) {
|
|
||||||
// Does not contain any sections or key nesting is disabled
|
|
||||||
if(!path.contains(DELIMITER) || !nestKeys) {
|
|
||||||
return new ArrayList<>(Collections.singletonList(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ArrayList<>(Arrays.asList(
|
|
||||||
path.split("(?<!\\\\)" + Pattern.quote(DELIMITER))));
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull String concat(@NotNull List<String> sections) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
// For disabled key nesting this should be only one section
|
|
||||||
for(String section : sections) {
|
|
||||||
if(builder.length() > 0) {
|
|
||||||
builder.append(DELIMITER);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull String append(@NotNull String parentPath, @NotNull String children) {
|
|
||||||
StringBuilder builder = new StringBuilder(parentPath);
|
|
||||||
|
|
||||||
if(builder.length() > 0) { // Only add delimiter between parent and child if parent is NOT empty
|
|
||||||
builder.append(DELIMITER);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.append(children).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "PathUtil{" +
|
|
||||||
"nestKeys=" + nestKeys +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package de.marhali.easyi18n.util;
|
package de.marhali.easyi18n.util;
|
||||||
|
|
||||||
import com.intellij.ide.projectView.PresentationData;
|
import com.intellij.ide.projectView.PresentationData;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
@ -13,13 +14,13 @@ public class TreeUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the full path for a given {@link TreePath}
|
* Constructs the full path for a given {@link TreePath}
|
||||||
* @param path TreePath
|
* @param treePath TreePath
|
||||||
* @return Full key (e.g user.username.title)
|
* @return Corresponding key path
|
||||||
*/
|
*/
|
||||||
public static String getFullPath(TreePath path) {
|
public static KeyPath getFullPath(TreePath treePath) {
|
||||||
StringBuilder builder = new StringBuilder();
|
KeyPath keyPath = new KeyPath();
|
||||||
|
|
||||||
for (Object obj : path.getPath()) {
|
for (Object obj : treePath.getPath()) {
|
||||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj;
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj;
|
||||||
Object value = node.getUserObject();
|
Object value = node.getUserObject();
|
||||||
String section = value instanceof PresentationData ?
|
String section = value instanceof PresentationData ?
|
||||||
@ -29,13 +30,9 @@ public class TreeUtil {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(builder.length() != 0) {
|
keyPath.add(section);
|
||||||
builder.append(PathUtil.DELIMITER);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(section);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.toString();
|
return keyPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,6 +19,6 @@ settings.path.file-pattern-tooltip=Defines a wildcard matcher to filter relevant
|
|||||||
settings.path.prefix=Path prefix
|
settings.path.prefix=Path prefix
|
||||||
settings.preview=Preview locale
|
settings.preview=Preview locale
|
||||||
settings.keys.sort=Sort translation keys alphabetically
|
settings.keys.sort=Sort translation keys alphabetically
|
||||||
settings.keys.nested=Nest translation keys if possible
|
settings.keys.nested=Escape delimiter character within a section layer.
|
||||||
settings.editor.assistance=I18n key completion, annotation and reference inside editor
|
settings.editor.assistance=I18n key completion, annotation and reference inside editor
|
||||||
error.io=Could not process file {0} with {1}. Unwanted files can be ignored via Translation file wildcard matcher option.
|
error.io=Could not process file {0} with {1}. Unwanted files can be ignored via Translation file wildcard matcher option.
|
@ -1,5 +1,6 @@
|
|||||||
package de.marhali.easyi18n;
|
package de.marhali.easyi18n;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.Translation;
|
import de.marhali.easyi18n.model.Translation;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import de.marhali.easyi18n.model.TranslationNode;
|
import de.marhali.easyi18n.model.TranslationNode;
|
||||||
@ -15,256 +16,184 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class TranslationDataTest {
|
public class TranslationDataTest {
|
||||||
|
|
||||||
private final int numOfTranslations = 18;
|
private final int numOfTranslations = 14;
|
||||||
|
private final Translation translation = new Translation("en", "test");
|
||||||
|
|
||||||
private void addTranslations(TranslationData data) {
|
private void addTranslations(TranslationData data) {
|
||||||
data.setTranslation("zulu", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("zulu"), translation);
|
||||||
data.setTranslation("gamma", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("gamma"), translation);
|
||||||
|
|
||||||
data.setTranslation("foxtrot.super.long.key", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("foxtrot.super.long.key"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("foxtrot", "super", "long", "key"), translation);
|
||||||
|
|
||||||
data.setTranslation("bravo.b", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("charlie.b", "sub"), translation);
|
||||||
data.setTranslation("bravo.c", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("charlie.a", "sub"), translation);
|
||||||
data.setTranslation("bravo.a", new Translation("en", "test"));
|
|
||||||
data.setTranslation("bravo.d", new Translation("en", "test"));
|
|
||||||
data.setTranslation("bravo.long.bravo", new Translation("en", "test"));
|
|
||||||
data.setTranslation("bravo.long.charlie.a", new Translation("en", "test"));
|
|
||||||
data.setTranslation("bravo.long.alpha", new Translation("en", "test"));
|
|
||||||
|
|
||||||
data.setTranslation("alpha.b", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo.b"), translation);
|
||||||
data.setTranslation("alpha.c", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo.c"), translation);
|
||||||
data.setTranslation("alpha.a", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo.a"), translation);
|
||||||
data.setTranslation("alpha.d", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo.d"), translation);
|
||||||
|
|
||||||
data.setTranslation("charlie.b", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo", "b"), translation);
|
||||||
data.setTranslation("charlie.c", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo", "c"), translation);
|
||||||
data.setTranslation("charlie.a", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo", "a"), translation);
|
||||||
data.setTranslation("charlie.d", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("bravo", "d"), translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeySorting() {
|
public void testKeySorting() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
this.addTranslations(data);
|
this.addTranslations(data);
|
||||||
|
|
||||||
Set<String> expectation = new LinkedHashSet<>(Arrays.asList(
|
Set<KeyPath> expectation = new LinkedHashSet<>(Arrays.asList(
|
||||||
"alpha.a", "alpha.b", "alpha.c", "alpha.d",
|
KeyPath.of("bravo", "a"), KeyPath.of("bravo", "b"), KeyPath.of("bravo", "c"), KeyPath.of("bravo", "d"),
|
||||||
"bravo.a", "bravo.b", "bravo.c", "bravo.d",
|
KeyPath.of("bravo.a"), KeyPath.of("bravo.b"), KeyPath.of("bravo.c"), KeyPath.of("bravo.d"),
|
||||||
"bravo.long.alpha", "bravo.long.bravo", "bravo.long.charlie.a",
|
KeyPath.of("charlie.a", "sub"), KeyPath.of("charlie.b", "sub"),
|
||||||
"charlie.a", "charlie.b", "charlie.c", "charlie.d",
|
KeyPath.of("foxtrot", "super", "long", "key"),
|
||||||
"foxtrot.super.long.key",
|
KeyPath.of("foxtrot.super.long.key"),
|
||||||
"gamma",
|
KeyPath.of("gamma"),
|
||||||
"zulu"
|
KeyPath.of("zulu")
|
||||||
));
|
));
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys(), expectation);
|
Assert.assertEquals(data.getFullKeys(), expectation);
|
||||||
|
Assert.assertEquals(data.getFullKeys().size(), numOfTranslations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeyUnordered() {
|
public void testKeyUnordered() {
|
||||||
TranslationData data = new TranslationData(false, true);
|
TranslationData data = new TranslationData(false);
|
||||||
this.addTranslations(data);
|
this.addTranslations(data);
|
||||||
|
|
||||||
Set<String> expectation = new LinkedHashSet<>(Arrays.asList(
|
Set<KeyPath> expectation = new LinkedHashSet<>(Arrays.asList(
|
||||||
"zulu",
|
KeyPath.of("zulu"),
|
||||||
"gamma",
|
KeyPath.of("gamma"),
|
||||||
"foxtrot.super.long.key",
|
KeyPath.of("foxtrot.super.long.key"),
|
||||||
"bravo.b", "bravo.c", "bravo.a", "bravo.d",
|
KeyPath.of("foxtrot", "super", "long", "key"),
|
||||||
"bravo.long.bravo", "bravo.long.charlie.a", "bravo.long.alpha",
|
KeyPath.of("charlie.b", "sub"), KeyPath.of("charlie.a", "sub"),
|
||||||
"alpha.b", "alpha.c", "alpha.a", "alpha.d",
|
KeyPath.of("bravo.b"), KeyPath.of("bravo.c"), KeyPath.of("bravo.a"), KeyPath.of("bravo.d"),
|
||||||
"charlie.b", "charlie.c", "charlie.a", "charlie.d"
|
KeyPath.of("bravo", "b"), KeyPath.of("bravo", "c"), KeyPath.of("bravo", "a"), KeyPath.of("bravo", "d")
|
||||||
));
|
));
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys(), expectation);
|
Assert.assertEquals(data.getFullKeys(), expectation);
|
||||||
|
Assert.assertEquals(data.getFullKeys().size(), numOfTranslations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeyNesting() {
|
public void testDelete() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
|
|
||||||
data.setTranslation("nested.alpha", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("alpha"), translation);
|
||||||
data.setTranslation("nested.bravo", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("nested.alpha"), translation);
|
||||||
data.setTranslation("other.alpha", new Translation("en", "test"));
|
data.setTranslation(KeyPath.of("nested.long.bravo"), translation);
|
||||||
data.setTranslation("other.bravo", new Translation("en", "test"));
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getRootNode().getChildren().size(), 2);
|
data.setTranslation(KeyPath.of("beta"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("nested", "alpha"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("nested", "long", "bravo"), translation);
|
||||||
|
|
||||||
for(TranslationNode node : data.getRootNode().getChildren().values()) {
|
Assert.assertEquals(data.getFullKeys().size(), 6);
|
||||||
Assert.assertFalse(node.isLeaf());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
data.setTranslation(KeyPath.of("alpha"), null);
|
||||||
public void testKeyNonNested() {
|
data.setTranslation(KeyPath.of("nested.alpha"), null);
|
||||||
TranslationData data = new TranslationData(true, false);
|
data.setTranslation(KeyPath.of("nested.long.bravo"), null);
|
||||||
this.addTranslations(data);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getRootNode().getChildren().size(), this.numOfTranslations);
|
|
||||||
|
|
||||||
for(TranslationNode node : data.getRootNode().getChildren().values()) {
|
|
||||||
Assert.assertTrue(node.isLeaf());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeleteNested() {
|
|
||||||
TranslationData data = new TranslationData(true, true);
|
|
||||||
|
|
||||||
Translation value = new Translation("en", "test");
|
|
||||||
|
|
||||||
data.setTranslation("alpha", value);
|
|
||||||
data.setTranslation("nested.alpha", value);
|
|
||||||
data.setTranslation("nested.long.bravo", value);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 3);
|
Assert.assertEquals(data.getFullKeys().size(), 3);
|
||||||
|
|
||||||
data.setTranslation("alpha", null);
|
data.setTranslation(KeyPath.of("beta"), null);
|
||||||
data.setTranslation("nested.alpha", null);
|
data.setTranslation(KeyPath.of("nested", "alpha"), null);
|
||||||
data.setTranslation("nested.long.bravo", null);
|
data.setTranslation(KeyPath.of("nested", "long", "bravo"), null);
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 0);
|
Assert.assertEquals(data.getFullKeys().size(), 0);
|
||||||
Assert.assertNull(data.getTranslation("alpha"));
|
|
||||||
Assert.assertNull(data.getTranslation("nested.alpha"));
|
Assert.assertNull(data.getTranslation(KeyPath.of("alpha")));
|
||||||
Assert.assertNull(data.getTranslation("nested.long.bravo"));
|
Assert.assertNull(data.getTranslation(KeyPath.of("nested.alpha")));
|
||||||
|
Assert.assertNull(data.getTranslation(KeyPath.of("nested.long.bravo")));
|
||||||
|
|
||||||
|
Assert.assertNull(data.getTranslation(KeyPath.of("beta")));
|
||||||
|
Assert.assertNull(data.getTranslation(KeyPath.of("nested", "alpha")));
|
||||||
|
Assert.assertNull(data.getTranslation(KeyPath.of("nested", "long", "bravo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteNonNested() {
|
public void testDeleteRecursively() {
|
||||||
TranslationData data = new TranslationData(true, false);
|
TranslationData data = new TranslationData(true);
|
||||||
|
|
||||||
Translation value = new Translation("en", "test");
|
|
||||||
|
|
||||||
data.setTranslation("alpha", value);
|
|
||||||
data.setTranslation("nested.alpha", value);
|
|
||||||
data.setTranslation("nested.long.bravo", value);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 3);
|
|
||||||
|
|
||||||
data.setTranslation("alpha", null);
|
|
||||||
data.setTranslation("nested.alpha", null);
|
|
||||||
data.setTranslation("nested.long.bravo", null);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 0);
|
|
||||||
Assert.assertNull(data.getTranslation("alpha"));
|
|
||||||
Assert.assertNull(data.getTranslation("nested.alpha"));
|
|
||||||
Assert.assertNull(data.getTranslation("nested.long.bravo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRecurseDeleteNonNested() {
|
|
||||||
TranslationData data = new TranslationData(true, false);
|
|
||||||
this.addTranslations(data);
|
this.addTranslations(data);
|
||||||
|
|
||||||
data.setTranslation("foxtrot.super.long.key", null);
|
data.setTranslation(KeyPath.of("foxtrot.super.long.key"), null);
|
||||||
|
data.setTranslation(KeyPath.of("foxtrot", "super", "long", "key"), null);
|
||||||
|
|
||||||
Assert.assertNull(data.getTranslation("foxtrot.super.long.key"));
|
Assert.assertNull(data.getTranslation(KeyPath.of("foxtrot.super.long.key")));
|
||||||
Assert.assertNull(data.getRootNode().getChildren().get("foxtrot"));
|
Assert.assertNull(data.getRootNode().getChildren().get("foxtrot"));
|
||||||
|
Assert.assertEquals(data.getFullKeys().size(), numOfTranslations - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRecurseDeleteNested() {
|
public void testOverwrite() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
this.addTranslations(data);
|
|
||||||
|
|
||||||
data.setTranslation("foxtrot.super.long.key", null);
|
|
||||||
|
|
||||||
Assert.assertNull(data.getTranslation("foxtrot.super.long.key"));
|
|
||||||
Assert.assertNull(data.getRootNode().getChildren().get("foxtrot"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOverwriteNonNested() {
|
|
||||||
TranslationData data = new TranslationData(true, false);
|
|
||||||
|
|
||||||
Translation before = new Translation("en", "before");
|
Translation before = new Translation("en", "before");
|
||||||
Translation after = new Translation("en", "after");
|
Translation after = new Translation("en", "after");
|
||||||
|
|
||||||
data.setTranslation("alpha", before);
|
data.setTranslation(KeyPath.of("alpha"), before);
|
||||||
data.setTranslation("nested.alpha", before);
|
data.setTranslation(KeyPath.of("nested.alpha"), before);
|
||||||
data.setTranslation("nested.long.bravo", before);
|
data.setTranslation(KeyPath.of("nested.long.bravo"), before);
|
||||||
|
data.setTranslation(KeyPath.of("beta"), before);
|
||||||
|
data.setTranslation(KeyPath.of("nested", "alpha"), before);
|
||||||
|
data.setTranslation(KeyPath.of("nested", "long", "bravo"), before);
|
||||||
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), before);
|
Assert.assertEquals(data.getTranslation(KeyPath.of("alpha")), before);
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), before);
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested.alpha")), before);
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), before);
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested.long.bravo")), before);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("beta")), before);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested", "alpha")), before);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested", "long", "bravo")), before);
|
||||||
|
|
||||||
data.setTranslation("alpha", after);
|
data.setTranslation(KeyPath.of("alpha"), after);
|
||||||
data.setTranslation("nested.alpha", after);
|
data.setTranslation(KeyPath.of("nested.alpha"), after);
|
||||||
data.setTranslation("nested.long.bravo", after);
|
data.setTranslation(KeyPath.of("nested.long.bravo"), after);
|
||||||
|
data.setTranslation(KeyPath.of("beta"), after);
|
||||||
|
data.setTranslation(KeyPath.of("nested", "alpha"), after);
|
||||||
|
data.setTranslation(KeyPath.of("nested", "long", "bravo"), after);
|
||||||
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), after);
|
Assert.assertEquals(data.getTranslation(KeyPath.of("alpha")), after);
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), after);
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested.alpha")), after);
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), after);
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested.long.bravo")), after);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("beta")), after);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested", "alpha")), after);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("nested", "long", "bravo")), after);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOverwriteNested() {
|
public void testTransformRecursively() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
|
|
||||||
Translation before = new Translation("en", "before");
|
data.setTranslation(KeyPath.of("alpha.nested.key"), translation);
|
||||||
Translation after = new Translation("en", "after");
|
data.setTranslation(KeyPath.of("alpha.other"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("bravo"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("alpha", "nested", "key"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("alpha", "other"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("charlie"), translation);
|
||||||
|
|
||||||
data.setTranslation("alpha", before);
|
Assert.assertEquals(6, data.getFullKeys().size());
|
||||||
data.setTranslation("nested.alpha", before);
|
|
||||||
data.setTranslation("nested.long.bravo", before);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), before);
|
data.setTranslation(KeyPath.of("alpha.nested"), translation);
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), before);
|
data.setTranslation(KeyPath.of("alpha.other.new"), translation);
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), before);
|
data.setTranslation(KeyPath.of("bravo"), null);
|
||||||
|
data.setTranslation(KeyPath.of("alpha", "nested"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("alpha", "other", "new"), translation);
|
||||||
|
data.setTranslation(KeyPath.of("charlie"), null);
|
||||||
|
|
||||||
data.setTranslation("alpha", after);
|
Assert.assertEquals(6, data.getFullKeys().size());
|
||||||
data.setTranslation("nested.alpha", after);
|
|
||||||
data.setTranslation("nested.long.bravo", after);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), after);
|
Assert.assertNotNull(data.getTranslation(KeyPath.of("alpha.nested.key")));
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), after);
|
Assert.assertNotNull(data.getTranslation(KeyPath.of("alpha.other")));
|
||||||
Assert.assertEquals(data.getTranslation("alpha"), after);
|
Assert.assertNull(data.getTranslation(KeyPath.of("bravo")));
|
||||||
}
|
Assert.assertEquals(data.getTranslation(KeyPath.of("alpha.nested")), translation);
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("alpha.other.new")), translation);
|
||||||
|
|
||||||
@Test
|
Assert.assertNull(data.getTranslation(KeyPath.of("alpha", "nested", "key")));
|
||||||
public void testRecurseTransformNested() {
|
Assert.assertNull(data.getTranslation(KeyPath.of("alpha", "other")));
|
||||||
TranslationData data = new TranslationData(true, true);
|
Assert.assertNull(data.getTranslation(KeyPath.of("charlie")));
|
||||||
|
Assert.assertEquals(data.getTranslation(KeyPath.of("alpha", "nested")), translation);
|
||||||
Translation value = new Translation("en", "test");
|
Assert.assertEquals(data.getTranslation(KeyPath.of("alpha", "other", "new")), translation);
|
||||||
|
|
||||||
data.setTranslation("alpha.nested.key", value);
|
|
||||||
data.setTranslation("alpha.other", value);
|
|
||||||
data.setTranslation("bravo", value);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 3);
|
|
||||||
|
|
||||||
data.setTranslation("alpha.nested", value);
|
|
||||||
data.setTranslation("alpha.other.new", value);
|
|
||||||
data.setTranslation("bravo", null);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 2);
|
|
||||||
Assert.assertNull(data.getTranslation("alpha.nested.key"));
|
|
||||||
Assert.assertNull(data.getTranslation("alpha.other"));
|
|
||||||
Assert.assertNull(data.getTranslation("bravo"));
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha.nested"), value);
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha.other.new"), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRecurseTransformNonNested() {
|
|
||||||
TranslationData data = new TranslationData(true, false);
|
|
||||||
|
|
||||||
Translation value = new Translation("en", "test");
|
|
||||||
|
|
||||||
data.setTranslation("alpha.nested.key", value);
|
|
||||||
data.setTranslation("alpha.other", value);
|
|
||||||
data.setTranslation("bravo", value);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 3);
|
|
||||||
|
|
||||||
data.setTranslation("alpha.nested", value);
|
|
||||||
data.setTranslation("alpha.other.new", value);
|
|
||||||
data.setTranslation("bravo", null);
|
|
||||||
|
|
||||||
Assert.assertEquals(data.getFullKeys().size(), 4);
|
|
||||||
Assert.assertNull(data.getTranslation("bravo"));
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha.nested.key"), value);
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha.other"), value);
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha.nested"), value);
|
|
||||||
Assert.assertEquals(data.getTranslation("alpha.other.new"), value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ import com.google.gson.JsonPrimitive;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.io.json.JsonArrayMapper;
|
import de.marhali.easyi18n.io.json.JsonArrayMapper;
|
||||||
import de.marhali.easyi18n.io.json.JsonMapper;
|
import de.marhali.easyi18n.io.json.JsonMapper;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
@ -16,7 +17,7 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link de.marhali.easyi18n.io.json.JsonMapper}
|
* Unit tests for {@link JsonMapper}.
|
||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class JsonMapperTest extends AbstractMapperTest {
|
public class JsonMapperTest extends AbstractMapperTest {
|
||||||
@ -28,7 +29,7 @@ public class JsonMapperTest extends AbstractMapperTest {
|
|||||||
input.add("alpha", new JsonPrimitive("test"));
|
input.add("alpha", new JsonPrimitive("test"));
|
||||||
input.add("bravo", new JsonPrimitive("test"));
|
input.add("bravo", new JsonPrimitive("test"));
|
||||||
|
|
||||||
TranslationData data = new TranslationData(false, true);
|
TranslationData data = new TranslationData(false);
|
||||||
JsonMapper.read("en", input, data.getRootNode());
|
JsonMapper.read("en", input, data.getRootNode());
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
@ -45,7 +46,7 @@ public class JsonMapperTest extends AbstractMapperTest {
|
|||||||
input.add("alpha", new JsonPrimitive("test"));
|
input.add("alpha", new JsonPrimitive("test"));
|
||||||
input.add("bravo", new JsonPrimitive("test"));
|
input.add("bravo", new JsonPrimitive("test"));
|
||||||
|
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
JsonMapper.read("en", input, data.getRootNode());
|
JsonMapper.read("en", input, data.getRootNode());
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
@ -57,9 +58,9 @@ public class JsonMapperTest extends AbstractMapperTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testArrays() {
|
public void testArrays() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("simple", create(arraySimple));
|
data.setTranslation(KeyPath.of("simple"), create(arraySimple));
|
||||||
data.setTranslation("escaped", create(arrayEscaped));
|
data.setTranslation(KeyPath.of("escaped"), create(arrayEscaped));
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
JsonMapper.write("en", output, data.getRootNode());
|
JsonMapper.write("en", output, data.getRootNode());
|
||||||
@ -69,81 +70,82 @@ public class JsonMapperTest extends AbstractMapperTest {
|
|||||||
Assert.assertTrue(output.get("escaped").isJsonArray());
|
Assert.assertTrue(output.get("escaped").isJsonArray());
|
||||||
Assert.assertEquals(arrayEscaped, StringEscapeUtils.unescapeJava(JsonArrayMapper.read(output.get("escaped").getAsJsonArray())));
|
Assert.assertEquals(arrayEscaped, StringEscapeUtils.unescapeJava(JsonArrayMapper.read(output.get("escaped").getAsJsonArray())));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
JsonMapper.read("en", output, input.getRootNode());
|
JsonMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertTrue(JsonArrayMapper.isArray(input.getTranslation("simple").get("en")));
|
Assert.assertTrue(JsonArrayMapper.isArray(input.getTranslation(KeyPath.of("simple")).get("en")));
|
||||||
Assert.assertTrue(JsonArrayMapper.isArray(input.getTranslation("escaped").get("en")));
|
Assert.assertTrue(JsonArrayMapper.isArray(input.getTranslation(KeyPath.of("escaped")).get("en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testSpecialCharacters() {
|
public void testSpecialCharacters() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("chars", create(specialCharacters));
|
data.setTranslation(KeyPath.of("chars"), create(specialCharacters));
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
JsonMapper.write("en", output, data.getRootNode());
|
JsonMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(specialCharacters, output.get("chars").getAsString());
|
Assert.assertEquals(specialCharacters, output.get("chars").getAsString());
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
JsonMapper.read("en", output, input.getRootNode());
|
JsonMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(specialCharacters, StringEscapeUtils.unescapeJava(input.getTranslation("chars").get("en")));
|
Assert.assertEquals(specialCharacters,
|
||||||
|
StringEscapeUtils.unescapeJava(input.getTranslation(KeyPath.of("chars")).get("en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNestedKeys() {
|
public void testNestedKeys() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("nested.key.section", create("test"));
|
data.setTranslation(KeyPath.of("nested", "key", "section"), create("test"));
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
JsonMapper.write("en", output, data.getRootNode());
|
JsonMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("test", output.getAsJsonObject("nested").getAsJsonObject("key").get("section").getAsString());
|
Assert.assertEquals("test", output.getAsJsonObject("nested").getAsJsonObject("key").get("section").getAsString());
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
JsonMapper.read("en", output, input.getRootNode());
|
JsonMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("test", input.getTranslation("nested.key.section").get("en"));
|
Assert.assertEquals("test", input.getTranslation(KeyPath.of("nested", "key", "section")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNonNestedKeys() {
|
public void testNonNestedKeys() {
|
||||||
TranslationData data = new TranslationData(true, false);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("long.key.with.many.sections", create("test"));
|
data.setTranslation(KeyPath.of("long.key.with.many.sections"), create("test"));
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
JsonMapper.write("en", output, data.getRootNode());
|
JsonMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertTrue(output.has("long.key.with.many.sections"));
|
Assert.assertTrue(output.has("long.key.with.many.sections"));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, false);
|
TranslationData input = new TranslationData(true);
|
||||||
JsonMapper.read("en", output, input.getRootNode());
|
JsonMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("test", input.getTranslation("long.key.with.many.sections").get("en"));
|
Assert.assertEquals("test", input.getTranslation(KeyPath.of("long.key.with.many.sections")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testLeadingSpace() {
|
public void testLeadingSpace() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("space", create(leadingSpace));
|
data.setTranslation(KeyPath.of("space"), create(leadingSpace));
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
JsonMapper.write("en", output, data.getRootNode());
|
JsonMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(leadingSpace, output.get("space").getAsString());
|
Assert.assertEquals(leadingSpace, output.get("space").getAsString());
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
JsonMapper.read("en", output, input.getRootNode());
|
JsonMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(leadingSpace, input.getTranslation("space").get("en"));
|
Assert.assertEquals(leadingSpace, input.getTranslation(KeyPath.of("space")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNumbers() {
|
public void testNumbers() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("numbered", create("15000"));
|
data.setTranslation(KeyPath.of("numbered"), create("15000"));
|
||||||
|
|
||||||
JsonObject output = new JsonObject();
|
JsonObject output = new JsonObject();
|
||||||
JsonMapper.write("en", output, data.getRootNode());
|
JsonMapper.write("en", output, data.getRootNode());
|
||||||
@ -154,6 +156,6 @@ public class JsonMapperTest extends AbstractMapperTest {
|
|||||||
input.addProperty("numbered", 143.23);
|
input.addProperty("numbered", 143.23);
|
||||||
JsonMapper.read("en", input, data.getRootNode());
|
JsonMapper.read("en", input, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("143.23", data.getTranslation("numbered").get("en"));
|
Assert.assertEquals("143.23", data.getTranslation(KeyPath.of("numbered")).get("en"));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package de.marhali.easyi18n.mapper;
|
|||||||
import de.marhali.easyi18n.io.properties.PropertiesArrayMapper;
|
import de.marhali.easyi18n.io.properties.PropertiesArrayMapper;
|
||||||
import de.marhali.easyi18n.io.properties.PropertiesMapper;
|
import de.marhali.easyi18n.io.properties.PropertiesMapper;
|
||||||
import de.marhali.easyi18n.io.properties.SortableProperties;
|
import de.marhali.easyi18n.io.properties.SortableProperties;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
@ -11,7 +12,7 @@ import org.junit.Assert;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link de.marhali.easyi18n.io.properties.PropertiesMapper}
|
* Unit tests for {@link PropertiesMapper}.
|
||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class PropertiesMapperTest extends AbstractMapperTest {
|
public class PropertiesMapperTest extends AbstractMapperTest {
|
||||||
@ -23,7 +24,7 @@ public class PropertiesMapperTest extends AbstractMapperTest {
|
|||||||
input.setProperty("alpha", "test");
|
input.setProperty("alpha", "test");
|
||||||
input.setProperty("bravo", "test");
|
input.setProperty("bravo", "test");
|
||||||
|
|
||||||
TranslationData data = new TranslationData(false, true);
|
TranslationData data = new TranslationData(false);
|
||||||
PropertiesMapper.read("en", input, data);
|
PropertiesMapper.read("en", input, data);
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(false);
|
SortableProperties output = new SortableProperties(false);
|
||||||
@ -40,7 +41,7 @@ public class PropertiesMapperTest extends AbstractMapperTest {
|
|||||||
input.setProperty("alpha", "test");
|
input.setProperty("alpha", "test");
|
||||||
input.setProperty("bravo", "test");
|
input.setProperty("bravo", "test");
|
||||||
|
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
PropertiesMapper.read("en", input, data);
|
PropertiesMapper.read("en", input, data);
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
@ -52,9 +53,9 @@ public class PropertiesMapperTest extends AbstractMapperTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testArrays() {
|
public void testArrays() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("simple", create(arraySimple));
|
data.setTranslation(KeyPath.of("simple"), create(arraySimple));
|
||||||
data.setTranslation("escaped", create(arrayEscaped));
|
data.setTranslation(KeyPath.of("escaped"), create(arrayEscaped));
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
PropertiesMapper.write("en", output, data);
|
PropertiesMapper.write("en", output, data);
|
||||||
@ -64,83 +65,84 @@ public class PropertiesMapperTest extends AbstractMapperTest {
|
|||||||
Assert.assertTrue(output.get("escaped") instanceof String[]);
|
Assert.assertTrue(output.get("escaped") instanceof String[]);
|
||||||
Assert.assertEquals(arrayEscaped, StringEscapeUtils.unescapeJava(PropertiesArrayMapper.read((String[]) output.get("escaped"))));
|
Assert.assertEquals(arrayEscaped, StringEscapeUtils.unescapeJava(PropertiesArrayMapper.read((String[]) output.get("escaped"))));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
PropertiesMapper.read("en", output, input);
|
PropertiesMapper.read("en", output, input);
|
||||||
|
|
||||||
Assert.assertTrue(PropertiesArrayMapper.isArray(input.getTranslation("simple").get("en")));
|
Assert.assertTrue(PropertiesArrayMapper.isArray(input.getTranslation(KeyPath.of("simple")).get("en")));
|
||||||
Assert.assertTrue(PropertiesArrayMapper.isArray(input.getTranslation("escaped").get("en")));
|
Assert.assertTrue(PropertiesArrayMapper.isArray(input.getTranslation(KeyPath.of("escaped")).get("en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testSpecialCharacters() {
|
public void testSpecialCharacters() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("chars", create(specialCharacters));
|
data.setTranslation(KeyPath.of("chars"), create(specialCharacters));
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
PropertiesMapper.write("en", output, data);
|
PropertiesMapper.write("en", output, data);
|
||||||
|
|
||||||
Assert.assertEquals(specialCharacters, output.get("chars"));
|
Assert.assertEquals(specialCharacters, output.get("chars"));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
PropertiesMapper.read("en", output, input);
|
PropertiesMapper.read("en", output, input);
|
||||||
|
|
||||||
Assert.assertEquals(specialCharacters, StringEscapeUtils.unescapeJava(input.getTranslation("chars").get("en")));
|
Assert.assertEquals(specialCharacters, StringEscapeUtils.unescapeJava(input.getTranslation(KeyPath.of("chars")).get("en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNestedKeys() {
|
public void testNestedKeys() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("nested.key.sections", create("test"));
|
data.setTranslation(KeyPath.of("nested", "key", "sections"), create("test"));
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
PropertiesMapper.write("en", output, data);
|
PropertiesMapper.write("en", output, data);
|
||||||
|
|
||||||
Assert.assertEquals("test", output.get("nested.key.sections"));
|
Assert.assertEquals("test", output.get("nested.key.sections"));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
PropertiesMapper.read("en", output, input);
|
PropertiesMapper.read("en", output, input);
|
||||||
|
|
||||||
|
System.out.println(input);
|
||||||
|
|
||||||
Assert.assertTrue(input.getRootNode().getChildren().containsKey("nested"));
|
Assert.assertTrue(input.getRootNode().getChildren().containsKey("nested"));
|
||||||
Assert.assertEquals("test", input.getTranslation("nested.key.sections").get("en"));
|
Assert.assertEquals("test", input.getTranslation(KeyPath.of("nested", "key", "sections")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNonNestedKeys() {
|
public void testNonNestedKeys() { // Note: Key nesting is not supported in properties file.
|
||||||
TranslationData data = new TranslationData(true, false);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("long.key.with.many.sections", create("test"));
|
data.setTranslation(KeyPath.of("long.key.with.many.sections"), create("test"));
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
PropertiesMapper.write("en", output, data);
|
PropertiesMapper.write("en", output, data);
|
||||||
|
|
||||||
Assert.assertNotNull(output.get("long.key.with.many.sections"));
|
Assert.assertNotNull(output.get("long.key.with.many.sections"));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, false);
|
TranslationData input = new TranslationData(true);
|
||||||
PropertiesMapper.read("en", output, input);
|
PropertiesMapper.read("en", output, input);
|
||||||
|
|
||||||
Assert.assertEquals("test", input.getRootNode().getChildren()
|
Assert.assertEquals("test", input.getTranslation(KeyPath.of("long", "key", "with", "many", "sections")).get("en"));
|
||||||
.get("long.key.with.many.sections").getValue().get("en"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testLeadingSpace() {
|
public void testLeadingSpace() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("space", create(leadingSpace));
|
data.setTranslation(KeyPath.of("space"), create(leadingSpace));
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
PropertiesMapper.write("en", output, data);
|
PropertiesMapper.write("en", output, data);
|
||||||
|
|
||||||
Assert.assertEquals(leadingSpace, output.get("space"));
|
Assert.assertEquals(leadingSpace, output.get("space"));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
PropertiesMapper.read("en", output, input);
|
PropertiesMapper.read("en", output, input);
|
||||||
|
|
||||||
Assert.assertEquals(leadingSpace, input.getTranslation("space").get("en"));
|
Assert.assertEquals(leadingSpace, input.getTranslation(KeyPath.of("space")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNumbers() {
|
public void testNumbers() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("numbered", create("15000"));
|
data.setTranslation(KeyPath.of("numbered"), create("15000"));
|
||||||
|
|
||||||
SortableProperties output = new SortableProperties(true);
|
SortableProperties output = new SortableProperties(true);
|
||||||
PropertiesMapper.write("en", output, data);
|
PropertiesMapper.write("en", output, data);
|
||||||
@ -151,6 +153,6 @@ public class PropertiesMapperTest extends AbstractMapperTest {
|
|||||||
input.put("numbered", 143.23);
|
input.put("numbered", 143.23);
|
||||||
PropertiesMapper.read("en", input, data);
|
PropertiesMapper.read("en", input, data);
|
||||||
|
|
||||||
Assert.assertEquals("143.23", data.getTranslation("numbered").get("en"));
|
Assert.assertEquals("143.23", data.getTranslation(KeyPath.of("numbered")).get("en"));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package de.marhali.easyi18n.mapper;
|
|||||||
|
|
||||||
import de.marhali.easyi18n.io.yaml.YamlArrayMapper;
|
import de.marhali.easyi18n.io.yaml.YamlArrayMapper;
|
||||||
import de.marhali.easyi18n.io.yaml.YamlMapper;
|
import de.marhali.easyi18n.io.yaml.YamlMapper;
|
||||||
|
import de.marhali.easyi18n.model.KeyPath;
|
||||||
import de.marhali.easyi18n.model.TranslationData;
|
import de.marhali.easyi18n.model.TranslationData;
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang.StringEscapeUtils;
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link de.marhali.easyi18n.io.yaml.YamlMapper}
|
* Unit tests for {@link YamlMapper}.
|
||||||
* @author marhali
|
* @author marhali
|
||||||
*/
|
*/
|
||||||
public class YamlMapperTest extends AbstractMapperTest {
|
public class YamlMapperTest extends AbstractMapperTest {
|
||||||
@ -27,7 +28,7 @@ public class YamlMapperTest extends AbstractMapperTest {
|
|||||||
input.set("alpha", "test");
|
input.set("alpha", "test");
|
||||||
input.set("bravo", "test");
|
input.set("bravo", "test");
|
||||||
|
|
||||||
TranslationData data = new TranslationData(false, true);
|
TranslationData data = new TranslationData(false);
|
||||||
YamlMapper.read("en", input, data.getRootNode());
|
YamlMapper.read("en", input, data.getRootNode());
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
@ -44,7 +45,7 @@ public class YamlMapperTest extends AbstractMapperTest {
|
|||||||
input.set("alpha", "test");
|
input.set("alpha", "test");
|
||||||
input.set("bravo", "test");
|
input.set("bravo", "test");
|
||||||
|
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
YamlMapper.read("en", input, data.getRootNode());
|
YamlMapper.read("en", input, data.getRootNode());
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
@ -56,9 +57,9 @@ public class YamlMapperTest extends AbstractMapperTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testArrays() {
|
public void testArrays() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("simple", create(arraySimple));
|
data.setTranslation(KeyPath.of("simple"), create(arraySimple));
|
||||||
data.setTranslation("escaped", create(arrayEscaped));
|
data.setTranslation(KeyPath.of("escaped"), create(arrayEscaped));
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
YamlMapper.write("en", output, data.getRootNode());
|
YamlMapper.write("en", output, data.getRootNode());
|
||||||
@ -68,81 +69,82 @@ public class YamlMapperTest extends AbstractMapperTest {
|
|||||||
Assert.assertTrue(output.isList("escaped"));
|
Assert.assertTrue(output.isList("escaped"));
|
||||||
Assert.assertEquals(arrayEscaped, StringEscapeUtils.unescapeJava(YamlArrayMapper.read(output.getList("escaped").get())));
|
Assert.assertEquals(arrayEscaped, StringEscapeUtils.unescapeJava(YamlArrayMapper.read(output.getList("escaped").get())));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
YamlMapper.read("en", output, input.getRootNode());
|
YamlMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertTrue(YamlArrayMapper.isArray(input.getTranslation("simple").get("en")));
|
Assert.assertTrue(YamlArrayMapper.isArray(input.getTranslation(KeyPath.of("simple")).get("en")));
|
||||||
Assert.assertTrue(YamlArrayMapper.isArray(input.getTranslation("escaped").get("en")));
|
Assert.assertTrue(YamlArrayMapper.isArray(input.getTranslation(KeyPath.of("escaped")).get("en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testSpecialCharacters() {
|
public void testSpecialCharacters() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("chars", create(specialCharacters));
|
data.setTranslation(KeyPath.of("chars"), create(specialCharacters));
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
YamlMapper.write("en", output, data.getRootNode());
|
YamlMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(specialCharacters, output.getString("chars").get());
|
Assert.assertEquals(specialCharacters, output.getString("chars").get());
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
YamlMapper.read("en", output, input.getRootNode());
|
YamlMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(specialCharacters, StringEscapeUtils.unescapeJava(input.getTranslation("chars").get("en")));
|
Assert.assertEquals(specialCharacters,
|
||||||
|
StringEscapeUtils.unescapeJava(input.getTranslation(KeyPath.of("chars")).get("en")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNestedKeys() {
|
public void testNestedKeys() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("nested.key.section", create("test"));
|
data.setTranslation(KeyPath.of("nested", "key", "section"), create("test"));
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
YamlMapper.write("en", output, data.getRootNode());
|
YamlMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("test", output.getString("nested.key.section").get());
|
Assert.assertEquals("test", output.getString("nested.key.section").get());
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
YamlMapper.read("en", output, input.getRootNode());
|
YamlMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("test", input.getTranslation("nested.key.section").get("en"));
|
Assert.assertEquals("test", input.getTranslation(KeyPath.of("nested", "key", "section")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNonNestedKeys() {
|
public void testNonNestedKeys() {
|
||||||
TranslationData data = new TranslationData(true, false);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("long.key.with.many.sections", create("test"));
|
data.setTranslation(KeyPath.of("long.key.with.many.sections"), create("test"));
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
YamlMapper.write("en", output, data.getRootNode());
|
YamlMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertTrue(output.getKeys().contains("long.key.with.many.sections"));
|
Assert.assertTrue(output.getKeys().contains("long.key.with.many.sections"));
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, false);
|
TranslationData input = new TranslationData(true);
|
||||||
YamlMapper.read("en", output, input.getRootNode());
|
YamlMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("test", input.getTranslation("long.key.with.many.sections").get("en"));
|
Assert.assertEquals("test", input.getTranslation(KeyPath.of("long.key.with.many.sections")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testLeadingSpace() {
|
public void testLeadingSpace() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("space", create(leadingSpace));
|
data.setTranslation(KeyPath.of("space"), create(leadingSpace));
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
YamlMapper.write("en", output, data.getRootNode());
|
YamlMapper.write("en", output, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(leadingSpace, output.getString("space").get());
|
Assert.assertEquals(leadingSpace, output.getString("space").get());
|
||||||
|
|
||||||
TranslationData input = new TranslationData(true, true);
|
TranslationData input = new TranslationData(true);
|
||||||
YamlMapper.read("en", output, input.getRootNode());
|
YamlMapper.read("en", output, input.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals(leadingSpace, input.getTranslation("space").get("en"));
|
Assert.assertEquals(leadingSpace, input.getTranslation(KeyPath.of("space")).get("en"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void testNumbers() {
|
public void testNumbers() {
|
||||||
TranslationData data = new TranslationData(true, true);
|
TranslationData data = new TranslationData(true);
|
||||||
data.setTranslation("numbered", create("15000"));
|
data.setTranslation(KeyPath.of("numbered"), create("15000"));
|
||||||
|
|
||||||
Section output = new MapSection();
|
Section output = new MapSection();
|
||||||
YamlMapper.write("en", output, data.getRootNode());
|
YamlMapper.write("en", output, data.getRootNode());
|
||||||
@ -153,6 +155,6 @@ public class YamlMapperTest extends AbstractMapperTest {
|
|||||||
input.set("numbered", 143.23);
|
input.set("numbered", 143.23);
|
||||||
YamlMapper.read("en", input, data.getRootNode());
|
YamlMapper.read("en", input, data.getRootNode());
|
||||||
|
|
||||||
Assert.assertEquals("143.23", data.getTranslation("numbered").get("en"));
|
Assert.assertEquals("143.23", data.getTranslation(KeyPath.of("numbered")).get("en"));
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user