Repository navigation
Build the Translation Engine from a configuration file, as .NET does - #75
Draft
jwrosewell wants to merge 1 commit into
Draft
jwrosewell wants to merge 1 commit into
jwrosewell wants to merge 1 commit into
Conversation
The specification's Translation Engine configuration has a configuration file set the options that take a single value, being SourceElementDataKey, FixedLanguage and MissingTranslationBehavior, with sources and translations added in code. .NET does this by taking the builder from its service collection, where code has prepared it. Java's PipelineBuilder always constructed a new builder, TranslationEngineBuilder was not annotated so no configuration file could name it, and the behavior had no parse method, so text from a file could not set it. - PipelineBuilder.addElementBuilder gives the configuration route a builder prepared in code, used in preference to constructing one. When more than one is of the type a configuration names, the first added is used, as .NET's FiftyOneServiceProvider and the services here do. - parseToType keeps the parse method's own message, and its exception as the cause, in the error it throws. - TranslationEngineBuilder is annotated with @ElementBuilder, and its build says where sources and translations come from when either is missing. - MissingTranslationBehavior.parse accepts Original, EmptyString and FlowError and the constant names, ignoring case, and refuses anything else naming the accepted values.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The specification's Translation Engine has a configuration file set the options that take a single value, being
SourceElementDataKey,FixedLanguageandMissingTranslationBehaviorwith the valuesOriginal,EmptyStringandFlowError, while sources and translations are added in code (translation-engine.md, Configuration, and Processing for the values)..NET does this by taking the builder from its service collection when one is supplied (
PipelineBuilder.cslines 411 to 414), so code can register aTranslationEngineBuilderthat already holds its sources and translations, and the file sets the rest. That matters because the engine refuses to build without at least one source and one translation, in .NET (TranslationEngineBase.cslines 188 to 204) and in Java (TranslationEngineBaselines 143 to 155).Java could not do any of this on rc (2299507).
PipelineBuilderalways constructed a new builder for a configured element (line 250), so code had no way to give it sources and translations.TranslationEngineBuilderhad no@ElementBuilderannotation (line 45), and the configuration route only finds annotated builders (lines 187 to 189), so no file could name it.MissingTranslationBehaviorhad no staticparsemethod, which the configuration route needs to turn text into any type other than a string (lines 953 to 989), so a file could not set the behavior. When a parse method did refuse a value, the error dropped the parse method's own message.Change
This follows .NET and the specification's Configuration section, with code adding sources and translations and the file setting the single-value options.
PipelineBuilder.addElementBuilder(Object builder), a new public method in pipeline.core. It gives the configuration route a builder prepared in code, whichbuildFromConfigurationuses for any element whose builder name resolves to that builder's type, in place of constructing one. The builder's type must still be one a configuration can name, being annotated with@ElementBuilder. This is the one new public surface in pipeline.core, and its name and shape are a choice for James to review.FiftyOneServiceProvider, which returns the first service of a matching type (FiftyOneServiceProvider.csline 58), and the existinggetServicein this class, which does the same for pipeline services. In .NET the rule belongs to whichever service provider the application passes in, and this is the one 51Degrees supplies.parseToTypenow keeps the parse method's own message in the error it throws, and passes the parse method's exception as the cause.TranslationEngineBuilderis annotated with@ElementBuilder, so a file names it asTranslationEngineorTranslationEngineBuilder. No other builder has either name, so the IP Intelligence country builders resolve as before. Its existing setters already carry the specification's names,setSourceElementDataKey,setFixedLanguageandsetMissingTranslationBehavior, and no older names are in use, so there are no deprecated aliases. When either sources or translations are missing,buildnow says they are added in code and how to useaddElementBuilder. Before, the engine's message was "At least one property translation must be configured.", which did not say where they come from. The exception type is unchanged.MissingTranslationBehavior.parse(String)acceptsOriginal,EmptyStringandFlowErrorand the constant namesORIGINAL,EMPTY_STRINGandFLOW_ERROR, ignoring case and any white space around the text. Anything else is refused with "'Sometimes' is not a missing translation behavior. Use Original, EmptyString or FlowError."An example configuration, with the builder prepared in code:
Options considered and not taken
Country=CountryTranslatedwith commas between pairs, chosen before the specification settles it. It would also need a fix so thatAddSource, which has two overloads, is matched reliably. That is a public format I did not count as simple and clearly safe.Tests
PipelineBuilderPreparedBuilderTest, using the existingListSplitterElementBuildertest builder:TranslationEngineConfigurationTests. Each case reads an XML configuration file that puts a test source element (CountrySourceElement) in front ofTranslationEngineand setsSourceElementDataKey,FixedLanguageandMissingTranslationBehavior. TheTranslationEngineBuilderis prepared in code with one source and one translation.Original,original,ORIGINALandOriginalkeep an untranslated value. The prepared builder is set to EmptyString first, so this shows the file's value replaced it.EmptyString,emptystring,EMPTY_STRINGandempty_stringgive an empty string.FlowError,flowerror,FLOW_ERRORandflow_erroradd the flow error for the untranslated value.Sometimesis refused with the accepted values in the message.MissingTranslationBehaviorTests, coveringparsedirectly: every accepted spelling, white space around the text, and null, empty,Sometimes,Empty StringandFlow-Errorrefused with the exact message.CountryBuildersConfigurationTest. One configuration namesCountryCodeTranslationEngine,CountriesTranslationEngineandTranslationEngine, with a prepared general builder given. It checks that the country engines are still built by their own builders, and the general one by the prepared builder.Checks
From the repository root, with Maven 3.9.16 on Java 21:
CountryTranslationIntegrationTest, which needs an IP Intelligence data file and the native engine. It is skipped the same way on both.cxx/datasubmodule, so that submodule has to be checked out for them to pass, as CI does.addElementBuilderandMissingTranslationBehavior.parsedo not exist there.What remains
AddTranslationis refused, because that method takes two values.AddSourcehas two overloads, and the configuration route uses whichever one reflection lists first, so a file that names it may or may not work. That is unchanged by this pull request.For the release notes
The general Translation Engine can be built from a configuration file once code has given it its sources and translations, through the new
PipelineBuilder.addElementBuilder. The file setsSourceElementDataKey,FixedLanguageandMissingTranslationBehavior, which acceptsOriginal,EmptyStringorFlowError.