Множинність у повідомленнях користувачів


106

Багато разів під час генерації повідомлень, які відображатимуться користувачеві, повідомлення буде містити ряд того, про що я хочу повідомити клієнта.

Наведу приклад: Клієнт вибрав ряд предметів від 1 і вище та натиснув видалити. Тепер я хочу надати клієнту повідомлення з підтвердженням, і хочу зазначити кількість вибраних ним елементів, щоб мінімізувати шанс помилки, вибравши купу елементів і натиснувши видалити, коли він хоче видалити лише один із їх.

Один із способів - зробити загальне повідомлення таким чином:

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

"Проблема" тут - випадок, коли noofitemselectedдорівнює 1, і ми повинні написати елемент і це замість елементів і їх .

Моє нормальне рішення буде чимось подібним

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

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

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

Отже, це в основному стосується більшості тексту, який певним чином виводиться з програм, і тоді рішення не таке просте, як просто змінити програму, щоб більше не виводити текст :)


6
@ 0xA3: Я не знаю, чи є в кожній мові множина, яка так само легко виражається як "предмет (и)".
Єнс

5
Напевно, ви також повинні думати про локалізацію. Це питання може стати набагато гіршим.
Алекс Браун

4
@Jens: Вони зазвичай не мають, принаймні зручних способів. Деякі мови мають, наприклад, різну плюралізацію для 2-4, ніж для 5-нескінченності, все це залежно від статі. "Природні мови: Локалізаційне божевілля! Незабаром скоро до комп'ютера!"
Пісквор вийшов з будівлі

29
IMO, ніщо не змушує програмістів виглядати ліньше для користувачів, ніж погана множина.
Грег

4
@ Øyvind: +1 для редагування. Здається, багато хто з "відповідачів" тут більше намагаються довести, що ваше питання неправильне, а не пропонувати правильне рішення. Анти-рішення, якщо хочете.
mwolfe02

Відповіді:


53

Якщо є будь-який шанс, незалежно від того, наскільки маленький, цю програму потрібно буде перекласти на інші мови, то обидві помиляються. Правильний спосіб зробити це:

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

Це тому, що різні мови по-різному обробляють множину. У таких, як малайська, навіть немає синтаксичних множин, тому рядки, як правило, будуть однаковими. Розділення двох рядків полегшує підтримку інших мов згодом.

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

Якщо ця програма призначена для споживання тільки внутрішньо вашою компанією, тоді зробіть ярлик "item(s)". Вам не потрібно нікого вражати при написанні коду підприємництва. Але я б радив не робити цього для публічно спожитого додатка, оскільки це створює враження, що програміст лінивий і тим самим знижує їх думку про якість цього додатка. Повірте, такі дрібні речі, як ця справа.


35
Хоча я згоден з цим припущенням, ви ігноруєте мови, які мають більш ніж два ступені множини. (Візьмемо для прикладу російську мову. Три різні способи вимови залежно від того, чи є її 1, <5 або> = 5 і навіть це залежить від того, про що ви конкретно говорите). В основному я кажу, що вам потрібна більш сильна умовна заява, а не просто потрійний оператор.
катастрофа

4
У noofitemsselectedцьому прикладі ви навіть можете оптимізувати перший варіант для першого варіанту; оскільки ви знаєте, що це 1.
Типово

16
Поки ми на цьому, іврит може мати різні множини для 1, 2, 3-10 та 11+.
Джоель Спольський

3
@Joel, іврит може мати стільки різних множин? לא ידעתי (я не знав)! Сучасний іврит схожий на англійську, наскільки множини (хоча давній іврит також мав подвійну форму.)
Кен Блум

3
Англійською мовою нуль трактується як множина (0 предметів, 2 предмети); що відбувається з нулем на івриті, російській, румунській мовах? Чи існує простий спосіб визначити діапазони? Я здогадуюсь, що інформацію потрібно визначати для кожної мови, тому будь-яка система, що базується на файлах повідомлень, має мати справу з різною кількістю множинності в наборі повідомлень. Ой! Налаштування перекладів теж було б складним - для різних мов потрібна різна кількість повідомлень.
Джонатан Леффлер

