Множественность пользовательских сообщений - PullRequest
106 голосов
/ 23 ноября 2010

Часто при создании сообщений для показа пользователю сообщение будет содержать число что-то , о котором я хочу сообщить клиенту.

Я приведу пример: клиент выбрал количество товаров от 1 и выше и нажал кнопку удаления. Теперь я хочу отправить клиенту подтверждающее сообщение и упомянуть количество выбранных им предметов, чтобы свести к минимуму вероятность того, что он допустил ошибку, выбрав несколько предметов и нажав «Удалить», когда он хочет удалить только один из им.

Один из способов - сделать общее сообщение следующим образом:

int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " item(s). Are you sure you want to delete it/them?";

«Проблема» здесь - это случай, когда noofitemselected равен 1, и мы должны написать item и it вместо items и их .

Мое нормальное решение будет примерно таким

int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " " + (noofitemsselected==1?"item" : "items") + ". Are you sure you want to delete " + (noofitemsselected==1?"it" : "them") + "?";

Это становится довольно длинным и довольно неприятным, очень быстрым, если в коде много ссылок на множество чисел, а реальное сообщение становится трудным для чтения.

Так что мои вопросы просты. Есть ли более эффективные способы создания таких сообщений?

EDIT

Я вижу, что многие люди очень зациклились на том, что я упомянул, что сообщение должно отображаться в окне сообщения, и просто дал ответ о том, как вообще не использовать окно сообщения, и что все хорошо.

Но помните, что проблема плюрализации распространяется и на тексты в других местах программы, помимо окон сообщений. Например, метка рядом с сеткой, отображающая количество линий, выбранных в сетке, будет иметь ту же проблему в отношении плюрализации.

Таким образом, это в основном относится к большей части текста, который каким-то образом выводится из программ, и тогда решение не так просто, как просто изменить программу так, чтобы она больше не выводила текст:)

Ответы [ 25 ]

4 голосов
/ 23 ноября 2010

Вы можете генерировать множественное число автоматически, см., Например. множественный генератор .

Правила генерации множественного числа см. wikipedia

string msg = "Do you want to delete " + numItems + GetPlural(" item", numItems) + "?";
4 голосов
/ 24 ноября 2010

Интернационализация

Я предполагаю, что вам нужна поддержка интернационализации, и в этом случае разные языки имеют разные шаблоны для множественного числа (например, специальная форма множественного числа для 2 или более сложных языков, таких как польский), и вы можетеЧтобы исправить это, положитесь на простой шаблон.

Вы можете использовать функцию GNU Gettext ngettext и предоставить два английских сообщения в исходном коде.Gettext обеспечит инфраструктуру для выбора из других (потенциально более) сообщений при переводе на другие языки.См. http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html для полного описания поддержки множественного числа в GNU gettext.

GNU Gettext находится под LGPL.ngettext назван GettextResourceManager.GetPluralString в C # -порте Gettext.

(Если вам не нужна поддержка локализации и вы не хотите использовать Gettext сразу, напишите свою собственную функцию, которая делает этодля английского языка и передайте ему два полных сообщения , таким образом, если вам понадобится l10n позже, вы можете добавить, переписав одну функцию.)

4 голосов
/ 24 ноября 2010

Мой общий подход состоит в том, чтобы написать «одну / множественную функцию», например:

public static string noun(int n, string single, string plural)
{
  if (n==1)
    return single;
  else
    return plural;
}

Затем в теле сообщения я вызываю эту функцию:

string message="Congratulations! You have won "+n+" "+noun(n, "foobar", "foobars")+"!";

Это не намного лучше, но, по крайней мере, это (а) помещает решение в функцию и поэтому немного загромождает код, а (б) является достаточно гибким, чтобы обрабатывать неправильные множественные числа.то есть достаточно легко произнести существительное (n, «child», «children») и т. п.

Конечно, это работает только для английского языка, но концепция легко расширяема для языков с более сложными окончаниями.

Мне приходит в голову, что вы можете сделать последний параметр необязательным для простого случая:

public static string noun(int n, string single, string plural=null)
{
  if (n==1)
    return single;
  else if (plural==null)
    return single+"s";
  else
    return plural;
}
4 голосов
/ 23 ноября 2010

