Python: Fix PowerFx eval crash on non-English system locales by setting CurrentUICulture to en-US (#4408)

* Fix #4321: Set CurrentUICulture to en-US in PowerFx eval()

On non-English systems, CultureInfo.CurrentUICulture causes PowerFx to
emit localized error messages. The existing ValueError guard only matches
English strings ("isn't recognized", "Name isn't valid"), so undefined
variable errors crash instead of returning None gracefully.

Fix: save and restore CurrentUICulture alongside CurrentCulture before
calling engine.eval(), ensuring error messages are always in English.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Reuse single CultureInfo instance to avoid redundant allocations

Cache CultureInfo("en-US") in a local variable instead of instantiating
it twice per eval() call, as suggested in PR review.

Fixes #4321

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add assertion for CurrentUICulture restoration after eval

Assert that the production code's finally-block correctly restores
CurrentUICulture to it-IT after eval returns, covering future
regressions where the culture could leak.

The CultureInfo caching suggestion (comment #2) was already
implemented in the production code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Evan Mattson
2026-03-04 14:46:16 +09:00
committed by GitHub
Unverified
parent e3ea71ec2e
commit 4dc20c6be4
2 changed files with 30 additions and 1 deletions
@@ -493,6 +493,31 @@ class TestPowerFxUndefinedVariables:
result = state.eval("=Local.Something.Nested.Deep")
assert result is None
async def test_undefined_variable_returns_none_with_non_english_ui_culture(self, mock_state):
"""Test that undefined variables return None even when CurrentUICulture is non-English.
Regression test for #4321: on non-English systems, CurrentUICulture causes
PowerFx to emit localized error messages that don't match the English
string guards ("isn't recognized", "Name isn't valid"), crashing the workflow.
The fix sets CurrentUICulture to en-US alongside CurrentCulture before eval.
"""
from System.Globalization import CultureInfo
state = DeclarativeWorkflowState(mock_state)
state.initialize()
# Simulate a non-English UI culture (e.g. Italian)
original_ui_culture = CultureInfo.CurrentUICulture
CultureInfo.CurrentUICulture = CultureInfo("it-IT")
try:
# Should return None, not raise ValueError with Italian error text
result = state.eval("=Local.StatusConversationId")
assert result is None
# Verify the production code restored CurrentUICulture after eval
assert str(CultureInfo.CurrentUICulture) == str(CultureInfo("it-IT"))
finally:
CultureInfo.CurrentUICulture = original_ui_culture
class TestStringInterpolation:
"""Test string interpolation patterns."""