94

Ви можете уникнути всієї цієї безладної множинності, просто видаливши елементи без будь-якого повідомлення та надавши користувачеві дійсно хороший інструмент скасування. Користувачі ніколи нічого не читають . У будь-якому випадку ви повинні створити хороший засіб скасування як частину вашої програми.

Ви фактично отримуєте 2 переваги, коли створюєте всеохоплюючий інструмент скасування. Перша перевага полегшує життя користувача, дозволяючи йому / їй перевертати помилки та мінімізувати читання. Друга перевага полягає в тому, що ваш додаток відображає реальне життя, дозволяючи повернути нетривіальний робочий процес (не лише помилки).

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


12
Чомусь я справді відчуваю, що я згоден з цим, і мушу підтримати це.
Коді Грей

4
@ Øyvind, Ось чому: Повідомлення, які просять користувача перевірити, дорого користувачеві, особливо коли вони представлені у вигляді модального діалогового вікна, яке зупиняє все, поки користувач не відповість на діалог. Це дратує багатьох користувачів до того моменту, коли вони починають просто клацати будь-яку кнопку, щоб пройти повз діалогове вікно (скільки встановників ви тільки що натиснули наступний, наступний, наступний? ). Отже, це безпечніше, і тертя користувача значно менша, якщо ви просто робите м'яке видалення та надаєте можливість скасувати. Gmail використовує цю техніку для найкращого ефекту.
Роберт Харві

5
Дискусійний, але в будь-якому випадку те саме питання виникне у випадках, окрім повідомлення про підтвердження про видалення, тож ця відповідь справді дотична до питання.
Jay

50
я підтримував це, не читаючи його. Я завжди можу це скасувати пізніше
Стівен А. Лоу

6
@ Роберт Харві: Напевно, апокрифний, але багато років тому я прочитав, що Лотос відправив 40 000 одиниць Lotus Notes для Mac і 60 000 було повернуто. Інтерфейс був настільки поганий, що навіть люди, які його піратували, надсилали його назад.
Дункан

39

Як щодо:

string message = "Are you sure you want to delete " + noofitemsselected + " item(s)?"

Таким чином ви усуваєте труднощі з укладанням кількості номерів і в кінцевому підсумку отримуєте ще коротше, більш точне повідомлення про помилку для користувача, як бонус. Ми всі знаємо, що користувачі так і не читають повідомлення про помилки . Чим вони коротші, тим більше шансів на те, щоб принаймні поглянути на текст.

Або, озброївшись цим знанням, що користувачі не читають повідомлень про помилки, ви можете підійти до цього по-іншому. Пропустіть повідомлення про підтвердження цілком і просто надайте функцію скасування, яка працює просто, незалежно від того, що було видалено. Більшість користувачів вже звикли скасовувати операцію, коли помічають, що це було не те, чого вони хотіли, і, ймовірно, вважають цю поведінку більш природною, ніж мати справу з іншим дратівливим спливаючим вікном.


1
Хороша відповідь. Однак замовник просив в цьому випадку надати повідомлення про помилки у багатьох випадках, оскільки він вважав, що це найкращий підхід. Але зміна тексту може хоча б мінімізувати проблему та зробити її менш брудною.
Øyvind Bråthen

@ Øyvind: Досить справедливо. Оскільки ви маєте слідкувати за клієнтом, я б або взяв перший запропонований мною підхід, або використав файл ресурсів з функцією обробника. Я просто думав, що варто вказати на альтернативу, тому що це так легко забути. Чорт, я навіть не думав про це, поки не представив свою першу відповідь.
Коді Грей

Альтернативи вітаються. Ось чому я і дав йому +1 :)
Øyvind Bråthen

1
+1 за те, що не намагаються вирішити нерозв'язну проблему. І пам’ятайте закон Стіва Круга: Приберіть половину слів. Потім зробіть це ще раз. Я використовую: "Видалити {x} предмет (и)?"
Серж Вотьє

20

