PluralShapeRule class
A count is interpolated into a sentence that has only one grammatical
shape, so some value of that count reads wrong: "{count} people"
renders "1 people".
The plural_categories rule is the other half of this: it checks a plural
is complete once one exists. Nothing checked that a plural should have
existed at all, which is how two English strings shipped saying
"1 people". This rule fires on the source only, because that is where
the defect is born — once the source is a plural expression, translations
are governed by plural_categories, and a fix applied to a translation
alone would leave the source wrong for every other locale.
The heuristic. A warning, not an error, and knowingly approximate:
- Find placeholders that carry a count. A placeholder qualifies by its
declared
@key.placeholders.<name>.type(int,num,double,number) or, when nothing is declared, by a conventional name (count,n,num,total,qty, or anything ending inCount). - Drop the ones already governed by a
plural/selectordinalexpression (IcuMessage.pluralSelectors). - Of what remains, find the noun the count governs (
_wordAfter) and fire only when that noun is already plural (_looksPlural) — which is precisely the disagreement: a count that can be 1 in front of a word that means many.
Step 3 is what keeps this quiet enough to leave on by default. Across the
first real corpus it ran on (a shipping app, ~900 source keys) it flagged
four strings, all four of them genuine, including one hiding inside the
other branch of an existing plural. Where it does misfire, the escape
hatch is the standard one: dialect check --ack plural_shape:source:<key>,
whose fingerprint retires the waiver as soon as the copy is edited.
Constructors
- PluralShapeRule()
-
const
Properties
- defaultSeverity → IssueSeverity
-
Default severity. May be overridden per-issue.
no setteroverride
- hashCode → int
-
The hash code for this object.
no setterinherited
- name → String
-
Stable rule identifier (snake_case). Used by the report formatter
to group findings and by users to silence/ack via state file
(post-v1.0).
no setteroverride
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
run(
DialectProject project) → List< Issue> -
Inspect
projectand return findings. May return an empty list. Should NOT throw — turn unexpected conditions into Issues so the report surfaces them rather than crashing.override -
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited