Add basic support for modularized / splitted json files | Fixes Issue #4
This commit is contained in:
parent
895bdbbe7f
commit
5f1d96d91d
@ -8,6 +8,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
|||||||
import de.marhali.easyi18n.io.TranslatorIO;
|
import de.marhali.easyi18n.io.TranslatorIO;
|
||||||
import de.marhali.easyi18n.model.LocalizedNode;
|
import de.marhali.easyi18n.model.LocalizedNode;
|
||||||
import de.marhali.easyi18n.model.Translations;
|
import de.marhali.easyi18n.model.Translations;
|
||||||
|
import de.marhali.easyi18n.util.JsonUtil;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -44,8 +45,11 @@ public class JsonTranslatorIO implements TranslatorIO {
|
|||||||
try {
|
try {
|
||||||
for(VirtualFile file : files) {
|
for(VirtualFile file : files) {
|
||||||
locales.add(file.getNameWithoutExtension());
|
locales.add(file.getNameWithoutExtension());
|
||||||
JsonObject tree = JsonParser.parseReader(new InputStreamReader(file.getInputStream(), file.getCharset())).getAsJsonObject();
|
|
||||||
readTree(file.getNameWithoutExtension(), tree, nodes);
|
JsonObject tree = JsonParser.parseReader(new InputStreamReader(file.getInputStream(),
|
||||||
|
file.getCharset())).getAsJsonObject();
|
||||||
|
|
||||||
|
JsonUtil.readTree(file.getNameWithoutExtension(), tree, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.accept(new Translations(locales, nodes));
|
callback.accept(new Translations(locales, nodes));
|
||||||
@ -65,13 +69,16 @@ public class JsonTranslatorIO implements TranslatorIO {
|
|||||||
try {
|
try {
|
||||||
for(String locale : translations.getLocales()) {
|
for(String locale : translations.getLocales()) {
|
||||||
JsonObject content = new JsonObject();
|
JsonObject content = new JsonObject();
|
||||||
writeTree(locale, content, translations.getNodes());
|
JsonUtil.writeTree(locale, content, translations.getNodes());
|
||||||
//JsonElement content = writeTree(locale, new JsonObject(), translations.getNodes());
|
|
||||||
|
|
||||||
String fullPath = directoryPath + "/" + locale + "." + FILE_EXTENSION;
|
String fullPath = directoryPath + "/" + locale + "." + FILE_EXTENSION;
|
||||||
VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(new File(fullPath));
|
File file = new File(fullPath);
|
||||||
|
boolean created = file.createNewFile();
|
||||||
|
|
||||||
file.setBinaryContent(gson.toJson(content).getBytes(file.getCharset()));
|
VirtualFile vf = created ? LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
|
||||||
|
: LocalFileSystem.getInstance().findFileByIoFile(file);
|
||||||
|
|
||||||
|
vf.setBinaryContent(gson.toJson(content).getBytes(vf.getCharset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Successfully saved
|
// Successfully saved
|
||||||
@ -83,57 +90,4 @@ public class JsonTranslatorIO implements TranslatorIO {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeTree(String locale, JsonObject parent, LocalizedNode node) {
|
|
||||||
if(node.isLeaf() && !node.getKey().equals(LocalizedNode.ROOT_KEY)) {
|
|
||||||
if(node.getValue().get(locale) != null) {
|
|
||||||
parent.add(node.getKey(), new JsonPrimitive(node.getValue().get(locale)));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
for(LocalizedNode children : node.getChildren()) {
|
|
||||||
if(children.isLeaf()) {
|
|
||||||
writeTree(locale, parent, children);
|
|
||||||
} else {
|
|
||||||
JsonObject childrenJson = new JsonObject();
|
|
||||||
writeTree(locale, childrenJson, children);
|
|
||||||
if(childrenJson.size() > 0) {
|
|
||||||
parent.add(children.getKey(), childrenJson);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readTree(String locale, JsonObject json, LocalizedNode data) {
|
|
||||||
for(Map.Entry<String, JsonElement> entry : json.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Try to go one level deeper
|
|
||||||
JsonObject childObject = entry.getValue().getAsJsonObject();
|
|
||||||
|
|
||||||
LocalizedNode childrenNode = data.getChildren(key);
|
|
||||||
|
|
||||||
if(childrenNode == null) {
|
|
||||||
childrenNode = new LocalizedNode(key, new ArrayList<>());
|
|
||||||
data.addChildren(childrenNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
readTree(locale, childObject, childrenNode);
|
|
||||||
|
|
||||||
} catch(IllegalStateException e) { // Reached end for this node
|
|
||||||
LocalizedNode leafNode = data.getChildren(key);
|
|
||||||
|
|
||||||
if(leafNode == null) {
|
|
||||||
leafNode = new LocalizedNode(key, new HashMap<>());
|
|
||||||
data.addChildren(leafNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> messages = leafNode.getValue();
|
|
||||||
messages.put(locale, entry.getValue().getAsString());
|
|
||||||
leafNode.setValue(messages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package de.marhali.easyi18n.io.implementation;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.io.TranslatorIO;
|
||||||
|
import de.marhali.easyi18n.model.LocalizedNode;
|
||||||
|
import de.marhali.easyi18n.model.Translations;
|
||||||
|
import de.marhali.easyi18n.util.JsonUtil;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO operations for splitted / modularized json files. Each locale can have multiple translation files.
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class ModularizedJsonTranslatorIO implements TranslatorIO {
|
||||||
|
|
||||||
|
private static final String FILE_EXTENSION = "json";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(@NotNull String directoryPath, @NotNull Consumer<Translations> callback) {
|
||||||
|
ApplicationManager.getApplication().saveAll(); // Save opened files (required if new locales were added)
|
||||||
|
|
||||||
|
ApplicationManager.getApplication().runReadAction(() -> {
|
||||||
|
VirtualFile directory = LocalFileSystem.getInstance().findFileByIoFile(new File(directoryPath));
|
||||||
|
|
||||||
|
if(directory == null || directory.getChildren() == null) {
|
||||||
|
throw new IllegalArgumentException("Specified folder is invalid (" + directoryPath + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualFile[] localeDirectories = directory.getChildren();
|
||||||
|
|
||||||
|
List<String> locales = new ArrayList<>();
|
||||||
|
LocalizedNode nodes = new LocalizedNode(LocalizedNode.ROOT_KEY, new ArrayList<>());
|
||||||
|
|
||||||
|
try {
|
||||||
|
for(VirtualFile localeDir : localeDirectories) {
|
||||||
|
String locale = localeDir.getName();
|
||||||
|
locales.add(locale);
|
||||||
|
|
||||||
|
// Read all json modules
|
||||||
|
for(VirtualFile module : localeDir.getChildren()) {
|
||||||
|
JsonObject tree = JsonParser.parseReader(new InputStreamReader(module.getInputStream(),
|
||||||
|
module.getCharset())).getAsJsonObject();
|
||||||
|
|
||||||
|
String moduleName = module.getNameWithoutExtension();
|
||||||
|
LocalizedNode moduleNode = nodes.getChildren(moduleName);
|
||||||
|
|
||||||
|
if(moduleNode == null) { // Create module / sub node
|
||||||
|
moduleNode = new LocalizedNode(moduleName, new ArrayList<>());
|
||||||
|
nodes.addChildren(moduleNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonUtil.readTree(locale, tree, moduleNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.accept(new Translations(locales, nodes));
|
||||||
|
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(@NotNull Translations translations, @NotNull String directoryPath, @NotNull Consumer<Boolean> callback) {
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||||
|
try {
|
||||||
|
for(String locale : translations.getLocales()) {
|
||||||
|
// Use top level children as modules
|
||||||
|
for (LocalizedNode module : translations.getNodes().getChildren()) {
|
||||||
|
JsonObject content = new JsonObject();
|
||||||
|
JsonUtil.writeTree(locale, content, module);
|
||||||
|
|
||||||
|
String fullPath = directoryPath + "/" + locale + "/" + module.getKey() + "." + FILE_EXTENSION;
|
||||||
|
File file = new File(fullPath);
|
||||||
|
boolean created = file.createNewFile();
|
||||||
|
|
||||||
|
VirtualFile vf = created ? LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
|
||||||
|
: LocalFileSystem.getInstance().findFileByIoFile(file);
|
||||||
|
|
||||||
|
vf.setBinaryContent(gson.toJson(content).getBytes(vf.getCharset()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully saved
|
||||||
|
callback.accept(true);
|
||||||
|
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
callback.accept(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package de.marhali.easyi18n.util;
|
|||||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import de.marhali.easyi18n.io.implementation.JsonTranslatorIO;
|
import de.marhali.easyi18n.io.implementation.JsonTranslatorIO;
|
||||||
|
import de.marhali.easyi18n.io.implementation.ModularizedJsonTranslatorIO;
|
||||||
import de.marhali.easyi18n.io.implementation.PropertiesTranslatorIO;
|
import de.marhali.easyi18n.io.implementation.PropertiesTranslatorIO;
|
||||||
import de.marhali.easyi18n.io.TranslatorIO;
|
import de.marhali.easyi18n.io.TranslatorIO;
|
||||||
|
|
||||||
@ -36,6 +37,11 @@ public class IOUtil {
|
|||||||
throw new IllegalStateException("Could not determine i18n format. At least one locale file must be defined");
|
throw new IllegalStateException("Could not determine i18n format. At least one locale file must be defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split files - Should be always JSON
|
||||||
|
if(any.get().isDirectory()) {
|
||||||
|
return new ModularizedJsonTranslatorIO();
|
||||||
|
}
|
||||||
|
|
||||||
switch (any.get().getFileType().getDefaultExtension().toLowerCase()) {
|
switch (any.get().getFileType().getDefaultExtension().toLowerCase()) {
|
||||||
case "json":
|
case "json":
|
||||||
return new JsonTranslatorIO();
|
return new JsonTranslatorIO();
|
||||||
|
83
src/main/java/de/marhali/easyi18n/util/JsonUtil.java
Normal file
83
src/main/java/de/marhali/easyi18n/util/JsonUtil.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package de.marhali.easyi18n.util;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
|
import de.marhali.easyi18n.model.LocalizedNode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json tree utilities for writing and reading {@link LocalizedNode}'s
|
||||||
|
* @author marhali
|
||||||
|
*/
|
||||||
|
public class JsonUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} based from an {@link LocalizedNode}
|
||||||
|
* @param locale Current locale
|
||||||
|
* @param parent Parent json. Can be an entire json document
|
||||||
|
* @param node The node instance
|
||||||
|
*/
|
||||||
|
public static void writeTree(String locale, JsonObject parent, LocalizedNode node) {
|
||||||
|
if(node.isLeaf() && !node.getKey().equals(LocalizedNode.ROOT_KEY)) {
|
||||||
|
if(node.getValue().get(locale) != null) {
|
||||||
|
parent.add(node.getKey(), new JsonPrimitive(node.getValue().get(locale)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for(LocalizedNode children : node.getChildren()) {
|
||||||
|
if(children.isLeaf()) {
|
||||||
|
writeTree(locale, parent, children);
|
||||||
|
} else {
|
||||||
|
JsonObject childrenJson = new JsonObject();
|
||||||
|
writeTree(locale, childrenJson, children);
|
||||||
|
if(childrenJson.size() > 0) {
|
||||||
|
parent.add(children.getKey(), childrenJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a {@link JsonObject} and writes the tree into the provided {@link LocalizedNode}
|
||||||
|
* @param locale Current locale
|
||||||
|
* @param json Json to read
|
||||||
|
* @param data Node. Can be a root node
|
||||||
|
*/
|
||||||
|
public static void readTree(String locale, JsonObject json, LocalizedNode data) {
|
||||||
|
for(Map.Entry<String, JsonElement> entry : json.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try to go one level deeper
|
||||||
|
JsonObject childObject = entry.getValue().getAsJsonObject();
|
||||||
|
|
||||||
|
LocalizedNode childrenNode = data.getChildren(key);
|
||||||
|
|
||||||
|
if(childrenNode == null) {
|
||||||
|
childrenNode = new LocalizedNode(key, new ArrayList<>());
|
||||||
|
data.addChildren(childrenNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
readTree(locale, childObject, childrenNode);
|
||||||
|
|
||||||
|
} catch(IllegalStateException e) { // Reached end for this node
|
||||||
|
LocalizedNode leafNode = data.getChildren(key);
|
||||||
|
|
||||||
|
if(leafNode == null) {
|
||||||
|
leafNode = new LocalizedNode(key, new HashMap<>());
|
||||||
|
data.addChildren(leafNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> messages = leafNode.getValue();
|
||||||
|
messages.put(locale, entry.getValue().getAsString());
|
||||||
|
leafNode.setValue(messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user