А як щодо того, що Java мала протягом багатьох років: java.text.MessageFormat та ChoiceFormat? Додаткову інформацію див. У розділі http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html .

MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
form.applyPattern(
   "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.");

Object[] testArgs = {new Long(12373), "MyDisk"};

System.out.println(form.format(testArgs));

// output, with different testArgs
output: The disk "MyDisk" are no files.
output: The disk "MyDisk" is one file.
output: The disk "MyDisk" are 1,273 files.

У вашому випадку ви хочете щось простіше:

MessageFormat form = new MessageFormat("Are you sure you want to delete {0,choice,1#one item,1<{0,number.integer} files}?");

Перевага такого підходу полягає в тому, що він добре працює з пакетами i18n, і ви можете забезпечити переклади належним чином для мов (як японська), які не мають поняття множини чи однини.


1
Цей підхід добре допомагає боротися з множинністю, але, на жаль, не справляється з гендерною ознакою. Вам потрібна інша рядок для кожного виду речі, яку можна видалити.
Містер Блискучий і Новий 安 宇

Якщо ви знаєте іменник, ви можете модифікувати речення для роботи з власним прикметником. Але так, вивчивши класичну грецьку мову, ви маєте іншу форму слова, засновану на іменниках чоловічого, жіночого або ніякого роду (прикметник набуває форми іменника, який він модифікує), а форма відрізняється залежно від його функції в реченні ( предмет, об’єкт тощо). Ми завжди можемо знайти випадки, коли одне рішення працює, а інше - ні. Ось так ява намагалися вирішити проблему. Ви все ще повинні бути обережними з тим, як формуєте формати повідомлень.
Берін Лорич

