Procházet zdrojové kódy

[web] Migrate manual plurals to i18next `_plural` convention (#33989)

* Add tests on plurals

* Update `collabs_per_proj` and its pluralisations

* Update `n_user` and its pluralisations

* Update `showing_x_results` and its pluralisations

* Update `show_x_more_projects` and its pluralisations

* `bin/run web npm run extract-translations`

* Populate `_plural` keys in non-en locales

For 2-form languages (da, de, es, fi, fr, it, nl, no, pt, sv, tr), copy
the existing bare-key value into the new `_plural` sibling to prevent
i18next from falling back to English for count!=1.

Also remove orphan singular keys (`collabs_per_proj_single`,
`showing_1_result*`) left over from the previous commits.

Bare-key values remain in their original plural form pending translator
review — count=1 will still render the plural form in non-en until
translators flip those to singular. Multi-form (cs, pl, ru) and
single-form (ja, ko, zh-CN, zh-TW) locales are unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Flip non-en bare-key values to singular form

Per review, the i18next v3 plural convention uses the bare key for count=1
(singular) and `_plural` for count!=1. The non-en bare-key values were
left as the original plural form by the previous commit so the `_plural`
siblings could be copied from them; this commit flips the bare values to
the singular form per language.

Languages where singular and plural noun forms coincide (Finnish, Swedish,
Turkish) are unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Apply suggestions from code review

Co-authored-by: Olzhas Askar <olzhas.askar@gmail.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Olzhas Askar <olzhas.askar@gmail.com>
GitOrigin-RevId: 628513ca792c2dcce023247e52b7320e2741cc54
Antoine Clausse před 2 měsíci
rodič
revize
0e4fe4090a

+ 5 - 4
services/web/frontend/extracted-translations.json

@@ -321,9 +321,9 @@
   "collaborator_chat": "",
   "collabs_per_proj": "",
   "collabs_per_proj_multiple": "",
+  "collabs_per_proj_plural": "",
   "collabs_per_proj_plus": "",
-  "collabs_per_proj_single": "",
-  "collabs_per_proj_single_plus": "",
+  "collabs_per_proj_plus_plural": "",
   "collapse": "",
   "column_width": "",
   "column_width_is_custom_click_to_resize": "",
@@ -1815,13 +1815,14 @@
   "show_outline": "",
   "show_version_history": "",
   "show_x_more_projects": "",
-  "showing_1_result": "",
-  "showing_1_result_of_total": "",
+  "show_x_more_projects_plural": "",
   "showing_pdf_preview_with_inverted_colors": "",
   "showing_x_out_of_n_projects": "",
   "showing_x_out_of_n_users": "",
   "showing_x_results": "",
   "showing_x_results_of_total": "",
+  "showing_x_results_of_total_plural": "",
+  "showing_x_results_plural": "",
   "sidebar": "",
   "sign_up": "",
   "simple_search_mode": "",

+ 1 - 3
services/web/frontend/js/features/pdf-preview/components/compile-timeout-paywall-modal.tsx

@@ -191,9 +191,7 @@ export function CompileTimeoutPaywallModal({
                 <strong>{t('compile_timeout_modal_intro')}</strong>
               </p>
               <div className="compile-time-paywall-feature-list">
-                <ListItem>
-                  {t('collabs_per_proj', { collabcount: 10 })}
-                </ListItem>
+                <ListItem>{t('collabs_per_proj', { count: 10 })}</ListItem>
                 <ListItem>{t('track_changes')}</ListItem>
                 <ListItem>{t('github_integration')}</ListItem>
                 <ListItem>{t('and_much_more')}</ListItem>

+ 1 - 1
services/web/frontend/js/features/project-list/components/load-more.tsx

@@ -21,7 +21,7 @@ export default function LoadMore() {
             className="project-list-load-more-button"
             onClick={() => loadMoreProjects()}
           >
-            {t('show_x_more_projects', { x: loadMoreCount })}
+            {t('show_x_more_projects', { count: loadMoreCount })}
           </OLButton>
         </>
       ) : null}

+ 1 - 7
services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx

@@ -38,13 +38,7 @@ function GroupPlanCollaboratorCount({ planCode }: { planCode: string }) {
   const { t } = useTranslation()
 
   if (planCode === 'collaborator') {
-    return (
-      <>
-        {t('collabs_per_proj', {
-          collabcount: 10,
-        })}
-      </>
-    )
+    return <>{t('collabs_per_proj', { count: 10 })}</>
   } else if (planCode === 'professional') {
     return <>{t('unlimited_collabs')}</>
   }

+ 2 - 2
services/web/frontend/js/shared/components/upgrade-prompt.tsx

@@ -107,7 +107,7 @@ export function UpgradePrompt({
                   {t('24x_more_compile_time')}
                 </IconListItem>
                 <IconListItem icon="group_add">
-                  {t('collabs_per_proj', { collabcount: 10 })}
+                  {t('collabs_per_proj', { count: 10 })}
                 </IconListItem>
                 <IconListItem icon="history">
                   {t('unlimited_document_history')}
@@ -145,7 +145,7 @@ export function UpgradePrompt({
                   {t('basic_compile_time')}
                 </IconListItem>
                 <IconListItem icon="person">
-                  {t('collabs_per_proj_single', { collabcount: 1 })}
+                  {t('collabs_per_proj', { count: 1 })}
                 </IconListItem>
                 <IconListItem icon="history_off">
                   {t('limited_document_history')}

+ 2 - 1
services/web/locales/cs.json

@@ -43,7 +43,8 @@
   "close": "Zavřít",
   "collaboration": "Spolupráce",
   "collaborator": "Collaborator",
-  "collabs_per_proj": "__collabcount__ spolupracovníků na projektu",
+  "collabs_per_proj": "__count__ spolupracovník na projektu",
+  "collabs_per_proj_plural": "__count__ spolupracovníků na projektu",
   "comment": "Komentář",
   "common": "Běžné",
   "compiler": "Kompilátor",

+ 10 - 8
services/web/locales/da.json

@@ -268,8 +268,8 @@
   "collaboration": "Samarbejde",
   "collaborator": "Samarbejdspartner",
   "collabratec_account_not_registered": "IEEE Collabratec™ konto er ikke registeret. Forbind til Overleaf from IEEE Collabratec™ eller log ind med en anden konto.",
-  "collabs_per_proj": "__collabcount__ samarbejdspartnere per projekt",
-  "collabs_per_proj_single": "__collabcount__ samarbejdspartnere per projekt",
+  "collabs_per_proj": "__count__ samarbejdspartner per projekt",
+  "collabs_per_proj_plural": "__count__ samarbejdspartnere per projekt",
   "collapse": "Fold sammen",
   "column_width": "Kolonnebredde",
   "column_width_is_custom_click_to_resize": "Kolonnebredden er brugerdefineret. Klik for at ændre",
@@ -1100,7 +1100,8 @@
   "n_more_updates_above_plural": "__count__ flere opdateringer ovenover",
   "n_more_updates_below": "__count__ mere opdatering nedenunder",
   "n_more_updates_below_plural": "__count__ flere opdateringer nedenunder",
-  "n_users": "__userCount__ brugere",
+  "n_users": "__count__ bruger",
+  "n_users_plural": "__count__ brugere",
   "name": "Navn",
   "name_usage_explanation": "Dit navn vil blive vist til dine samarbejdspartnere (så de ved hvem de arbejder sammen med).",
   "native": "Indbygget",
@@ -1643,12 +1644,13 @@
   "show_local_file_contents": "Vis lokalt filindhold",
   "show_more": "vis mere",
   "show_outline": "Vis disposition",
-  "show_x_more_projects": "Vis __x__ flere projekter",
-  "showing_1_result": "Viser 1 resultat",
-  "showing_1_result_of_total": "Viser 1 resultat ud af __total__",
+  "show_x_more_projects": "Vis __count__ mere projekt",
+  "show_x_more_projects_plural": "Vis __count__ flere projekter",
   "showing_x_out_of_n_projects": "Viser __x__ af __n__ projekter.",
-  "showing_x_results": "Viser __x__ resultater",
-  "showing_x_results_of_total": "Viser __x__ resultater ud af __total__",
+  "showing_x_results": "Viser __count__ resultat",
+  "showing_x_results_of_total": "Viser __count__ resultat ud af __total__",
+  "showing_x_results_of_total_plural": "Viser __count__ resultater ud af __total__",
+  "showing_x_results_plural": "Viser __count__ resultater",
   "sign_up": "Opret konto",
   "sign_up_for_free": "Opret gratis konto",
   "sign_up_for_free_account": "Opret gratis konto og modtag regelmæssige opdateringer",

+ 8 - 7
services/web/locales/de.json

@@ -328,8 +328,8 @@
   "collaboration": "Zusammenarbeit",
   "collaborator": "Mitarbeiter",
   "collabratec_account_not_registered": "IEEE-Collabratec™-Konto nicht registriert. Bitte verbinde dich mit Overleaf von IEEE Collabratec™ oder melde dich mit einem anderen Konto an.",
-  "collabs_per_proj": "__collabcount__ Mitarbeiter pro Projekt",
-  "collabs_per_proj_single": "__collabcount__ Mitarbeiter pro Projekt",
+  "collabs_per_proj": "__count__ Mitarbeiter pro Projekt",
+  "collabs_per_proj_plural": "__count__ Mitarbeiter pro Projekt",
   "collapse": "Einklappen",
   "comment": "Kommentar",
   "comment_only": "Nur Kommentare",
@@ -1360,12 +1360,13 @@
   "show_less": "Weniger anzeigen",
   "show_live_equation_previews_while_typing": "Live-Gleichungsvorschau beim Tippen anzeigen",
   "show_outline": "Dateigliederung anzeigen",
-  "show_x_more_projects": "__x__ weitere Projekte anzeigen",
-  "showing_1_result": "1 Ergebnis wird angezeigt",
-  "showing_1_result_of_total": "Zeige 1 Ergebnis von __total__",
+  "show_x_more_projects": "__count__ weiteres Projekt anzeigen",
+  "show_x_more_projects_plural": "__count__ weitere Projekte anzeigen",
   "showing_x_out_of_n_projects": "Es werden __x__ von __n__ Projekten angezeigt.",
-  "showing_x_results": "Es werden __x__ Ergebnisse angezeigt",
-  "showing_x_results_of_total": "Es werden __x__ Ergebnisse von __total__ angezeigt",
+  "showing_x_results": "Es wird __count__ Ergebnis angezeigt",
+  "showing_x_results_of_total": "Es wird __count__ Ergebnis von __total__ angezeigt",
+  "showing_x_results_of_total_plural": "Es werden __count__ Ergebnisse von __total__ angezeigt",
+  "showing_x_results_plural": "Es werden __count__ Ergebnisse angezeigt",
   "single_sign_on_sso": "Single Sign-On (SSO)",
   "site_description": "Ein einfach bedienbarer Online-LaTeX-Editor. Keine Installation notwendig, Zusammenarbeit in Echtzeit, Versionskontrolle, Hunderte von LaTeX-Vorlagen und mehr",
   "skip_to_content": "Zum Inhalt springen",

+ 12 - 11
services/web/locales/en.json

@@ -423,11 +423,11 @@
   "collaborators_per_project": "Collaborators per project",
   "collaborators_per_project_explanation": "The number of editors and reviewers you can invite to collaborate on a project with you. The limit is per project and you can invite different people to different projects.",
   "collabratec_account_not_registered": "IEEE Collabratec™ account not registered. Please connect to Overleaf from IEEE Collabratec™ or log in with a different account.",
-  "collabs_per_proj": "__collabcount__ collaborators per project",
+  "collabs_per_proj": "__count__ collaborator per project",
   "collabs_per_proj_multiple": "Multiple collaborators per project",
-  "collabs_per_proj_plus": "__collabcount__ collaborators per project, plus:",
-  "collabs_per_proj_single": "__collabcount__ collaborator per project",
-  "collabs_per_proj_single_plus": "__collabcount__ collaborator per project, plus:",
+  "collabs_per_proj_plural": "__count__ collaborators per project",
+  "collabs_per_proj_plus": "__count__ collaborator per project, plus:",
+  "collabs_per_proj_plus_plural": "__count__ collaborators per project, plus:",
   "collapse": "Collapse",
   "column_width": "Column width",
   "column_width_is_custom_click_to_resize": "Column width is custom. Click to resize",
@@ -1611,7 +1611,8 @@
   "n_more_updates_above_plural": "__count__ more updates above",
   "n_more_updates_below": "__count__ more update below",
   "n_more_updates_below_plural": "__count__ more updates below",
-  "n_users": "__userCount__ users",
+  "n_users": "__count__ user",
+  "n_users_plural": "__count__ users",
   "name": "Name",
   "name_usage_explanation": "Your name will be displayed to your collaborators (so they know who they’re working with).",
   "native": "Native",
@@ -1727,7 +1728,6 @@
   "one_free_collab": "One free collaborator",
   "one_per_project": "1 per project",
   "one_step_away_from_professional_features": "You are one step away from accessing <0>Overleaf premium features</0>!",
-  "one_user": "1 user",
   "ongoing_experiments": "Ongoing experiments",
   "online_latex_editor": "Online LaTeX Editor",
   "only_add_people_who_dont_yet_have_access": "Only add people who don’t yet have access.",
@@ -2360,14 +2360,15 @@
   "show_more": "show more",
   "show_outline": "Show File outline",
   "show_version_history": "Show version history",
-  "show_x_more_projects": "Show __x__ more projects",
-  "showing_1_result": "Showing 1 result",
-  "showing_1_result_of_total": "Showing 1 result of __total__",
+  "show_x_more_projects": "Show __count__ more project",
+  "show_x_more_projects_plural": "Show __count__ more projects",
   "showing_pdf_preview_with_inverted_colors": "Showing PDF preview with inverted colors",
   "showing_x_out_of_n_projects": "Showing __x__ out of __n__ projects.",
   "showing_x_out_of_n_users": "Showing __x__ out of __n__ users",
-  "showing_x_results": "Showing __x__ results",
-  "showing_x_results_of_total": "Showing __x__ results of __total__",
+  "showing_x_results": "Showing __count__ result",
+  "showing_x_results_of_total": "Showing __count__ result of __total__",
+  "showing_x_results_of_total_plural": "Showing __count__ results of __total__",
+  "showing_x_results_plural": "Showing __count__ results",
   "sidebar": "Sidebar",
   "sign_up": "Sign up",
   "sign_up_for_free": "Sign up for free",

+ 2 - 1
services/web/locales/es.json

@@ -218,7 +218,8 @@
   "cn": "Chino (simplificado)",
   "collaboration": "Colaboración",
   "collaborator": "Colaborador",
-  "collabs_per_proj": "__collabcount__ colaboradores por proyecto",
+  "collabs_per_proj": "__count__ colaborador por proyecto",
+  "collabs_per_proj_plural": "__count__ colaboradores por proyecto",
   "comment": "Comentar",
   "common": "Común",
   "compile_error_entry_description": "Un error ha impedido la compilación de este proyecto",

+ 2 - 1
services/web/locales/fi.json

@@ -45,7 +45,8 @@
   "cn": "Kiina (Yksinkertainen)",
   "collaboration": "Yhteistyö",
   "collaborator": "Työtoveri",
-  "collabs_per_proj": "__collabcount__ työtoveria per projekti",
+  "collabs_per_proj": "__count__ työtoveri per projekti",
+  "collabs_per_proj_plural": "__count__ työtoveria per projekti",
   "comment": "Kommentoi",
   "common": "Yleisiä",
   "compiler": "Kääntäjä",

+ 6 - 6
services/web/locales/fr.json

@@ -221,8 +221,8 @@
   "collaboration": "Collaboration",
   "collaborator": "Collaborateur·rice",
   "collabratec_account_not_registered": "Pas de compte IEEE Collabratec™ enregistré. Veuillez vous connecter à Overleaf via IEEE Collabratec™ ou bien vous connecter avec un compte différent.",
-  "collabs_per_proj": "__collabcount__ collaborateur·rice·s par projet",
-  "collabs_per_proj_single": "__collabcount__ collaborateurs par projet",
+  "collabs_per_proj": "__count__ collaborateur·rice par projet",
+  "collabs_per_proj_plural": "__count__ collaborateur·rice·s par projet",
   "collapse": "Replier",
   "column_width": "Largeur de colonne",
   "column_width_is_custom_click_to_resize": "La largeur des colonnes est personnalisée. Cliquez pour redimensionner",
@@ -984,11 +984,11 @@
   "sharelatex_beta_program": "Programme de bêta __appName__",
   "show_less": "voir moins",
   "show_outline": "Afficher la structure du fichier",
-  "showing_1_result": "Affiche 1 résultat",
-  "showing_1_result_of_total": "Affiche 1 résultat sur __total__",
   "showing_x_out_of_n_projects": "Affiche __x__ sur __n__ projets.",
-  "showing_x_results": "Affiche __x__ résultats",
-  "showing_x_results_of_total": "Affiche __x__ résultats sur __total__",
+  "showing_x_results": "Affiche __count__ résultat",
+  "showing_x_results_of_total": "Affiche __count__ résultat sur __total__",
+  "showing_x_results_of_total_plural": "Affiche __count__ résultats sur __total__",
+  "showing_x_results_plural": "Affiche __count__ résultats",
   "sign_up": "S’inscrire",
   "site_description": "Un éditeur LaTeX en ligne facile à utiliser. Pas d’installation, collaboration en temps réel, gestion des versions, des centaines de modèles de documents LaTeX, et plus encore.",
   "skip_to_content": "Aller au contenu",

+ 2 - 1
services/web/locales/it.json

@@ -56,7 +56,8 @@
   "cn": "Cinese (Semplificato)",
   "collaboration": "Collaborazione",
   "collaborator": "Collaboratore",
-  "collabs_per_proj": "__collabcount__ collaboratori per progetto",
+  "collabs_per_proj": "__count__ collaboratore per progetto",
+  "collabs_per_proj_plural": "__count__ collaboratori per progetto",
   "comment": "Commento",
   "common": "Comune",
   "compile_larger_projects": "Compila progetti più grandi",

+ 1 - 1
services/web/locales/ja.json

@@ -75,7 +75,7 @@
   "cn": "中国語(簡体字)",
   "collaboration": "コラボレーション",
   "collaborator": "共同編集者",
-  "collabs_per_proj": "プロジェクトあたりの __collabcount__ 共同編集者",
+  "collabs_per_proj": "プロジェクトあたりの __count__ 共同編集者",
   "comment": "コメント",
   "common": "共通",
   "compile_larger_projects": "大きなプロジェクトをコンパイル",

+ 1 - 1
services/web/locales/ko.json

@@ -91,7 +91,7 @@
   "code_check_failed_explanation": "자동 컴파일 실행 전에 에러를 수정해야합니다.",
   "collaboration": "콜라보레이션",
   "collaborator": "콜라보레이터",
-  "collabs_per_proj": "프로젝트 당 __collabcount__명까지 공유 가능",
+  "collabs_per_proj": "프로젝트 당 __count__명까지 공유 가능",
   "comment": "댓글",
   "common": "일반",
   "compile_larger_projects": "큰 프로젝트 컴파일",

+ 2 - 1
services/web/locales/nl.json

@@ -91,7 +91,8 @@
   "cn": "Chinees (vereenvoudigd)",
   "collaboration": "Samenwerking",
   "collaborator": "Bijdrager",
-  "collabs_per_proj": "__collabcount__ bijdragers per project",
+  "collabs_per_proj": "__count__ bijdrager per project",
+  "collabs_per_proj_plural": "__count__ bijdragers per project",
   "comment": "Reageren",
   "common": "Veelvoorkomend",
   "compact": "Compact",

+ 2 - 1
services/web/locales/no.json

@@ -57,7 +57,8 @@
   "cn": "Kinesisk (Forenklet)",
   "collaboration": "Samarbeid",
   "collaborator": "Samarbeidspartner",
-  "collabs_per_proj": "__collabcount__ samarbeidspartnere per prosjekt",
+  "collabs_per_proj": "__count__ samarbeidspartner per prosjekt",
+  "collabs_per_proj_plural": "__count__ samarbeidspartnere per prosjekt",
   "comment": "Kommenter",
   "common": "Vanilige",
   "compile_larger_projects": "Kompiler Større Prosjekter",

+ 2 - 1
services/web/locales/pl.json

@@ -30,7 +30,8 @@
   "clearing": "Czyszczenie",
   "click_here_to_view_sl_in_lng": "Kliknij tutaj, żeby używać __appName__ w <0>__lngName__</0>m",
   "collaborator": "Współpracownik",
-  "collabs_per_proj": "__collabcount__ współpracowników na projekt",
+  "collabs_per_proj": "__count__ współpracownik na projekt",
+  "collabs_per_proj_plural": "__count__ współpracowników na projekt",
   "comment": "Skomentuj",
   "common": "Wspólne",
   "compiler": "Kompilator",

+ 2 - 1
services/web/locales/pt.json

@@ -106,7 +106,8 @@
   "code_check_failed_explanation": "Seu código contém erros que precisam ser corrigidos antes de rodar a auto-compilação",
   "collaboration": "Colaboração",
   "collaborator": "Colaborador",
-  "collabs_per_proj": "__collabcount__ colaboradores por projeto",
+  "collabs_per_proj": "__count__ colaborador por projeto",
+  "collabs_per_proj_plural": "__count__ colaboradores por projeto",
   "comment": "Comentário",
   "common": "Comum",
   "compact": "Compacto",

+ 1 - 1
services/web/locales/ru.json

@@ -88,7 +88,7 @@
   "cn": "Китайский (упрощённый)",
   "collaboration": "Совместная разработка",
   "collaborator": "Совместная работа",
-  "collabs_per_proj": "Максимальное число соавторов на проект: __collabcount__",
+  "collabs_per_proj": "Максимальное число соавторов на проект: __count__",
   "comment": "Комментарии",
   "common": "Общие",
   "compile_larger_projects": "Компиляция больших проектов",

+ 2 - 2
services/web/locales/sv.json

@@ -139,8 +139,8 @@
   "collaborate_online_and_offline": "Samarbeta online och offline, med ditt eget arbetsflöde",
   "collaboration": "Samarbete",
   "collaborator": "Samarbetare",
-  "collabs_per_proj": "__collabcount__ samarbetare per projekt",
-  "collabs_per_proj_single": "__collabcount__ medarbetare per projekt",
+  "collabs_per_proj": "__count__ samarbetare per projekt",
+  "collabs_per_proj_plural": "__count__ samarbetare per projekt",
   "collapse": "Kontrahera",
   "comment": "Kommentar",
   "common": "Vanliga",

+ 2 - 1
services/web/locales/tr.json

@@ -60,7 +60,8 @@
   "cn": "Çince (Basitleştirilmiş)",
   "collaboration": "İş birliği",
   "collaborator": "İş ortağı",
-  "collabs_per_proj": "her bir proje için __collabcount__ iş ortağı",
+  "collabs_per_proj": "her bir proje için __count__ iş ortağı",
+  "collabs_per_proj_plural": "her bir proje için __count__ iş ortağı",
   "comment": "Yorumlar",
   "common": "Belirli",
   "compiler": "Derleyici",

+ 5 - 8
services/web/locales/zh-CN.json

@@ -311,8 +311,7 @@
   "collaborator": "合作者",
   "collaborator_chat": "协作者聊天",
   "collabratec_account_not_registered": "未注册 IEEE Collabratec™ 帐户。请从IEEE Collabratec™连接到Overleaf 或者使用其他帐户登录。",
-  "collabs_per_proj": "每个项目 __collabcount__ 个合作者",
-  "collabs_per_proj_single": "__collabcount__ 个合作者每个项目",
+  "collabs_per_proj": "每个项目 __count__ 个合作者",
   "collapse": "合上",
   "column_width": "列宽",
   "column_width_is_custom_click_to_resize": "列宽为默认值,单击以调整大小",
@@ -1266,7 +1265,7 @@
   "n_more_updates_above_plural": "__count__处更新在上方",
   "n_more_updates_below": "__count__处更新在下方",
   "n_more_updates_below_plural": "__count__处更新在下方",
-  "n_users": "__userCount__ 个用户",
+  "n_users": "__count__ 个用户",
   "name": "名字",
   "name_usage_explanation": "您的名字将显示给您的合作者(以便他们知道正在与谁合作)。",
   "native": "本机",
@@ -1874,12 +1873,10 @@
   "show_more": "显示更多",
   "show_outline": "显示文件大纲",
   "show_version_history": "显示版本历史记录",
-  "show_x_more_projects": "再显示 __x__ 个项目",
-  "showing_1_result": "显示 1 个结果",
-  "showing_1_result_of_total": "显示 1 个结果(共计 __total__ )",
+  "show_x_more_projects": "再显示 __count__ 个项目",
   "showing_x_out_of_n_projects": "显示 __x__ 个项目(共 __n__ 个)",
-  "showing_x_results": "显示 __x__ 结果",
-  "showing_x_results_of_total": "显示  __x__ 个结果(共计__total__ )",
+  "showing_x_results": "显示 __count__ 结果",
+  "showing_x_results_of_total": "显示  __count__ 个结果(共计__total__ )",
   "sign_up": "注册",
   "sign_up_for_free": "免费注册",
   "sign_up_for_free_account": "注册免费帐户并接收定期更新",

+ 30 - 0
services/web/test/frontend/infrastructure/i18n.spec.tsx

@@ -144,4 +144,34 @@ describe('i18n', function () {
         .should('have.text', "<i>T</i>&<b>e</b>'s<code>t</code>ing")
     })
   })
+
+  describe('plurals', function () {
+    // See https://www.i18next.com/misc/json-format#i-18-next-json-v3
+    it('picks singular for count=1', function () {
+      const Test = () => {
+        const { t } = useTranslation()
+        return <div>{t('project_search_file_count', { count: 1 })}</div>
+      }
+      cy.mount(<Test />)
+      cy.findByText('in 1 file')
+    })
+
+    it('picks plural for count>1', function () {
+      const Test = () => {
+        const { t } = useTranslation()
+        return <div>{t('project_search_file_count', { count: 5 })}</div>
+      }
+      cy.mount(<Test />)
+      cy.findByText('in 5 files')
+    })
+
+    it('picks plural for count=0', function () {
+      const Test = () => {
+        const { t } = useTranslation()
+        return <div>{t('project_search_file_count', { count: 0 })}</div>
+      }
+      cy.mount(<Test />)
+      cy.findByText('in 0 files')
+    })
+  })
 })