@@ -57,6 +57,87 @@ with Git's dedicated test helpers like `test_path_is_file`.
5757- If you can't find any instances to fix, let us know what search command you
5858 used
5959
60+ ### Fix Improper Pluralization to Use ` ngettext() `
61+
62+ Help improve Git's internationalization (i18n) support by finding
63+ translatable strings that include a numeric placeholder (` %d ` or
64+ ` %i ` ) but use ` _() ` instead of ` Q_() ` . This matters because
65+ some languages (like Polish) have more than two plural forms, and
66+ ` Q_() ` is the only correct way to handle them.
67+
68+ For example, the Polish word for "file" changes form depending on count:
69+
70+ - 1 → * plik*
71+ - 2 - 4 → * pliki*
72+ - 5 - 21 → * plików*
73+ - 22 - 24 → * pliki*
74+ - 25 - 31 → * plików*
75+
76+ A call like ` _("Split into %d hunks.") ` cannot be correctly translated
77+ for all counts. It must be rewritten using ` Q_() ` which is an alias
78+ for ` ngettext() ` .
79+
80+ #### Steps to Complete
81+
82+ 1 . Find candidate strings using:
83+
84+ ``` bash
85+ git grep ' [^Q]_("[^"]*%[id]' -- ' *.c'
86+ ```
87+
88+ 2 . Review the results and identify strings where the number genuinely
89+ controls a ** count of things** (hunks, branches, objects, etc.). Skip
90+ messages where ` %d ` refers to something that is never pluralized,
91+ such as an error code, a line number, or a timeout value:
92+
93+ ``` c
94+ // NOT a pluralization candidate — error code is never "plural"
95+ die_errno (_ ("unable to get credential storage lock in %d ms"), timeout_ms);
96+
97+ // IS a candidate — hunk count should be pluralized
98+ _ ("Split into %d hunks.")
99+ ```
100+
101+ 3. Rewrite the candidate using `ngettext()`:
102+
103+ ```c
104+ // Before:
105+ printf(_("Split into %d hunks."), n);
106+
107+ // After:
108+ printf(Q_("Split into %d hunk.",
109+ "Split into %d hunks.", n), n);
110+ ```
111+
112+ 4 . Build and run the relevant tests to confirm nothing is broken.
113+
114+ #### Notes
115+
116+ - Pick ** one source file** with a small number of instances to keep
117+ the patch focused and reviewable.
118+ - There are known candidates in ` add-patch.c ` , ` archive-zip.c ` ,
119+ ` builtin/checkout.c ` , ` builtin/describe.c ` , ` builtin/fsck.c ` — so
120+ there should be plenty to choose from.
121+ - Each logical change (e.g., one function or one file) should ideally
122+ be its own commit.
123+ - Follow Git's commit message conventions.
124+ - Before starting, ask on the mailing list to confirm no one else is
125+ working on the same file.
126+
127+ #### Need Help?
128+
129+ - See the [ gettext manual on plural forms] ( https://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms )
130+ for background on why ` ngettext() ` is necessary.
131+ - Search the codebase for existing ` Q_() ` usages as examples
132+ of the correct pattern:
133+
134+ ``` bash
135+ git grep -3 ' Q_(' -- ' *.c'
136+ ```
137+
138+ - If you can't find any unfixed instances, let us know the search command
139+ you used so we can retire this microproject idea.
140+
60141
61142### Add more builtin patterns for userdiff
62143
0 commit comments