Ви завжди можете годувати рішення Java двома цілими числами, де друге вказує стать. (Насправді, гендерна угода, як правило, викликає занепокоєння просто тому, що випадки використання вмісту різних об'єктів у повідомлення рідше, ніж встановлення різних номерів одного і того ж об’єкта в повідомлення)
Кен Блум

12

Я б хотів не твердо кодувати повідомлення, але надаючи два повідомлення в окремий файл ресурсу. Подібно до

string DELETE_SINGLE = "You have selected {0} item. Are you sure you want to delete it?";
string DELETE_MULTI = "You have selected {0} items. Are you sure you want to delete them?";

а потім подавати їх у String.Format як

if(noofitemsselected == 1)
    messageTemplate = MessageResources.DELETE_SINGLE;
else
    messageTemplate = MessageResources.DELETE_MULTI;

string message = String.Format(messageTemplate, noofitemsselected)

Я думаю, що такий підхід простіше локалізувати та підтримувати. Усі повідомлення інтерфейсу користувача знаходитимуться в одній локації.


+1, мені подобається такий підхід. Хоча вам потрібно буде відслідковувати еквіваленти назви ресурсу.
За замовчуванням

11

Ви можете повністю усунути проблему, по-різному сформулювавши повідомлення.

string message = "The number of selected items is " + noofitemsselected + ". Are you sure you want to delete everything in this selection?";

10

Перше, що я запропонував би: використовувати string.Format. Це дозволяє зробити щось подібне:

int numOfItems = GetNumOfItems();
string msgTemplate;
msgTemplate = numOfItems == 1 ? "You selected only {0} item." : "Wow, you selected {0} items!";
string msg = string.Format(msgTemplate, numOfItems);

Крім того, у програмах WPF я бачив системи, де рядок ресурсів буде обмежено на два повідомлення: сингулярне та множинне повідомлення (або повідомлення нульове / одиничне / багато) навіть. Потім спеціальний конвертер може бути використаний для розбору цього ресурсу та використання відповідної (відформатованої) рядки, тож ваш Xaml виглядає приблизно так:

<TextBlock Text="{Binding numOfItems, Converter={StaticResource c:NumericMessageFormatter}, ConverterParameter={StaticResource s:SuitableMessageTemplate}}" />

7

Для англійської мовою багато відповідей вище. Для інших мов це складніше, оскільки множини залежать від роду іменника та слова, що закінчується. Деякі приклади французькою мовою:

Регулярне чоловіче:

Vous avez choisi 1 compte. Voulez-vous vraiment le supprimer.
Vous avez choisi 2 comptes. Voulez-vous vraiment les supprimer.

Регулярний жіночий

Vous avez choisi 1 table. Voulez-vous vraiment la supprimer.
Vous avez choisi 2 tables. Voulez-vous vraiment les supprimer.

Нерегулярний чоловічий (закінчується 's')

Vous avez choisi 1 pays. Voulez-vous vraiment le supprimer.
Vous avez choisi 2 pays. Voulez-vous vraiment les supprimer?

Така ж проблема існує в більшості латинських мов, а в німецькій чи російській мовах стає гірше, де є три статі (чоловічий, жіночий та нікерівний).

Вам потрібно подбати, якщо ваша мета - обробляти більше, ніж просто англійською.


Принаймні в моєму випадку це насправді не проблема. Для кожного тексту, який я хочу вставити число, я буду знати, що таке іменник при генерації рядка. Але для прийняття більш загального рішення я згоден з вами, що змусити його працювати на "всіх" мовах може бути дуже важким, якщо не неможливим завданням.
Øyvind Bråthen

1
Або візьміть польську, де форма множини використовуваного іменника відрізняється залежно від числа! : /
UpTheCreek

5

Щоб мати можливість множинні повідомлення, які можна буде правильно локалізувати, я вважаю, що було б розумно спершу створити шар непрямості між номером та повідомленням.

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

get_message(DELETE_WARNING, quantity)

Далі створіть словник, який містить можливі повідомлення та варіанти, та повідомте про варіанти, коли вони повинні використовуватися.

DELETE_WARNING = {
   1: 'Are you sure you want to delete %s item',
   >1: 'Are you sure you want to delete %s items'
   >5: 'My language has special plural above five, do you wish to delete it?'
}

Тепер ви можете просто знайти ключ, який відповідає quantityзначенню та інтерполювати значення quantityцього повідомлення.

Це надто спрощений і наївний приклад, але я насправді не бачу іншого розумного способу зробити це і зможу забезпечити гарну підтримку для L10N та I18N.


5

Вам доведеться перевести функцію нижче з VBA в C #, але ваше використання зміниться на:

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

У мене є функція VBA, яку я використовую в MS Access, щоб робити саме те, про що ви говорите. Я знаю, що я буду зламаний на шматки для розміщення VBA, але тут все одно. Алгоритм повинен бути зрозумілий з коментарів:

'---------------------------------------------------------------------------------------'
' Procedure : Pluralize'
' Purpose   : Formats an English phrase to make verbs agree in number.'
' Usage     : Msg = "There [is/are] # record[s].  [It/They] consist[s/] of # part[y/ies] each."'
'             Pluralize(Msg, 1) --> "There is 1 record.  It consists of 1 party each."'
'             Pluralize(Msg, 6) --> "There are 6 records.  They consist of 6 parties each."'
'---------------------------------------------------------------------------------------'
''
Function Pluralize(Text As String, Num As Variant, Optional NumToken As String = "#")
Const OpeningBracket = "\["
Const ClosingBracket = "\]"
Const DividingSlash = "/"
Const CharGroup = "([^\]]*)"  'Group of 0 or more characters not equal to closing bracket'
Dim IsPlural As Boolean, Msg As String, Pattern As String

    On Error GoTo Err_Pluralize

    If IsNumeric(Num) Then
        IsPlural = (Num <> 1)
    End If

    Msg = Text

    'Replace the number token with the actual number'
    Msg = Replace(Msg, NumToken, Num)

    'Replace [y/ies] style references'
    Pattern = OpeningBracket & CharGroup & DividingSlash & CharGroup & ClosingBracket
    Msg = RegExReplace(Pattern, Msg, "$" & IIf(IsPlural, 2, 1))

    'Replace [s] style references'
    Pattern = OpeningBracket & CharGroup & ClosingBracket
    Msg = RegExReplace(Pattern, Msg, IIf(IsPlural, "$1", ""))

    'Return the modified message'    
    Pluralize = Msg
End Function

Function RegExReplace(SearchPattern As String, _
                      TextToSearch As String, _
                      ReplacePattern As String) As String
Dim RE As Object

    Set RE = CreateObject("vbscript.regexp")
    With RE
        .MultiLine = False
        .Global = True
        .IgnoreCase = False
        .Pattern = SearchPattern
    End With

    RegExReplace = RE.Replace(TextToSearch, ReplacePattern)
End Function

Використання трохи відрізалося в коментарях до коду вище, тому я повторю це тут:

Msg = "There [is/are] # record[s]. [It/They] consist[s/] of # part[y/ies] each."

Pluralize(Msg, 1) --> "There is 1 record.  It consists of 1 party each."
Pluralize(Msg, 6) --> "There are 6 records.  They consist of 6 parties each."

Так, це рішення ігнорує мови, які не є англійською. Чи це має значення, залежить від ваших вимог.


4

Ви можете створити множину автоматично, див. генератор множини .

Про правила генерації множини див. У Вікіпедії

string msg = "Do you want to delete " + numItems + GetPlural(" item", numItems) + "?";

Мені подобається використовувати цей метод, якщо додаток не інтернаціоналізується. Пуралізація призводить до більш відшліфованого застосування.
cspolton

1
Це дуже важко інтернаціоналізувати, і це часто виходить з ладу англійською мовою, наприклад, "У вас є замовлення + numMice + GetPlural (" миша ", numMice)"
Джеймс Андерсон

@James Anderson: Зараз це не найкращий граматичний приклад ;-) Не потрапляйте в пастку думок, що використання методу GetPural є єдиним методом, який ви можете використовувати.
cspolton

в поєднанні з ще кількома функціями для обробки ще кількох кутових справ, я думаю, що це дуже хороше рішення, але не коротше.
lalli

4

Як щодо більш загального способу. Уникайте плюралізації у другому реченні:

Кількість вибраних елементів, які потрібно видалити: не вибрано жодних файлів.
Ти впевнений?

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


"Вибрані елементи, які потрібно видалити:" не звучать правильно, речення вказує список імен, але друкується номер. Навіть якщо змінити на "Кількість елементів, які потрібно видалити:", все-таки "елементи" незручно.
lalli

@lalli: Так, формулювання не є досконалим, і жодне із запропонованих рішень не звучить ідеально. Я лише пропоную поставити його у такій формі, як етикетка та значення. Ви маєте рацію щодо додавання Number(я відповідав, коли качав дитину спати).
Даносаура

4

Мій загальний підхід - написати "єдину / множину", наприклад:

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, "дитина", "діти") тощо.

Звичайно, це працює лише для англійської мови, але ця концепція легко поширюється на мови зі складнішими закінченнями.

Мені здається, що ви можете зробити останній параметр необов’язковим для легкого випадку:

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;
}

1
Мені подобається ваша остання частина, де ви використовуєте значення за замовчуванням, щоб "unclutterize" код у випадку операції за замовчуванням додавання s для множини іменника.
Øyvind Bråthen

4

Інтернаціоналізація

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

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

GNU Gettext знаходиться під LGPL. ngettextназивається GettextResourceManager.GetPluralStringв порту C # Gettext.

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


3

Як щодо написання функції, як

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
ви не замислювались над цим, чи ви знайомі, у вас є функція сортувати множення чи ні за реченням, тоді ви переходите класти "це / їх" в кінці lol
Barkermn01

Вам слід просто передати цій функції два повідомлення для всього речення.
Кен Блум

Це був лише приклад. Я розумію, що варіант надсилати цілі речення є більш правильним.
Павло Моршенюк

3

Для першої проблеми, я маю на увазі Pluralize, ви можете використовувати Inflector .

А для другого, ви можете використовувати розширення представлення рядків з такою назвою, як ToPronounString.


3

У мене було таке саме запитання, яке поставив мені вчора член нашої команди.

