Issue #3614403: Select option labels are declared as plain strings, so they are never translated
The options widget reads a base field's allowed_values and only sanitizes it (OptionsWidgetBase::getOptions()), so a label written as a plain PHP string reaches the select exactly as written. A French site shows "The full price" under a French label and description, and no translation function ever sees the string, so extraction never picks it up either.
What changed
Every option label is now a TranslatableMarkup, the pattern the resource's settlement field and the Kessai state lists already used. Seventeen lists over eight files:
- yoyaku: the booking state; the resource's booking mode, booking cutoff, lead time unit, refund gate and cancellation deadline unit.
- yoyaku_payment: the collection mode, the deposit handling, the refund gate and the refund deadline unit.
- yoyaku_calendar: the availability display and the selection mode.
- yoyaku_manager: the grant scope. yoyaku_node: the display mode. yoyaku_ticket: the ticket switch.
The fifteen French strings that were missing are in the same commit.
The guard
OptionLabelsTranslatableTest walks the base fields of every yoyaku entity type and fails on any label that is not translatable, rather than naming today's fields. It was checked against a single reverted label and reported it precisely (yoyaku_tariff.collect_mode[full] = 'The full price'), so the next plain string fails here instead of being noticed on a translated screen.
Note for the release notes
Option labels live in the installed field storage definitions, so a site that installed before this change reports those fields as needing an update until it reinstalls. Pre-1.0, so no update hook.
Testing
103/103 kernel classes green across the whole project (the change touches base fields in six modules, so the sweep was run without a filter). phpcs and cspell clean on every changed file; phpstan unchanged, with its eight pre-existing new static() warnings all in files this does not touch.