Skip to content

Accept the specification's translation option names, and the behavior as text - #64

Draft
jwrosewell wants to merge 3 commits into
rcfrom
fix/translation-missing-behavior-text
Draft

jwrosewell wants to merge 3 commits into
rcfrom
fix/translation-missing-behavior-text

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The Translation Engine's missing translation option differed from the specification in two ways. On rc at 0507eef, the problems were these.

  1. The option had a different name. The specification names the engine's options SourceElementDataKey, FixedLanguage and MissingTranslationBehavior (translation-engine.md, "Configuration"). Python already took source_element_data_key and fixed_language, the same names in Python's style. It named the third option behavior, both in TranslationEngineBase.__init__ (translation_engine_base.py lines 62 to 68) and in Translator.__init__ (translator.py lines 41 to 44).
  2. A behavior given as text had no effect, and nothing said so. Both constructors stored the value as given (translation_engine_base.py line 105 and translator.py line 61). The translator compares the value with the MissingTranslationBehavior members and treats anything that is not EMPTY_STRING or FLOW_ERROR as ORIGINAL (translator.py lines 118 to 124). PipelineBuilder.build_from_configuration passes each element's elementParameters to its constructor as they are, and a configuration file can only give text. So a configuration naming "EmptyString" or "FlowError", which are the specification's names for the behaviors (translation-engine.md, "Processing"), matched no member, and a missing translation kept its original value. A typing mistake was treated the same way.

Change

All line numbers in this section are at d9ec5ee.

The specification's name, with the old name kept

  • TranslationEngineBase and Translator take missing_translation_behavior (translation_engine_base.py lines 62 to 71 and translator.py lines 42 to 47). A value given by position is taken as missing_translation_behavior, as it was taken as behavior before.
  • behavior still works as a keyword-only, deprecated alias. Using it raises a DeprecationWarning that names missing_translation_behavior. When both are given, missing_translation_behavior wins. When neither is given the behavior is Original, as before. This is done by _resolve (missing_translation_behavior.py lines 77 to 98), and both docstrings say so.
  • source_element_data_key and fixed_language already had the specification's names, so they are unchanged and have no alias.

The behavior as text

  • MissingTranslationBehavior.from_value (missing_translation_behavior.py lines 43 to 69) returns a member as it is. It turns text into the member the text names, accepting the specification's names (Original, EmptyString, FlowError) and the members' own names and values (ORIGINAL, empty_string, FLOW_ERROR and so on), ignoring case and underscores.
  • Anything else, None included, raises ValueError naming the three accepted names. Because both constructors use it, an unknown value stops the engine, or a pipeline built from a configuration file, being built.

The IP Intelligence translation engines

  • CountryCodeTranslationEngine and CountriesTranslationEngine are not changed. They pass the behavior by position, which the new constructor takes as missing_translation_behavior and the old one took as behavior. So they work with either release of fiftyone_pipeline_translation, raise no deprecation warning, and fiftyone_ipintelligence_translation needs no new release for this change.

No readme or example names the behavior option, so none changed.

For the release notes

  • The Translation Engine takes the specification's name for the missing translation option, missing_translation_behavior. The old name, behavior, still works but raises a DeprecationWarning, and if both are given missing_translation_behavior is used.
  • A Translation Engine configuration that names the missing translation behavior as text, such as "EmptyString" or "FlowError", now takes effect, where before it was ignored and the original value was kept.
  • An unknown value for the missing translation behavior, which was also ignored before, now stops the pipeline being built with a ValueError.

Tests

All the tests below are in MissingTranslationBehaviorTests in pipeline/fiftyone_pipeline_translation/tests/test_translation.py (line 226). They use a source holding "Germany", which has a French translation, and "Spain", which does not.

The behavior as text

  • test_from_value_names_each_member checks twelve spellings, being each specification name, member name and member value, and other mixes of case and underscores.
  • test_from_value_returns_a_member_as_it_is checks each member.
  • test_each_text_takes_effect builds an engine with each spelling and checks the result for "Spain". It stays "Spain" for Original, becomes an empty string for EmptyString, and becomes None with one flow error for FlowError.
  • test_each_member_takes_effect does the same with each member.
  • test_unknown_value_is_refused_when_the_engine_is_built checks that "", "Empty String", "Origin", "Missing", "flow-error", None, 1 and ["Original"] each raise ValueError naming the accepted names.
  • test_translator_takes_text builds a Translator with "EmptyString".

