Ответ
Правильная плюрализация — это не просто добавление 's'. В разных языках разное количество форм для множественного числа (например, в русском 3, в арабском — 6). Решение должно быть основано на стандартах ICU (Unicode).
1. Использование библиотеки Humanizer (Рекомендуемый подход)
Humanizer поддерживает множество языков и склонений, предоставляя простой API.
// Установите пакет: Install-Package Humanizer
using Humanizer;
// Плюрализация на английском
"apple".Pluralize(1); // "apple"
"apple".Pluralize(2); // "apples"
// Плюрализация на русском (требует установки культуры)
var culture = new System.Globalization.CultureInfo("ru-RU");
"сообщение".Pluralize(1, culture); // "сообщение"
"сообщение".Pluralize(2, culture); // "сообщения"
"сообщение".Pluralize(5, culture); // "сообщений"
// Форматирование строк с числительными
"Message".ToQuantity(5, ShowQuantityAs.Words); // "five messages" (en)
2. Использование .resx файлов с выбором формы по правилам
Для полного контроля можно хранить шаблоны в ресурсах, а выбор осуществлять по формуле. Для русского языка часто используется формула:
string GetRussianPluralForm(int number, string form1, string form2, string form5)
{
number = Math.Abs(number) % 100;
int n1 = number % 10;
if (number > 10 && number < 20) return form5;
if (n1 > 1 && n1 < 5) return form2;
if (n1 == 1) return form1;
return form5;
}
// В ресурсном файле Messages.ru.resx:
// PluralForm1: "{0} сообщение"
// PluralForm2: "{0} сообщения"
// PluralForm5: "{0} сообщений"
int count = 5;
string form = GetRussianPluralForm(count, PluralForm1, PluralForm2, PluralForm5);
string result = string.Format(form, count); // "5 сообщений"
3. Использование IStringLocalizer и Plural в ASP.NET Core
В современных приложениях ASP.NET Core фреймворк предоставляет встроенные средства.
// В ресурсном файле (например, Resources.ru.resx) можно использовать параметризованные ключи.
// На практике часто используют библиотеки, подобные `SmartFormat` или `MessageFormatter`,
// которые поддерживают плюрализацию по стандарту ICU прямо в строке шаблона.
// Пример со SmartFormat (пакет SmartFormat.NET)
using SmartFormat;
var message = Smart.Format("{0} {0:сообщение|сообщения|сообщений}", count);
4. Ключевые принципы:
- Не изобретайте велосипед: Для поддержки многих языков используйте проверенные библиотеки (
Humanizer,SmartFormat). - Отделяйте данные от шаблона: Число и строковый шаблон должны быть независимы.
- Тестируйте на пограничных значениях: 0, 1, 2, 5, 11, 21, 101.
- Учитывайте контекст: Иногда фраза "1 file(s) processed" лучше, чем сложная система склонений для редких языков в MVP.
Ответ 18+ 🔞
Слушай, вот смотри, плюрализация — это ж не просто тупо 's' накинуть, как многие думают. Ну типа, в русском три формы, в арабском их шесть, ёпта! Надо по стандартам ICU делать, а не костыли из говна и палок лепить.
1. Humanizer — это вообще огонь, бери его Ставишь пакетик и не паришься. Библиотека знает кучу языков и все эти ваши склонения.
// Поставил пакет и поехали
using Humanizer;
// По-английски
"apple".Pluralize(1); // "apple"
"apple".Pluralize(2); // "apples" — ну тут всё просто, да
// А вот по-русски уже интереснее, культуру надо указать
var culture = new System.Globalization.CultureInfo("ru-RU");
"сообщение".Pluralize(1, culture); // "сообщение"
"сообщение".Pluralize(2, culture); // "сообщения"
"сообщение".Pluralize(5, culture); // "сообщений" — вот, блядь, уже три разных формы!
// А ещё можно словами число выводить, для красоты
"Message".ToQuantity(5, ShowQuantityAs.Words); // "five messages"
2. Старый дедовский способ с .resx и своей функцией Если хочешь всё контролировать, как параноик, то вот тебе формула для русского языка. Выглядит страшновато, но работает.
string GetRussianPluralForm(int number, string form1, string form2, string form5)
{
number = Math.Abs(number) % 100; // На всякий случай от отрицательных
int n1 = number % 10;
if (number > 10 && number < 20) return form5; // 11, 12, 13...19 — всегда форма 5
if (n1 > 1 && n1 < 5) return form2; // 2, 3, 4 — форма 2
if (n1 == 1) return form1; // 1 — форма 1
return form5; // всё остальное — форма 5 (0, 5, 6, 7, 8, 9, 10, 20...)
}
// В ресурсах (Messages.ru.resx) заводишь три строки:
// PluralForm1: "{0} сообщение"
// PluralForm2: "{0} сообщения"
// PluralForm5: "{0} сообщений"
int count = 5;
string form = GetRussianPluralForm(count, PluralForm1, PluralForm2, PluralForm5);
string result = string.Format(form, count); // "5 сообщений"
3. В ASP.NET Core своя магия есть
Там можно через IStringLocalizer работать, но часто народ тянет SmartFormat, потому что он умеет плюрализацию прямо в строке шаблона, что очень удобно.
using SmartFormat;
// Глянь, как лаконично: прямо в строке три формы через '|'
var message = Smart.Format("{0} {0:сообщение|сообщения|сообщений}", count);
// Если count = 5, получится "5 сообщений"
4. Главное, что запомнить:
- Не выёбывайся и не пили велосипед: Есть
Humanizer, естьSmartFormat— бери и пользуйся. Зачем тебе эта головная боль на ровном месте? - Шаблоны отдельно, цифры отдельно: Не вшивай числа в готовые фразы, а то потом локализаторы тебя проклянут. Храни шаблоны в ресурсах.
- Тестируй на всём, особенно на краевых случаях: 0, 1, 2, 5, 11, 21, 101. Вот на 101 сообщении твой код и сломается, если накосячил.
- Смотри по контексту: Если делаешь MVP и там только английский, иногда проще написать "1 file(s) processed", чем городить систему на все языки мира. Но это уже на твоей совести, чувак.