reformat translation files based on IDE preferences

Resolves #123
Resolves #128
This commit is contained in:
marhali 2022-05-31 21:36:21 +02:00
parent 090b7a0216
commit 26af16d0c8
9 changed files with 49 additions and 26 deletions

View File

@ -8,6 +8,7 @@
- Indicate translations with duplicated values yellow
- Multiple translation filters can be used together
- Option to consider subdirectories for modularized translation files
- Reformat translation files based on IDE preferences
### Changed
- Reengineered how translation filters are applied internally

View File

@ -54,7 +54,7 @@ public class DataStore {
ApplicationManager.getApplication().runReadAction(() -> {
try {
this.data = new IOHandler(settings).read();
this.data = new IOHandler(project, settings).read();
this.changeListener.updateLocalesPath(settings.getLocalesDirectory());
successResult.accept(true);
@ -80,7 +80,7 @@ public class DataStore {
ApplicationManager.getApplication().runWriteAction(() -> {
try {
new IOHandler(settings).write(this.data);
new IOHandler(project, settings).write(this.data);
successResult.accept(true);
} catch (Exception ex) {

View File

@ -1,8 +1,14 @@
package de.marhali.easyi18n.io;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import de.marhali.easyi18n.exception.EmptyLocalesDirException;
import de.marhali.easyi18n.io.folder.FolderStrategy;
import de.marhali.easyi18n.io.parser.ParserStrategy;
@ -22,6 +28,7 @@ import java.util.List;
*/
public class IOHandler {
private final @NotNull Project project;
private final @NotNull ProjectSettings settings;
private final @NotNull FolderStrategy folderStrategy;
@ -29,8 +36,8 @@ public class IOHandler {
private final @NotNull ParserStrategyType parserStrategyType;
private final @NotNull ParserStrategy parserStrategy;
public IOHandler(@NotNull ProjectSettings settings) throws Exception {
public IOHandler(@NotNull Project project, @NotNull ProjectSettings settings) throws Exception {
this.project = project;
this.settings = settings;
this.folderStrategy = settings.getFolderStrategy().getStrategy()
@ -76,7 +83,7 @@ public class IOHandler {
/**
* Writes the provided translation data to the local project files <br>
* <b>Note:</b> This method must be called from an Write-Action-Context (see ApplicationManager)
* <b>Note:</b> This method must be called from a Write-Action-Context (see ApplicationManager)
* @param data Cached translation data to save
* @throws IOException Write action failed
*/
@ -92,7 +99,25 @@ public class IOHandler {
for(TranslationFile file : translationFiles) {
try {
this.parserStrategy.write(data, file);
String content = this.parserStrategy.write(data, file);
if(content == null) {
// We should consider deleting the target translation file if it has no content
continue;
}
Document document = FileDocumentManager.getInstance().getDocument(file.getVirtualFile());
assert document != null;
document.setText(content);
PsiFile psi = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
assert psi != null;
new ReformatCodeProcessor(psi, false).run();
FileDocumentManager.getInstance().saveDocument(document);
} catch (Exception ex) {
throw new IOException(file + "\n\n" + ex.getMessage(), ex);
}

View File

@ -38,7 +38,7 @@ public class ModularNamespaceFolderStrategy extends FolderStrategy {
for (VirtualFile localeFile : dir.getChildren()) {
if(localeFile.isDirectory()) {
if(settings.isIncludeSubDirs()) {
if(ns.isEmpty() || settings.isIncludeSubDirs()) {
files.addAll(findLocaleFiles(new KeyPath(ns, localeFile.getName()), localeFile));
}
continue;
@ -67,7 +67,8 @@ public class ModularNamespaceFolderStrategy extends FolderStrategy {
for (Map.Entry<String, TranslationNode> entry : node.getChildren().entrySet()) {
String parentPath = localesPath + "/" + String.join("/", path);
if(super.exists(parentPath, entry.getKey())) { // Is directory - includeSubDirs
// Root-Node or is directory(includeSubDirs)
if(path.isEmpty() || super.exists(parentPath, entry.getKey())) {
files.addAll(createLocaleFiles(localesPath, locales, new KeyPath(path, entry.getKey()), type, entry.getValue()));
continue;
}

View File

@ -1,10 +1,10 @@
package de.marhali.easyi18n.io.parser;
import de.marhali.easyi18n.model.*;
import de.marhali.easyi18n.model.KeyPath;
import de.marhali.easyi18n.settings.ProjectSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@ -28,11 +28,13 @@ public abstract class ParserStrategy {
public abstract void read(@NotNull TranslationFile file, @NotNull TranslationData data) throws Exception;
/**
* Writes the relevant data to the translation file (consider namespace and locale)
* Constructs the relevant data to represents the specified translation file. (consider namespace and locale)
* @param data Translation data cache
* @param file Target translation file
* @return String representing target translation file.
* Can be null to indicate that the file is not necessary and could be deleted
*/
public abstract void write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception;
public abstract @Nullable String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception;
/**
* Determines translation node to use for parsing

View File

@ -44,13 +44,12 @@ public class JsonParserStrategy extends ParserStrategy {
}
@Override
public void write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
public @NotNull String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
TranslationNode targetNode = super.getTargetNode(data, file);
JsonObject output = new JsonObject();
JsonMapper.write(file.getLocale(), output, Objects.requireNonNull(targetNode));
VirtualFile vf = file.getVirtualFile();
vf.setBinaryContent(GSON.toJson(output).getBytes(vf.getCharset()));
return GSON.toJson(output);
}
}

View File

@ -46,13 +46,12 @@ public class Json5ParserStrategy extends ParserStrategy {
}
@Override
public void write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
public @NotNull String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
TranslationNode targetNode = super.getTargetNode(data, file);
Json5Object output = new Json5Object();
Json5Mapper.write(file.getLocale(), output, Objects.requireNonNull(targetNode));
VirtualFile vf = file.getVirtualFile();
vf.setBinaryContent(JSON5.serialize(output).getBytes(vf.getCharset()));
return JSON5.serialize(output);
}
}

View File

@ -44,7 +44,7 @@ public class PropertiesParserStrategy extends ParserStrategy {
}
@Override
public void write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
public @NotNull String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
TranslationNode targetNode = super.getTargetNode(data, file);
TranslationData targetData = new TranslationData(data.getLocales(), targetNode);
@ -53,9 +53,7 @@ public class PropertiesParserStrategy extends ParserStrategy {
try(StringWriter writer = new StringWriter()) {
output.store(writer, null);
VirtualFile vf = file.getVirtualFile();
vf.setBinaryContent(writer.toString().getBytes(vf.getCharset()));
return writer.toString();
}
}
}

View File

@ -40,13 +40,11 @@ public class YamlParserStrategy extends ParserStrategy {
}
@Override
public void write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
public @NotNull String write(@NotNull TranslationData data, @NotNull TranslationFile file) throws Exception {
TranslationNode targetNode = super.getTargetNode(data, file);
Section output = new MapSection();
YamlMapper.write(file.getLocale(), output, targetNode);
VirtualFile vf = file.getVirtualFile();
vf.setBinaryContent(Section.toString(output).getBytes(vf.getCharset()));
return Section.toString(output);
}
}