consider subdirectories for modularized translation files
Resolves #124
This commit is contained in:
parent
8dc66e1250
commit
c03d97f3e8
@ -7,6 +7,7 @@
|
||||
- Duplicate translation values filter
|
||||
- Indicate translations with duplicated values yellow
|
||||
- Multiple translation filters can be used together
|
||||
- Option to consider subdirectories for modularized translation files
|
||||
|
||||
### Changed
|
||||
- Reengineered how translation filters are applied internally
|
||||
|
@ -6,8 +6,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import de.marhali.easyi18n.io.parser.ParserStrategyType;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
import de.marhali.easyi18n.model.TranslationFile;
|
||||
|
||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -71,4 +71,14 @@ public abstract class FolderStrategy {
|
||||
|
||||
return Objects.requireNonNull(vf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given file or directory exists
|
||||
* @param parent Parent path
|
||||
* @param child File / Directory name
|
||||
* @return true if file is existing otherwise false
|
||||
*/
|
||||
protected boolean exists(@NotNull String parent, @NotNull String child) {
|
||||
return LocalFileSystem.getInstance().findFileByIoFile(new File(parent, child)) != null;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package de.marhali.easyi18n.io.folder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import de.marhali.easyi18n.io.parser.ParserStrategyType;
|
||||
import de.marhali.easyi18n.model.KeyPath;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
import de.marhali.easyi18n.model.TranslationFile;
|
||||
import de.marhali.easyi18n.model.TranslationNode;
|
||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -12,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Modularized translation folder strategy by locale.
|
||||
@ -31,12 +34,26 @@ public class ModularLocaleFolderStrategy extends FolderStrategy {
|
||||
for(VirtualFile localeModuleDir : localesDirectory.getChildren()) {
|
||||
if(localeModuleDir.isDirectory()) {
|
||||
String locale = localeModuleDir.getNameWithoutExtension();
|
||||
files.addAll(findNamespaceFiles(locale, new KeyPath(), localeModuleDir));
|
||||
}
|
||||
}
|
||||
|
||||
for(VirtualFile namespaceFile : localeModuleDir.getChildren()) {
|
||||
if(super.isFileRelevant(namespaceFile)) {
|
||||
files.add(new TranslationFile(namespaceFile, locale, namespaceFile.getNameWithoutExtension()));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
private List<TranslationFile> findNamespaceFiles(@NotNull String locale, @NotNull KeyPath ns, @NotNull VirtualFile dir) {
|
||||
List<TranslationFile> files = new ArrayList<>();
|
||||
|
||||
for(VirtualFile namespaceFile : dir.getChildren()) {
|
||||
if(namespaceFile.isDirectory()) {
|
||||
if(settings.isIncludeSubDirs()) {
|
||||
files.addAll(findNamespaceFiles(locale, new KeyPath(ns, namespaceFile.getName()), namespaceFile));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(super.isFileRelevant(namespaceFile)) {
|
||||
files.add(new TranslationFile(namespaceFile, locale, new KeyPath(ns, namespaceFile.getNameWithoutExtension())));
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,12 +68,28 @@ public class ModularLocaleFolderStrategy extends FolderStrategy {
|
||||
List<TranslationFile> files = new ArrayList<>();
|
||||
|
||||
for(String locale : data.getLocales()) {
|
||||
for(String namespace : data.getRootNode().getChildren().keySet()) {
|
||||
VirtualFile vf = super.constructFile(localesPath + "/" + locale,
|
||||
namespace + "." + type.getFileExtension());
|
||||
files.addAll(this.createNamespaceFiles(localesPath, locale, new KeyPath(), type, data.getRootNode()));
|
||||
}
|
||||
|
||||
files.add(new TranslationFile(vf, locale, namespace));
|
||||
return files;
|
||||
}
|
||||
|
||||
private List<TranslationFile> createNamespaceFiles(
|
||||
String localesPath, String locale, KeyPath path,
|
||||
ParserStrategyType type, TranslationNode node) throws IOException {
|
||||
|
||||
List<TranslationFile> files = new ArrayList<>();
|
||||
|
||||
for(Map.Entry<String, TranslationNode> entry : node.getChildren().entrySet()) {
|
||||
String parentPath = localesPath + "/" + locale + "/" + String.join("/", path);
|
||||
|
||||
if(super.exists(parentPath, entry.getKey())) { // Is directory - includeSubDirs
|
||||
files.addAll(createNamespaceFiles(localesPath, locale, new KeyPath(path, entry.getKey()), type, entry.getValue()));
|
||||
continue;
|
||||
}
|
||||
|
||||
VirtualFile vf = super.constructFile(parentPath, entry.getKey() + "." + type.getFileExtension());
|
||||
files.add(new TranslationFile(vf, locale, new KeyPath(path, entry.getKey())));
|
||||
}
|
||||
|
||||
return files;
|
||||
|
@ -3,8 +3,10 @@ package de.marhali.easyi18n.io.folder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import de.marhali.easyi18n.io.parser.ParserStrategyType;
|
||||
import de.marhali.easyi18n.model.KeyPath;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
import de.marhali.easyi18n.model.TranslationFile;
|
||||
import de.marhali.easyi18n.model.TranslationNode;
|
||||
import de.marhali.easyi18n.settings.ProjectSettings;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -12,6 +14,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Modular translation folder strategy by namespace.
|
||||
@ -26,17 +30,22 @@ public class ModularNamespaceFolderStrategy extends FolderStrategy {
|
||||
|
||||
@Override
|
||||
public @NotNull List<TranslationFile> analyzeFolderStructure(@NotNull VirtualFile localesDirectory) {
|
||||
return new ArrayList<>(findLocaleFiles(new KeyPath(), localesDirectory));
|
||||
}
|
||||
|
||||
private List<TranslationFile> findLocaleFiles(KeyPath ns, VirtualFile dir) {
|
||||
List<TranslationFile> files = new ArrayList<>();
|
||||
|
||||
for(VirtualFile namespaceModuleDir : localesDirectory.getChildren()) {
|
||||
if(namespaceModuleDir.isDirectory()) {
|
||||
String namespace = namespaceModuleDir.getNameWithoutExtension();
|
||||
|
||||
for(VirtualFile localeFile : namespaceModuleDir.getChildren()) {
|
||||
if(super.isFileRelevant(localeFile)) {
|
||||
files.add(new TranslationFile(localeFile, localeFile.getNameWithoutExtension(), namespace));
|
||||
}
|
||||
for (VirtualFile localeFile : dir.getChildren()) {
|
||||
if(localeFile.isDirectory()) {
|
||||
if(settings.isIncludeSubDirs()) {
|
||||
files.addAll(findLocaleFiles(new KeyPath(ns, localeFile.getName()), localeFile));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(super.isFileRelevant(localeFile)) {
|
||||
files.add(new TranslationFile(localeFile, localeFile.getNameWithoutExtension(), ns));
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,14 +57,24 @@ public class ModularNamespaceFolderStrategy extends FolderStrategy {
|
||||
@NotNull String localesPath, @NotNull ParserStrategyType type,
|
||||
@NotNull TranslationData data) throws IOException {
|
||||
|
||||
return new ArrayList<>(this.createLocaleFiles(
|
||||
localesPath, data.getLocales(), new KeyPath(), type, data.getRootNode()));
|
||||
}
|
||||
|
||||
private List<TranslationFile> createLocaleFiles(String localesPath, Set<String> locales, KeyPath path, ParserStrategyType type, TranslationNode node) throws IOException {
|
||||
List<TranslationFile> files = new ArrayList<>();
|
||||
|
||||
for(String namespace : data.getRootNode().getChildren().keySet()) {
|
||||
for(String locale : data.getLocales()) {
|
||||
VirtualFile vf = super.constructFile(localesPath + "/" + namespace,
|
||||
locale + "." + type.getFileExtension());
|
||||
for (Map.Entry<String, TranslationNode> entry : node.getChildren().entrySet()) {
|
||||
String parentPath = localesPath + "/" + String.join("/", path);
|
||||
|
||||
files.add(new TranslationFile(vf, locale, namespace));
|
||||
if(super.exists(parentPath, entry.getKey())) { // Is directory - includeSubDirs
|
||||
files.addAll(createLocaleFiles(localesPath, locales, new KeyPath(path, entry.getKey()), type, entry.getValue()));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String locale : locales) {
|
||||
VirtualFile vf = super.constructFile(parentPath, locale + "." + type.getFileExtension());
|
||||
files.add(new TranslationFile(vf, locale, path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,15 +46,7 @@ public abstract class ParserStrategy {
|
||||
TranslationNode targetNode = data.getRootNode();
|
||||
|
||||
if(file.getNamespace() != null) {
|
||||
String moduleName = file.getNamespace();
|
||||
TranslationNode moduleNode = data.getNode(new KeyPath(moduleName));
|
||||
|
||||
if(moduleNode == null) {
|
||||
moduleNode = new TranslationNode(this.settings.isSorting());
|
||||
data.getRootNode().setChildren(moduleName, moduleNode);
|
||||
}
|
||||
|
||||
targetNode = moduleNode;
|
||||
targetNode = data.getOrCreateNoe(file.getNamespace());
|
||||
}
|
||||
|
||||
return targetNode;
|
||||
|
@ -89,6 +89,20 @@ public class TranslationData {
|
||||
return node;
|
||||
}
|
||||
|
||||
public @NotNull TranslationNode getOrCreateNoe(@NotNull KeyPath fullPath) {
|
||||
TranslationNode node = this.rootNode;
|
||||
|
||||
if(fullPath.isEmpty()) { // Return root node if empty path was supplied
|
||||
return node;
|
||||
}
|
||||
|
||||
for(String section : fullPath) {
|
||||
node = node.getOrCreateChildren(section);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fullPath Absolute translation key path
|
||||
* @return Found translation. Can be null if path is empty or is not a leaf element
|
||||
|
@ -13,9 +13,9 @@ public class TranslationFile {
|
||||
|
||||
private final @NotNull VirtualFile virtualFile;
|
||||
private final @NotNull String locale;
|
||||
private final @Nullable String namespace;
|
||||
private final @Nullable KeyPath namespace;
|
||||
|
||||
public TranslationFile(@NotNull VirtualFile virtualFile, @NotNull String locale, @Nullable String namespace) {
|
||||
public TranslationFile(@NotNull VirtualFile virtualFile, @NotNull String locale, @Nullable KeyPath namespace) {
|
||||
this.virtualFile = virtualFile;
|
||||
this.locale = locale;
|
||||
this.namespace = namespace;
|
||||
@ -29,7 +29,7 @@ public class TranslationFile {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public @Nullable String getNamespace() {
|
||||
public @Nullable KeyPath getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,8 @@ settings.resource.folder.tooltip=What is the folder structure of your translatio
|
||||
settings.resource.parser.items=JSON;JSON5;YAML;YML;Properties;ARB
|
||||
settings.resource.parser.tooltip=Which file parser should be used to process your translation files?
|
||||
settings.resource.file-pattern.tooltip=Defines a wildcard matcher to filter relevant translation files. For example *.json, *.??? or *.*.
|
||||
settings.resource.nesting.title=Consider subdirectories for modularized translation files
|
||||
settings.resource.nesting.tooltip=Validates directories within a module and passes them as a submodule.
|
||||
settings.resource.sorting.title=Sort translation keys alphabetically
|
||||
settings.resource.sorting.tooltip=Sorts all translation keys alphabetically. If disabled, the original key-order in the files is kept.
|
||||
# Editor Configuration
|
||||
|
Loading…
x
Reference in New Issue
Block a user