diff --git a/autograder-api/src/main/java/de/firemage/autograder/api/AbstractLinter.java b/autograder-api/src/main/java/de/firemage/autograder/api/AbstractLinter.java index 8ad28f41..cad22757 100644 --- a/autograder-api/src/main/java/de/firemage/autograder/api/AbstractLinter.java +++ b/autograder-api/src/main/java/de/firemage/autograder/api/AbstractLinter.java @@ -1,7 +1,11 @@ package de.firemage.autograder.api; +import fluent.bundle.FluentBundle; +import fluent.bundle.FluentResource; + import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.function.Consumer; @@ -20,6 +24,7 @@ class Builder { private int threads; private ClassLoader classLoader; private int maxProblemsPerCheck = -1; + private List messageOverrides = new ArrayList<>(); private Builder(Locale locale) { this.locale = locale; @@ -64,5 +69,14 @@ public ClassLoader getClassLoader() { public Locale getLocale() { return locale; } + + public Builder messagesOverride(FluentResource bundle) { + this.messageOverrides.add(bundle); + return this; + } + + public List getMessageOverrides() { + return this.messageOverrides; + } } } diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/Linter.java b/autograder-core/src/main/java/de/firemage/autograder/core/Linter.java index 8d9727db..838d6395 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/Linter.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/Linter.java @@ -56,10 +56,22 @@ public Linter( default -> throw new IllegalArgumentException("No translation available for the locale " + locale); }; try { - FluentResource resource = FTLParser.parse(FTLStream.of( - new String(this.getClass().getResourceAsStream(filename).readAllBytes(), StandardCharsets.UTF_8) + var fluentBuilder = FluentBundle.builder(locale, ICUFunctionFactory.INSTANCE); + + // The name FluentBuilder#addResourceOverriding is a lie; it does not override preexisting messages + + // message overrides + for (var bundle : builder.getMessageOverrides()) { + fluentBuilder.addResourceOverriding(bundle); + } + + // default messages + FluentResource defaultMessages = FTLParser.parse(FTLStream.of( + new String(this.getClass().getResourceAsStream(filename).readAllBytes(), StandardCharsets.UTF_8) )); - this.fluentBundle = FluentBundle.builder(locale, ICUFunctionFactory.INSTANCE).addResource(resource).build(); + fluentBuilder.addResourceOverriding(defaultMessages); + + this.fluentBundle = fluentBuilder.build(); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/autograder-core/src/test/java/de/firemage/autograder/core/TestMessageOverriding.java b/autograder-core/src/test/java/de/firemage/autograder/core/TestMessageOverriding.java new file mode 100644 index 00000000..3b2fab5c --- /dev/null +++ b/autograder-core/src/test/java/de/firemage/autograder/core/TestMessageOverriding.java @@ -0,0 +1,56 @@ +package de.firemage.autograder.core; + +import de.firemage.autograder.api.AbstractLinter; +import fluent.syntax.parser.FTLParser; +import fluent.syntax.parser.FTLStream; +import org.junit.jupiter.api.Test; + +import java.util.Locale; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TestMessageOverriding { + @Test + void testNoMessageOverride() { + var builder = AbstractLinter.builder(Locale.ENGLISH); + var linter = new Linter(builder); + String msg = linter.translateMessage(new LocalizedMessage("status-compiling")); + assertEquals("Compiling", msg); + } + + @Test + void testSingleMessageOverride() { + String fluentFile = "status-compiling = Foo Bar"; + + var builder = + AbstractLinter.builder(Locale.ENGLISH).messagesOverride(FTLParser.parse(FTLStream.of(fluentFile))); + var linter = new Linter(builder); + String msg = linter.translateMessage(new LocalizedMessage("status-compiling")); + assertEquals("Foo Bar", msg); + } + + @Test + void testDoubleMessageOverride() { + String fluentFile1 = "status-compiling = param {$x}"; + String fluentFile2 = "status-compiling = Foo Bar"; + + var builder = AbstractLinter.builder(Locale.ENGLISH) + .messagesOverride(FTLParser.parse(FTLStream.of(fluentFile1))) + .messagesOverride(FTLParser.parse(FTLStream.of(fluentFile2))); + var linter = new Linter(builder); + String msg = linter.translateMessage(new LocalizedMessage("status-compiling", Map.of("x", "xyz"))); + assertEquals("param xyz", msg); + } + + @Test + void testNonOverriddenMessageWithOverrides() { + String fluentFile = "status-compiling = Foo Bar"; + + var builder = + AbstractLinter.builder(Locale.ENGLISH).messagesOverride(FTLParser.parse(FTLStream.of(fluentFile))); + var linter = new Linter(builder); + String msg = linter.translateMessage(new LocalizedMessage("status-model")); + assertEquals("Building the code model", msg); + } +}