diff --git a/CHANGELOG.md b/CHANGELOG.md index 2934414..fbd8650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,21 @@ # easy-i18n Changelog ## [Unreleased] +### Added +- Support for IntelliJ Platform version 2022.3 +- Regex support for translation file patterns + +### Changed +- Reload function internally consolidated + +### Fixed +- Parsing for .properties files ## [4.2.4] -### Changed -- Improved exception handling on syntax errors +### Changed +- Improved exception handling on syntax errors -### Fixed +### Fixed - Some settings are not retained on IDE restarts ## [4.2.3] diff --git a/gradle.properties b/gradle.properties index 0ce983e..d171033 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,12 +4,12 @@ pluginGroup = de.marhali.easyi18n pluginName = easy-i18n # SemVer format -> https://semver.org -pluginVersion = 4.2.4 +pluginVersion = 4.3.0 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. pluginSinceBuild = 203 -pluginUntilBuild = 222.* +pluginUntilBuild = 223 # IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties platformType = IU diff --git a/src/main/java/de/marhali/easyi18n/DataStore.java b/src/main/java/de/marhali/easyi18n/DataStore.java index b335c88..db0bf31 100644 --- a/src/main/java/de/marhali/easyi18n/DataStore.java +++ b/src/main/java/de/marhali/easyi18n/DataStore.java @@ -49,9 +49,6 @@ public class DataStore { */ public void loadFromPersistenceLayer(@NotNull Consumer successResult) { ProjectSettings settings = ProjectSettingsService.get(project).getState(); - - ApplicationManager.getApplication().saveAll(); // Save opened files (required if new locales were added) - ApplicationManager.getApplication().runReadAction(() -> { try { this.data = new IOHandler(project, settings).read(); diff --git a/src/main/java/de/marhali/easyi18n/InstanceManager.java b/src/main/java/de/marhali/easyi18n/InstanceManager.java index 829c60a..8eddfae 100644 --- a/src/main/java/de/marhali/easyi18n/InstanceManager.java +++ b/src/main/java/de/marhali/easyi18n/InstanceManager.java @@ -72,6 +72,7 @@ public class InstanceManager { * Fetches data from persistence layer and notifies all endpoints via {@link DataBus}. */ public void reload() { + ApplicationManager.getApplication().saveAll(); // Save opened files (required if new locales were added) store.loadFromPersistenceLayer((success) -> bus.propagate().onUpdateData(store.getData())); } diff --git a/src/main/java/de/marhali/easyi18n/io/folder/FolderStrategy.java b/src/main/java/de/marhali/easyi18n/io/folder/FolderStrategy.java index d9161fa..149be8a 100644 --- a/src/main/java/de/marhali/easyi18n/io/folder/FolderStrategy.java +++ b/src/main/java/de/marhali/easyi18n/io/folder/FolderStrategy.java @@ -7,8 +7,8 @@ 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 de.marhali.easyi18n.util.WildcardRegexMatcher; -import org.apache.commons.io.FilenameUtils; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -51,7 +51,8 @@ public abstract class FolderStrategy { * @return true if file matches and should be processed */ protected boolean isFileRelevant(@NotNull VirtualFile file) { - return !file.isDirectory() && FilenameUtils.wildcardMatch(file.getName(), this.settings.getFilePattern()); + return !file.isDirectory() + && WildcardRegexMatcher.matchWildcardRegex(file.getName(), settings.getFilePattern()); } /** diff --git a/src/main/java/de/marhali/easyi18n/io/parser/json5/Json5ParserStrategy.java b/src/main/java/de/marhali/easyi18n/io/parser/json5/Json5ParserStrategy.java index 1baf0ec..70d9224 100644 --- a/src/main/java/de/marhali/easyi18n/io/parser/json5/Json5ParserStrategy.java +++ b/src/main/java/de/marhali/easyi18n/io/parser/json5/Json5ParserStrategy.java @@ -26,7 +26,7 @@ import java.util.Objects; public class Json5ParserStrategy extends ParserStrategy { private static final Json5 JSON5 = Json5.builder(builder -> - builder.allowInvalidSurrogate().trailingComma().indentFactor(4).build()); + builder.allowInvalidSurrogate().trailingComma().indentFactor(2).build()); public Json5ParserStrategy(@NotNull ProjectSettings settings) { super(settings); diff --git a/src/main/java/de/marhali/easyi18n/io/parser/properties/PropertiesParserStrategy.java b/src/main/java/de/marhali/easyi18n/io/parser/properties/PropertiesParserStrategy.java index 936dbf8..007c788 100644 --- a/src/main/java/de/marhali/easyi18n/io/parser/properties/PropertiesParserStrategy.java +++ b/src/main/java/de/marhali/easyi18n/io/parser/properties/PropertiesParserStrategy.java @@ -47,9 +47,7 @@ public class PropertiesParserStrategy extends ParserStrategy { throw new SyntaxException(ex.getMessage(), file); } - if(!input.isEmpty()) { - PropertiesMapper.read(file.getLocale(), input, targetData, converter); - } + PropertiesMapper.read(file.getLocale(), input, targetData, converter); } } diff --git a/src/main/java/de/marhali/easyi18n/service/FileChangeListener.java b/src/main/java/de/marhali/easyi18n/service/FileChangeListener.java index 00ed6e2..88ce083 100644 --- a/src/main/java/de/marhali/easyi18n/service/FileChangeListener.java +++ b/src/main/java/de/marhali/easyi18n/service/FileChangeListener.java @@ -54,10 +54,7 @@ public class FileChangeListener implements AsyncFileListener { events.forEach((e) -> { if(e.getPath().contains(localesPath)) { // Perform reload logger.debug("Detected file change. Reloading instance..."); - InstanceManager manager = InstanceManager.get(project); - manager.store().loadFromPersistenceLayer((success) -> { - manager.bus().propagate().onUpdateData(manager.store().getData()); - }); + InstanceManager.get(project).reload(); } }); } diff --git a/src/main/java/de/marhali/easyi18n/settings/ProjectSettingsService.java b/src/main/java/de/marhali/easyi18n/settings/ProjectSettingsService.java index 1cc0538..3363ec5 100644 --- a/src/main/java/de/marhali/easyi18n/settings/ProjectSettingsService.java +++ b/src/main/java/de/marhali/easyi18n/settings/ProjectSettingsService.java @@ -31,7 +31,7 @@ public class ProjectSettingsService implements PersistentStateComponent {}); + + // Save the cached translation data to a temporary output directory + ProjectSettingsState out = new ProjectSettingsState(settings); + out.setLocalesDirectory(tempPath.toString()); + ProjectSettingsService.get(getProject()).setState(out); + + InstanceManager.get(getProject()).store().saveToPersistenceLayer(success -> {}); + + // Compare file structure and contents + IOFileFilter fileFilter = TrueFileFilter.INSTANCE; + + File originalDirectory = new File(Objects.requireNonNull(settings.getLocalesDirectory())); + File[] originalFiles = FileUtils.listFiles(originalDirectory, fileFilter, fileFilter).toArray(new File[0]); + + File outputDirectory = tempPath.toFile(); + File[] outputFiles = FileUtils.listFiles(outputDirectory, fileFilter, fileFilter).toArray(new File[0]); + + Arrays.sort(originalFiles); + Arrays.sort(outputFiles); + + assertEquals(originalFiles.length, outputFiles.length); + + for(int i = 0; i < originalFiles.length; i++) { + File originalFile = originalFiles[i]; + File outputFile = outputFiles[i]; + + // Replace originalFile with os-dependent line-separators + assertEquals(FileUtils.readFileToString(originalFile, CHARSET).replace("\n", System.lineSeparator()), + FileUtils.readFileToString(outputFile, CHARSET)); + } + } +} diff --git a/src/test/java/de/marhali/easyi18n/e2e/TestSettingsState.java b/src/test/java/de/marhali/easyi18n/e2e/TestSettingsState.java new file mode 100644 index 0000000..50b403b --- /dev/null +++ b/src/test/java/de/marhali/easyi18n/e2e/TestSettingsState.java @@ -0,0 +1,51 @@ +package de.marhali.easyi18n.e2e; + +import de.marhali.easyi18n.io.folder.FolderStrategyType; +import de.marhali.easyi18n.io.parser.ParserStrategyType; +import de.marhali.easyi18n.settings.presets.DefaultPreset; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Settings base for end-to-end tests. + * @author marhali + */ +public class TestSettingsState extends DefaultPreset { + + private final String localesDirectory; + private final FolderStrategyType folderStrategy; + private final ParserStrategyType parserStrategy; + + public TestSettingsState(String localesDirectory, FolderStrategyType folderStrategy, ParserStrategyType parserStrategy) { + this.localesDirectory = localesDirectory; + this.folderStrategy = folderStrategy; + this.parserStrategy = parserStrategy; + } + + + @Override + public @Nullable String getLocalesDirectory() { + return localesDirectory; + } + + @Override + public @NotNull FolderStrategyType getFolderStrategy() { + return folderStrategy; + } + + @Override + public @NotNull ParserStrategyType getParserStrategy() { + return parserStrategy; + } + + @Override + public @NotNull String getFilePattern() { + return "*.*"; + } + + @Override + public boolean isSorting() { + return false; + } +} diff --git a/src/test/java/de/marhali/easyi18n/e2e/single/SingleJson5Test.java b/src/test/java/de/marhali/easyi18n/e2e/single/SingleJson5Test.java new file mode 100644 index 0000000..ff12ae9 --- /dev/null +++ b/src/test/java/de/marhali/easyi18n/e2e/single/SingleJson5Test.java @@ -0,0 +1,20 @@ +package de.marhali.easyi18n.e2e.single; + +import de.marhali.easyi18n.e2e.EndToEndTestCase; +import de.marhali.easyi18n.e2e.TestSettingsState; +import de.marhali.easyi18n.io.folder.FolderStrategyType; +import de.marhali.easyi18n.io.parser.ParserStrategyType; + +/** + * @author marhali + * End-to-end tests for single directory json5 files. + */ +public class SingleJson5Test extends EndToEndTestCase { + public SingleJson5Test() { + super(new TestSettingsState( + "src/test/resources/single/json5", + FolderStrategyType.SINGLE, + ParserStrategyType.JSON5) + ); + } +} diff --git a/src/test/java/de/marhali/easyi18n/e2e/single/SingleJsonTest.java b/src/test/java/de/marhali/easyi18n/e2e/single/SingleJsonTest.java new file mode 100644 index 0000000..68f0826 --- /dev/null +++ b/src/test/java/de/marhali/easyi18n/e2e/single/SingleJsonTest.java @@ -0,0 +1,20 @@ +package de.marhali.easyi18n.e2e.single; + +import de.marhali.easyi18n.e2e.EndToEndTestCase; +import de.marhali.easyi18n.e2e.TestSettingsState; +import de.marhali.easyi18n.io.folder.FolderStrategyType; +import de.marhali.easyi18n.io.parser.ParserStrategyType; + +/** + * End-to-end tests for single directory json files. + * @author marhali + */ +public class SingleJsonTest extends EndToEndTestCase { + public SingleJsonTest() { + super(new TestSettingsState( + "src/test/resources/single/json", + FolderStrategyType.SINGLE, + ParserStrategyType.JSON) + ); + } +} diff --git a/src/test/java/de/marhali/easyi18n/e2e/single/SinglePropertiesTest.java b/src/test/java/de/marhali/easyi18n/e2e/single/SinglePropertiesTest.java new file mode 100644 index 0000000..8420450 --- /dev/null +++ b/src/test/java/de/marhali/easyi18n/e2e/single/SinglePropertiesTest.java @@ -0,0 +1,20 @@ +package de.marhali.easyi18n.e2e.single; + +import de.marhali.easyi18n.e2e.EndToEndTestCase; +import de.marhali.easyi18n.e2e.TestSettingsState; +import de.marhali.easyi18n.io.folder.FolderStrategyType; +import de.marhali.easyi18n.io.parser.ParserStrategyType; + +/** + * End-to-end tests for single directory .properties files. + * @author marhali + */ +public class SinglePropertiesTest extends EndToEndTestCase { + public SinglePropertiesTest() { + super(new TestSettingsState( + "src/test/resources/single/properties", + FolderStrategyType.SINGLE, + ParserStrategyType.PROPERTIES) + ); + } +} \ No newline at end of file diff --git a/src/test/java/de/marhali/easyi18n/e2e/single/SingleYamlTest.java b/src/test/java/de/marhali/easyi18n/e2e/single/SingleYamlTest.java new file mode 100644 index 0000000..da609b9 --- /dev/null +++ b/src/test/java/de/marhali/easyi18n/e2e/single/SingleYamlTest.java @@ -0,0 +1,20 @@ +package de.marhali.easyi18n.e2e.single; + +import de.marhali.easyi18n.e2e.EndToEndTestCase; +import de.marhali.easyi18n.e2e.TestSettingsState; +import de.marhali.easyi18n.io.folder.FolderStrategyType; +import de.marhali.easyi18n.io.parser.ParserStrategyType; + +/** + * End-to-ends tests for single directory yaml files. + * @author marhali + */ +public class SingleYamlTest extends EndToEndTestCase { + public SingleYamlTest() { + super(new TestSettingsState( + "src/test/resources/single/yaml", + FolderStrategyType.SINGLE, + ParserStrategyType.YML) + ); + } +} diff --git a/src/test/java/de/marhali/easyi18n/settings/ProjectSettingsServiceTest.java b/src/test/java/de/marhali/easyi18n/settings/ProjectSettingsServiceTest.java index 94c774f..5ccc4f9 100644 --- a/src/test/java/de/marhali/easyi18n/settings/ProjectSettingsServiceTest.java +++ b/src/test/java/de/marhali/easyi18n/settings/ProjectSettingsServiceTest.java @@ -10,9 +10,16 @@ import de.marhali.easyi18n.settings.presets.DefaultPreset; * @author marhali */ public class ProjectSettingsServiceTest extends BasePlatformTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + ProjectSettingsService.get(getProject()).setState(new ProjectSettingsState()); + } + public void testSettingsDefaultPreset() { ProjectSettingsState state = ProjectSettingsService.get(getProject()).getState(); - assertEquals(state, new ProjectSettingsState(new DefaultPreset())); + assertEquals(new ProjectSettingsState(new DefaultPreset()), state); } public void testPersistenceState() { diff --git a/src/test/resources/single/json/de.json b/src/test/resources/single/json/de.json new file mode 100644 index 0000000..145065b --- /dev/null +++ b/src/test/resources/single/json/de.json @@ -0,0 +1,11 @@ +{ + "title": "Titel", + "number": 187, + "object": { + "title": "Titel" + }, + "array": [ + "element1", + "element2" + ] +} \ No newline at end of file diff --git a/src/test/resources/single/json/en.json b/src/test/resources/single/json/en.json new file mode 100644 index 0000000..b274e3a --- /dev/null +++ b/src/test/resources/single/json/en.json @@ -0,0 +1,11 @@ +{ + "title": "Title", + "number": -187, + "object": { + "title": "Title" + }, + "array": [ + "item1", + "item2" + ] +} \ No newline at end of file diff --git a/src/test/resources/single/json5/de.json5 b/src/test/resources/single/json5/de.json5 new file mode 100644 index 0000000..2f722ae --- /dev/null +++ b/src/test/resources/single/json5/de.json5 @@ -0,0 +1,12 @@ +{ + "title": "Titel", + "number": 187, + "hex": 0x187, + "object": { + "title": "Titel", + }, + "array": [ + "element1", + "element2", + ], +} \ No newline at end of file diff --git a/src/test/resources/single/json5/en.json5 b/src/test/resources/single/json5/en.json5 new file mode 100644 index 0000000..3161f98 --- /dev/null +++ b/src/test/resources/single/json5/en.json5 @@ -0,0 +1,12 @@ +{ + "title": "Title", + "number": -187, + "hex": -0x187, + "object": { + "title": "Title", + }, + "array": [ + "item1", + "item2", + ], +} \ No newline at end of file diff --git a/src/test/resources/single/properties/de.properties b/src/test/resources/single/properties/de.properties new file mode 100644 index 0000000..da7cba4 --- /dev/null +++ b/src/test/resources/single/properties/de.properties @@ -0,0 +1,2 @@ +breakLine=eins\nzwei +title=Titel diff --git a/src/test/resources/single/properties/en.properties b/src/test/resources/single/properties/en.properties new file mode 100644 index 0000000..f9b8eca --- /dev/null +++ b/src/test/resources/single/properties/en.properties @@ -0,0 +1,2 @@ +breakLine=first\nsecond +title=Title diff --git a/src/test/resources/single/yaml/de.yaml b/src/test/resources/single/yaml/de.yaml new file mode 100644 index 0000000..5e7a01e --- /dev/null +++ b/src/test/resources/single/yaml/de.yaml @@ -0,0 +1,3 @@ +title: Titel +nested: + title: Titel diff --git a/src/test/resources/single/yaml/en.yaml b/src/test/resources/single/yaml/en.yaml new file mode 100644 index 0000000..f9e21b7 --- /dev/null +++ b/src/test/resources/single/yaml/en.yaml @@ -0,0 +1,3 @@ +title: Title +nested: + title: Title