The option names

  • test_specification_name_takes_effect_without_a_warning passes each specification name as missing_translation_behavior, with deprecation warnings turned into errors.
  • test_old_name_still_takes_effect_with_a_warning passes each as behavior, and checks for a DeprecationWarning naming missing_translation_behavior and for the same results.
  • test_specification_name_wins_when_both_are_given passes missing_translation_behavior="EmptyString" and behavior="FlowError", and checks for EmptyString's result and the warning.
  • test_neither_name_given_is_original and test_none_given_by_either_name_is_refused check that neither given means Original, and that None is refused under either name.
  • test_translator_takes_both_names checks the same three cases on Translator.

Configuration files

  • test_configuration_text_takes_effect builds the pipeline with build_from_configuration from a configuration that uses the specification's names, source_element_data_key and missing_translation_behavior. Every value is text, a list or a dictionary, as a configuration file gives them. It runs with "EmptyString", "flow_error" and "Original", with deprecation warnings turned into errors.
  • test_configuration_with_the_old_name_still_takes_effect uses behavior in the configuration and checks the warning and the result.
  • test_configuration_with_an_unknown_value_is_refused checks that "EmptyStrings" stops the build.

Verification

On Windows with Python 3.14.7, with fiftyone_pipeline_core, fiftyone_pipeline_translation and fiftyone_ipintelligence_translation installed from this checkout into a virtual environment, I ran python -m pytest tests -p no:cacheprovider -q in each package's folder.

pipeline/fiftyone_pipeline_translation

  • rc's code with rc's tests gave 19 passed.
  • rc's code with this branch's tests gave 47 failed, 28 passed, 6 subtests passed. The failures are the new tests. For example, a configuration naming "EmptyString" gave ['Allemagne', 'Spain'], and missing_translation_behavior was not a parameter.
  • This branch gave 34 passed, 47 subtests passed, being the 19 existing tests and the 15 new ones.

ip-intelligence/fiftyone_ipintelligence_translation

The IP Intelligence package's files are the same as on rc. I ran its tests with -W error::DeprecationWarning, so a deprecation warning would fail them.

  • With this branch's fiftyone_pipeline_translation they gave 26 passed.
  • With rc's fiftyone_pipeline_translation they gave 26 passed.

Remaining

  • Removing the behavior alias would break callers, so it waits for a release where that is allowed.
  • A configuration file can still set the engine's sources and translations through elementParameters, which the specification says stay in code. That is not changed here.

…n one

TranslationEngineBase and Translator stored the behavior they were given
without checking it, and compared it with the MissingTranslationBehavior
members. A configuration file can only give text, so a configuration
naming "EmptyString" or "flow_error" matched no member and a missing
translation kept its original value, with nothing to say the setting had
been ignored.

MissingTranslationBehavior.from_value now returns a member as it is, and
turns text naming a member into that member. It takes the
specification's names (Original, EmptyString, FlowError) and the members'
own names and values, ignoring case and underscores, and raises
ValueError for anything else. The engine and the translator use it, so
an unknown value stops the engine being built. The parameter is still
named behavior.
The specification names the Translation Engine's options
SourceElementDataKey and MissingTranslationBehavior. Python already took
source_element_data_key, but named the second option behavior.

TranslationEngineBase and Translator now take missing_translation_behavior.
behavior still works as a keyword-only deprecated alias that raises a
DeprecationWarning, and when both are given missing_translation_behavior
wins. Neither given means Original, as before. A value given by position
is taken as missing_translation_behavior, as it was taken as behavior.

The IP Intelligence translation engines now pass every option by its name,
so they need a fiftyone_pipeline_translation that takes the new name. Their
package requires fiftyone_pipeline_translation 4.5.43 or later, the
version the release plan gives this commit.
@jwrosewell jwrosewell changed the title Accept the missing translation behavior as text, and refuse an unknown one Accept the specification's translation option names, and the behavior as text Nov 8, 2026
The IP Intelligence translation engines pass the missing translation
behavior by position. A value passed by position is taken as
missing_translation_behavior by the new translation package and as
behavior by the old one, so the engines work with either release and
raise no deprecation warning without any change. Passing it by name
needed a minimum version of fiftyone_pipeline_translation that cannot be
known until the release that carries the new name, so the engines and
their package's requirements are back to their rc content.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant