fix(goal): fall back gracefully for an unsupported reply locale (#7745)

* fix(goal): fall back gracefully for an unsupported reply locale

goal_reply_text and goal_status_text indexed _TEXT directly with the
caller's locale, so a locale outside NotificationLocale (en-US/zh-CN)
raised KeyError. The /connect handshake (connect_reply_text) normalizes
with supported_locale and falls back to en-US; the /goal replies must do
the same instead of surfacing an internal error to the user.

Normalize the locale in both public entry points. Adds tests pinning the
fallback for an unknown locale and the zh-CN wording for a supported one.

* style(tests): format goal status locale assertion

---------

Co-authored-by: lisry-1 <249596828+lisry-1@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
lisry-1 2026-10-31 19:19:42 +08:00 committed by GitHub
parent eb5d1e1880
commit e0f5483fdf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 0 deletions

View File

@ -16,6 +16,7 @@ from __future__ import annotations
import math
from collections.abc import Mapping
from app.channels.reply_locale import supported_locale
from app.scheduler.notification_text import goal_reason_text
from deerflow.persistence.scheduled_task_runs.finalization import CHECK_FAILURE_CODES
from deerflow.runtime.goal import is_active_goal
@ -65,6 +66,7 @@ _WAITING_KEYS = {"needs_user_input": "waiting_for_you", "external_wait": "waitin
def goal_reply_text(key: str, locale: str) -> str:
"""A fixed ``/goal`` reply (``none``, ``cleared``, ``*_failed``) in ``locale``."""
locale = supported_locale(locale)
return _TEXT[locale][key]
@ -102,6 +104,7 @@ def goal_status_text(goal: object, outcome: object, *, running: bool, locale: st
``running`` says whether the thread has a run pending or in progress.
"""
locale = supported_locale(locale)
text = _TEXT[locale]
if is_active_goal_state(goal):
lines = [text["goal"].format(objective=goal["objective"])]

View File

@ -0,0 +1,25 @@
"""Tests for ``/goal`` reply text locale handling.
``goal_status.py`` hosts its own reply wording and, unlike the ``/connect``
handshake, used to index its ``_TEXT`` table directly with the caller's locale.
A locale outside ``NotificationLocale`` therefore raised ``KeyError`` instead of
falling back, which is the opposite of ``connect_reply_text``. These tests pin
the fallback behavior.
"""
from app.channels.goal_status import goal_reply_text, goal_status_text
def test_goal_reply_text_unknown_locale_falls_back_to_default():
"""A locale outside NotificationLocale must fall back, not raise KeyError."""
assert goal_reply_text("none", "ja-JP") == "No active goal."
def test_goal_reply_text_known_zh_locale():
"""A supported locale still selects its own wording."""
assert goal_reply_text("none", "zh-CN") == "当前没有目标。"
def test_goal_status_text_unknown_locale_falls_back_to_default():
"""The status reply also falls back for an unsupported locale."""
assert goal_status_text(None, None, running=False, locale="ja-JP") == "No active goal."