Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,31 @@ All user-visible strings must be wrapped with `_()` for translation support:
raise ValueError(_("Invalid handle: %s") % handle)
```
The alias `_(string , context)` is preferred to `pgettext(context, message)`.
Use `ngettext(singular, plural, n)` for plural forms.

Use `ngettext(singular, plural, n)` instead of `_()` whenever a formatted

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to use ngettext even when the English plural form is the same as the singular or the case where n is always greater than 1. Many languages have more complex plural forms than in English.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, that framing was itself wrong. Reworded to drop the "English form changes" test entirely β€” the rule is now "any string that counts a noun" uses ngettext, and I called out explicitly that identical English singular/plural and n-always->1 are not valid reasons to skip it, since other languages have plural rules (2-4 vs 5+, dual forms, etc.) English doesn't. Commit 4485f48.

string embeds a count next to a noun whose English form changes between 1
and 2+ (person/people, entry/entries, generation/generations, match/matches,
timestamp/timestamps, etc.):

```python
ngettext(
"%(count)d person",
"%(count)d people",
count,
) % {"count": count}
```

Before finishing a change, check every `_("...%d..."` / `_("...%(name)d..."`
string you wrote or touched against this rule β€” `_("Found %d people")`
produces "Found 1 people" for translators with no way to fix it.

Ordinal or fraction displays with no inflecting noun (`"page %(cur)d/%(total)d"`,
`"generation %(gen)d/%(total)d"`, `"row %(row)d"`) do *not* need `ngettext` β€”
only convert a string when an actual noun in it would change form.

If a package centralizes its `_` alias (e.g. `_ = glocale.translation.gettext`
in an `__init__.py`), also export `ngettext = glocale.translation.ngettext`
there, so submodules can import both together.

## Submodule Import Rules

Expand Down
Loading