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.model.LocalizedNode;
|
||||
import de.marhali.easyi18n.model.Translations;
|
||||
import de.marhali.easyi18n.util.JsonUtil;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -44,8 +45,11 @@ public class JsonTranslatorIO implements TranslatorIO {
|
||||
try {
|
||||
for(VirtualFile file : files) {
|
||||
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));
|
||||
@ -65,13 +69,16 @@ public class JsonTranslatorIO implements TranslatorIO {
|
||||
try {
|
||||
for(String locale : translations.getLocales()) {
|
||||
JsonObject content = new JsonObject();
|
||||
writeTree(locale, content, translations.getNodes());
|
||||
//JsonElement content = writeTree(locale, new JsonObject(), translations.getNodes());
|
||||
JsonUtil.writeTree(locale, content, translations.getNodes());
|
||||
|
||||
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
|
||||
@ -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.VirtualFile;
|
||||
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.TranslatorIO;
|
||||
|
||||
@ -36,6 +37,11 @@ public class IOUtil {
|
||||
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()) {
|
||||
case "json":
|
||||
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