Codeberg #297 and #298 are the same crash, reported twice from fr-FR:
Resources$NotFoundException: Plural resource ID #0x7f0f0000
quantity=14 item=other
values-fr translated agenda_range_days with only "one" and "many".
French "many" matches millions only, so every count from 2 upwards
resolves to "other" — which the translation doesn't define. Android
falls back to "other" for any quantity form it can't find, but nothing
falls back for "other" itself and there is no fall back to the base
locale either, so getQuantityString throws. Any French user with a
custom agenda range of 2+ days crashed the moment that label composed:
the settings summary, the range picker, and the live preview while
typing a day count.
Nothing caught it. The lint config downgrades MissingQuantity on the
grounds that a missing form "falls back to other at runtime" — true of
every form except "other", which is the one that was missing here. And
check_translations.py treated <plurals> as an opaque key via
RESOURCE_TAGS, never looking inside at quantities.
So enforce the one invariant Android actually requires: a translated
<plurals> must carry an "other" item. Locales may still skip forms
their language rarely uses (Arabic "zero", the missing Italian "many"
in search_delete_title) because those do fall back. Lint's
MissingQuantity can't tell the two cases apart, which is why this lives
in the script rather than in a lint severity, and the stale lint comment
is corrected to say so.
The broken French string itself is owned by Weblate and is fixed there.