Как насчет более общего способа. Избегайте множественного числа во втором предложении:

Number of selected items to be deleted: noofitemsselected.
Are you sure?

Я обнаружил, что при таком способе в конце строки ставится число, которое действительно легко обнаружить Это решение будет работать с той же логикой на любом языке.

3 голосов
/ 23 ноября 2010

Как насчет написать функцию, как

string GetOutputMessage(int count, string oneItemMsg, string multiItemMsg)
{
 return string.Format("{0} {1}", count, count > 1 ? multiItemMsg : oneItemMsg);
}

.. и использовать его когда нужно?

string message = "You have selected " + GetOutputMessage(noofitemsselected,"item","items") + ". Are you sure you want to delete it/them?";
3 голосов
/ 23 ноября 2010

Для первой проблемы, я имею в виду Pluralize, вы можете использовать Inflector .

А для второй вы можете использовать расширение строкового представления с именем, например ToPronounString.

3 голосов
/ 23 ноября 2010

Мне задали тот же вопрос вчера один из членов нашей команды.

С тех пор, как он снова появился здесь, в StackOverflow, я решил, что вселенная говорит мне, что нужно попытаться найти достойное решение.

Я быстро соединил что-то, и это ни в коем случае не идеально, однако это могло бы быть полезным или вызвать некоторую дискуссию / разработку.

Этот код основан на идее, что может быть 3 сообщения. Один для нулевых элементов, один для одного элемента и один для более чем одного элемента, которые имеют следующую структуру:

singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural

Я создал внутренний класс для тестирования, чтобы имитировать класс ресурсов. Я еще не проверял это с использованием фактического файла ресурсов, поэтому мне еще предстоит увидеть полный результат.

Вот код (в настоящее время я включил несколько обобщений, где я знаю, что я мог бы указать третий параметр просто как тип, а также второй параметр - строку, я думаю, что есть способ объединить эти два параметра в нечто лучшее но я вернусь к этому, когда у меня будет свободное время.

    public static string GetMessage<T>(int count, string resourceSingularName, T resourceType) where T : Type
{
    var resourcePluralName = resourceSingularName + "_Plural";
    var resourceZeroName = resourceSingularName + "_Zero";
    string resource = string.Empty;
    if(count == 0)
    {
        resource = resourceZeroName;
    }
    else{
        resource = (count <= 1)? resourceSingularName : resourcePluralName;
    }
    var x = resourceType.GetProperty(resource).GetValue(Activator.CreateInstance(resourceType),null);

    return x.ToString();
}

Тестовый класс ресурсов:

internal class TestMessenger
{
    public string Tester{get{
    return "Hello World of one";}}
    public string Tester_Zero{get{
    return "Hello no world";}}
    public string Tester_Plural{get{
    return "Hello Worlds";}}
}

и мой метод быстрого выполнения

void Main()
{
    var message = GetMessage(56, "Tester",typeof(TestMessenger));
    message.Dump();
}
2 голосов
/ 23 ноября 2010

Я зависит от того, какое приятное сообщение вы хотите получить.От самого простого к сложному:

  1. Перепишите ваше сообщение об ошибке, чтобы избежать множественного числа.Не так хорошо для вашего пользователя, но быстрее.

  2. Используйте более общий язык, но все равно включите число (а).

  3. Использовать ""множественное число" и инфлекторная система аля Rails, так что вы можете сказать pluralize(5,'bunch') и получить 5 bunches.У Rails есть хороший шаблон для этого.

  4. Для интернационализации вам нужно взглянуть на то, что обеспечивает Java.Это будет поддерживать широкий спектр языков, в том числе те, которые имеют различные формы прилагательных с 2 или 3 предметами.Решение "s" ориентировано на английский язык.

Какой вариант вы выберете, зависит от целей вашего продукта.- ндп

2 голосов
/ 23 ноября 2010

Вы можете перейти к более общему сообщению типа «Вы уверены, что хотите удалить выбранные элементы?».

2 голосов
/ 23 ноября 2010

С моей точки зрения, ваше первое решение является наиболее подходящим. Почему я говорю так: если вам нужно приложение для поддержки нескольких языков, второй вариант может быть кропотливым При первом подходе текст легко локализуется без особых усилий.

...