Translate wish names in plan proposal output
Preset wish names follow the UI language in the wish editor, but the plan proposal still rendered outcome.wishName straight from the stored entity.name, so a proposal could show "Höstlov" with the UI in English. The proposal now carries wish_name_message_key alongside each wish name, and the frontend resolves it with the same helper the editor uses -- falling back to the stored literal when the key is absent or unknown. Nothing is translated on the backend; text crosses the wire as a key. Four surfaces carried a name and all four are covered: WindowOutcome itself, the explanation summary's interpolated data, and two remedies -- including REMEDY_LOWER_PRIORITY_WISH, which names a *different* sibling wish whose key can differ from the outcome's own. The proposal response mapping is hand-written and has dropped new fields twice before, so this is covered by an API-level test asserting the field reaches the response body, not only a service test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RXMhc9nT6sNz1SL4j8dznL
This commit is contained in:
@@ -262,6 +262,12 @@ class Age4Projection:
|
||||
class WindowOutcome:
|
||||
wish_id: UUID
|
||||
wish_name: str
|
||||
# i18n provenance of `wish_name` (see `app.entities.leave_wish.LeaveWish
|
||||
# .name_message_key`) — carried alongside the literal so the frontend can
|
||||
# re-translate a preset-created wish's name into the UI's current locale,
|
||||
# exactly like `resolveWishName` already does for the wish editor. `None`
|
||||
# for a free-typed/user-renamed wish, or any row predating this field.
|
||||
wish_name_message_key: str | None
|
||||
year: int
|
||||
start_date: date
|
||||
end_date: date
|
||||
@@ -1041,6 +1047,7 @@ class _Ledger:
|
||||
outcome = WindowOutcome(
|
||||
wish_id=wish.id,
|
||||
wish_name=wish.name,
|
||||
wish_name_message_key=wish.name_message_key,
|
||||
year=w.anchor_year,
|
||||
start_date=w.start,
|
||||
end_date=w.end,
|
||||
@@ -1051,6 +1058,7 @@ class _Ledger:
|
||||
message_key=MESSAGE_KEY_WINDOW_EXPLANATION,
|
||||
data={
|
||||
"wish_name": wish.name,
|
||||
"wish_name_message_key": wish.name_message_key,
|
||||
"year": w.anchor_year,
|
||||
"weeks_wished": wish.target_weeks,
|
||||
"weeks_funded": weeks_funded,
|
||||
@@ -1143,6 +1151,7 @@ class _Ledger:
|
||||
message_key=f"planRemedies.{REMEDY_LOWER_PRIORITY_WISH}",
|
||||
data={
|
||||
"wish_name": other.name,
|
||||
"wish_name_message_key": other.name_message_key,
|
||||
"from_weeks": other.target_weeks,
|
||||
"to_weeks": half_weeks,
|
||||
"freed_days": freed_estimate,
|
||||
@@ -1171,7 +1180,11 @@ class _Ledger:
|
||||
ShortfallRemedy(
|
||||
kind=REMEDY_SHIFT_WINDOW_INTO_FREE_DAYS,
|
||||
message_key=f"planRemedies.{REMEDY_SHIFT_WINDOW_INTO_FREE_DAYS}",
|
||||
data={"wish_name": wish.name, "shift_gain": shift_gain},
|
||||
data={
|
||||
"wish_name": wish.name,
|
||||
"wish_name_message_key": wish.name_message_key,
|
||||
"shift_gain": shift_gain,
|
||||
},
|
||||
days_freed=shift_gain,
|
||||
)
|
||||
)
|
||||
@@ -1384,6 +1397,7 @@ class _Ledger:
|
||||
return WindowOutcome(
|
||||
wish_id=wish.id,
|
||||
wish_name=wish.name,
|
||||
wish_name_message_key=wish.name_message_key,
|
||||
year=anchor_year,
|
||||
start_date=bound_start,
|
||||
end_date=bound_end,
|
||||
@@ -1394,6 +1408,7 @@ class _Ledger:
|
||||
message_key=MESSAGE_KEY_WINDOW_EXPLANATION,
|
||||
data={
|
||||
"wish_name": wish.name,
|
||||
"wish_name_message_key": wish.name_message_key,
|
||||
"year": anchor_year,
|
||||
"weeks_wished": wish.target_weeks,
|
||||
"weeks_funded": 0.0,
|
||||
|
||||
Reference in New Issue
Block a user