Оскільки він знову з'явився тут, на 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();
}

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

2

З моєї точки зору, ваше перше рішення є найбільш підходящим. Чому я кажу, що це, якщо вам потрібна програма для підтримки декількох мов, другий варіант може бути кропітким. При кулаковому підході легко локалізувати текст без особливих зусиль.


2

Ви можете перейти до більш загального повідомлення на зразок "Ви впевнені, що хочете видалити вибрані елементи".


3
Це звичайно спрацьовує, але я думаю, що ідея запитувача показати кількість елементів, які збираються видалити з першого погляду, є хорошою. Не раз я намагався видалити файл зі свого робочого столу і випадково видалив більше одного файлу.
Коді Грей

2

Я залежить від того, яке приємне повідомлення ви хочете мати. Від найлегшого до найважчого:

  1. Перепишіть своє повідомлення про помилку, щоб уникнути плюралізації. Не так приємно для вашого користувача, але швидше.

  2. Використовуйте більш загальну мову, але все ж включайте число (-и).

  3. Використовуйте "плюралізацію" та систему інфлектора ala Rails, так що ви можете сказати pluralize(5,'bunch')і отримати 5 bunches. Рейки мають для цього хороший зразок.

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

Який варіант ви будете використовувати, залежить від ваших цілей продукту. - ndp


2

Чому ви хочете представити повідомлення, яке можуть насправді зрозуміти користувачі? Це суперечить 40-річній історії програмування. Nooooo, у нас справа хороша, не псуйте це зрозумілими повідомленнями.


(д / к)


+1: тут також добре бачити гумор. Але навіть якщо ви жартуєте, я розумію вашу основу. У багатьох багатьох програмах, створених протягом років, є надзвичайно погані повідомлення. Зазвичай тому, що вони так чи інакше отримують технічну можливість для нормального користувача.
Øyvind Bråthen

Гарна думка. Мені завжди подобається, коли я отримую повідомлення на кшталт "Помилка 494-B при введенні користувача" - це додає тієї додаткової маленької таємниці про те, що не так, що робить життя набагато цікавішим. Нещодавно я отримав помилку при спробі створити пароль, який просто сказав: "Пароль не відповідає вимогам безпеки". Жодного натяку тільки на те, якої вимоги я не відповідав. Мій пароль містив великі і малі літери та кілька цифр. Я спробував додати соціальний характер. Все ще ні. Це нарешті минуло, коли я ВИДАЛИ персонажа. Я думаю, у них було правило, що ти не можеш мати одного і того ж символу двічі поспіль.
Jay



0

Один із підходів, про який я не бачив, - це використання тегу заміни / вибору (наприклад, щось на кшталт "Ви збираєтеся розчавити {0} [? I ({0} = 1): / cactus / cacti /]". (іншими словами, вираз у форматі вказує на підстановку на основі того, чи дорівнює нулю аргументу, прийнятим як ціле число, рівний 1). Я бачив такі теги, які використовувались за дні до .net; я не знаю жодного стандартний для них у .net, і я не знаю найкращого способу їх форматування.


0

Я б задумався за хвилину, всі пропозиції тут або робити плюралізацію (і турбуватися про більше ніж 1 рівень плюралізації, стать та ін.), Або взагалі не використовувати її і приємно скасувати.

Я б пішов немовним способом і використовував для цього візуальні черги. наприклад, уявіть додаток Iphone, який ви вибираєте, витираючи палець. перед тим, як видалити їх за допомогою головної кнопки видалення, вона "похитне" вибрані елементи та покаже вам знак питання під заголовком із кнопками V (ok) або X (скасувати) ...

Або в 3D-світі Kinekt / Move / Wii - уявіть собі, як вибираєте файли, переміщаєте руку до кнопки видалення і, щоб сказати, перемістіть руку над головою для підтвердження (використовуючи ті ж візуальні символи, як я згадував раніше. Наприклад, замість цього прохання видалити 3 файли? Він покаже вам три файли з наведенням напівпрозорого червоного червоного кольору на X та скаже вам зробити щось для підтвердження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.