Pluralitas dalam pesan pengguna

106

Sering kali, saat membuat pesan untuk ditampilkan kepada pengguna, pesan tersebut akan berisi sejumlah hal yang ingin saya informasikan kepada pelanggan.

Saya akan memberikan contoh: Pelanggan telah memilih sejumlah item dari 1 dan lebih tinggi, dan mengklik hapus. Sekarang saya ingin memberikan pesan konfirmasi kepada pelanggan, dan saya ingin menyebutkan jumlah item yang telah dia pilih untuk meminimalkan kemungkinan dia melakukan kesalahan dengan memilih sekumpulan item dan mengklik hapus ketika dia hanya ingin menghapus salah satu mereka.

Salah satu caranya adalah dengan membuat pesan umum seperti ini:

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

"Masalah" di sini adalah kasus di mana noofitemselectedadalah 1, dan kita harus menulis barang dan itu bukan item dan mereka .

Solusi normal saya akan menjadi seperti ini

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

Ini menjadi cukup panjang dan sangat buruk sangat cepat jika ada banyak referensi ke jamak angka di dalam kode, dan pesan yang sebenarnya menjadi sulit untuk dibaca.

Jadi pertanyaan saya sederhana. Apakah ada cara yang lebih baik untuk menghasilkan pesan seperti ini?

EDIT

Saya melihat banyak orang menjadi sangat terpaku jika saya menyebutkan bahwa pesan harus ditampilkan di dalam kotak pesan, dan hanya memberikan jawaban tentang cara menghindari penggunaan kotak pesan sama sekali, dan itu semua bagus .

Namun perlu diingat bahwa masalah pluralisasi juga berlaku untuk teks di tempat lain dalam program selain kotak pesan. Misalnya, label di samping kisi yang menampilkan jumlah baris yang dipilih dalam kisi akan memiliki masalah yang sama terkait kemajemukan.

Jadi ini pada dasarnya berlaku untuk sebagian besar teks yang dikeluarkan dengan cara tertentu dari program, dan kemudian solusinya tidak sesederhana hanya dengan mengubah program menjadi tidak mengeluarkan teks lagi :)

Øyvind Bråthen
sumber
6
@ 0xA3: Saya tidak begitu tahu apakah setiap bahasa memiliki bentuk jamak yang mudah diekspresikan seperti "item (s)".
Jens
5
Anda mungkin juga harus memikirkan tentang pelokalan. Masalah ini bisa menjadi jauh lebih buruk.
Alex Brown
4
@ Jens: Mereka biasanya tidak, dengan cara yang sesederhana mungkin. Beberapa bahasa memiliki misalnya pluralisasi yang berbeda untuk 2-4 daripada untuk 5-tak terhingga, semua itu tergantung pada jenis kelamin. "Bahasa Alami: Kegilaan Lokalisasi! Segera hadir di komputer di dekat Anda!"
Piskvor meninggalkan gedung
29
IMO, tidak ada yang membuat programmer terlihat malas bagi pengguna selain pluralitas yang buruk.
Greg
4
@ Øyvind: +1 untuk Sunting Anda. Tampaknya banyak "penjawab" di sini lebih berniat untuk membuktikan bahwa pertanyaan Anda salah, daripada menawarkan solusi yang benar. Anti-solusi, jika Anda mau.
mwolfe02

Jawaban:

53

Jika ada peluang, sekecil apa pun, aplikasi ini perlu diterjemahkan ke bahasa lain, maka keduanya salah. Cara yang benar untuk melakukannya adalah:

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?"
);

Ini karena bahasa yang berbeda menangani pluralitas secara berbeda. Beberapa orang seperti bahasa Melayu bahkan tidak memiliki bentuk jamak sintaksis sehingga stringnya secara umum akan identik. Memisahkan dua string memudahkan untuk mendukung bahasa lain di kemudian hari.

Jika tidak, jika aplikasi ini dimaksudkan untuk dikonsumsi oleh masyarakat umum dan seharusnya ramah pengguna, maka metode kedua lebih disukai. Maaf, tapi saya tidak tahu cara yang lebih singkat untuk melakukan ini.

Jika aplikasi ini dimaksudkan untuk dikonsumsi hanya secara internal oleh perusahaan Anda, lakukan cara pintas "item(s)". Anda tidak perlu membuat siapa pun terkesan saat menulis kode giat. Tetapi saya menyarankan untuk tidak melakukan ini untuk aplikasi yang dikonsumsi publik karena ini memberi kesan bahwa programmer malas dan dengan demikian menurunkan pendapat mereka tentang kualitas aplikasi. Percayalah, hal-hal kecil seperti ini.

slebetman
sumber
35
Meskipun saya setuju dengan premis tersebut, Anda mengabaikan bahasa yang memiliki lebih dari dua derajat pluralitas. (Ambil bahasa Rusia misalnya. Tiga cara berbeda untuk mengatakan tergantung pada apakah 1, <5, atau> = 5 dan bahkan itu tergantung pada apa yang sebenarnya Anda bicarakan). Pada dasarnya saya mengatakan Anda membutuhkan pernyataan bersyarat yang lebih kuat dan bukan hanya operator terner.
Parah
4
Anda bahkan dapat mengoptimalkan noofitemsselecteddalam contoh ini untuk opsi pertama; karena Anda tahu itu adalah 1.
Default
16
Sementara kita melakukannya, bahasa Ibrani dapat memiliki bentuk jamak yang berbeda untuk 1, 2, 3-10, dan 11+.
Joel Spolsky
3
@ Joel, bahasa Ibrani dapat memiliki banyak bentuk jamak yang berbeda? לא ידעתי (Saya tidak tahu)! Bahasa Ibrani modern seperti bahasa Inggris sejauh bentuk jamak (meskipun bahasa Ibrani kuno juga memiliki bentuk ganda.)
Ken Bloom
3
Dalam bahasa Inggris, nol diperlakukan seperti jamak (0 item, 2 item); apa yang terjadi dengan nol dalam bahasa Ibrani, Rusia, Rumania? Apakah ada cara sederhana untuk mengidentifikasi rentang? Saya menduga bahwa informasi harus ditentukan per bahasa, jadi sistem apa pun yang didasarkan pada file pesan harus berurusan dengan berbagai jumlah pluralitas dalam satu set pesan. Aduh! Menyiapkan terjemahan juga akan rumit - jumlah pesan yang berbeda dibutuhkan untuk bahasa yang berbeda.
Jonathan Leffler
94

Anda dapat menghindari semua kemajemukan yang berantakan ini dengan hanya menghapus item tanpa pesan apa pun dan memberi pengguna fasilitas Urungkan yang sangat bagus. Pengguna tidak pernah membaca apapun . Anda harus membangun fasilitas Undo yang baik sebagai bagian dari program Anda.

Anda benar-benar mendapatkan 2 keuntungan saat membuat fasilitas Undo yang lengkap. Manfaat pertama membuat hidup pengguna lebih mudah dengan memungkinkan dia membalik kesalahan dan meminimalkan membaca. Manfaat kedua adalah bahwa aplikasi Anda mencerminkan kehidupan nyata dengan memungkinkan pembalikan alur kerja non-sepele (bukan hanya kesalahan).

Saya pernah menulis aplikasi tanpa menggunakan satu dialog pun atau pesan konfirmasi. Butuh beberapa pemikiran serius dan jauh lebih sulit untuk diterapkan daripada menggunakan pesan tipe konfirmasi. Tetapi hasil akhirnya cukup bagus untuk digunakan menurut pengguna akhirnya.

HTTP 410
sumber
12
Untuk beberapa alasan, saya benar-benar merasa setuju dengan ini dan harus memberi suara positif.
Cody Gray
4
@ Øyvind, Berikut alasannya: Pesan yang meminta verifikasi pengguna mahal bagi pengguna, terutama bila disajikan dalam bentuk kotak dialog modal yang menghentikan semuanya hingga pengguna menjawab dialog tersebut. Ini mengganggu banyak pengguna, ke titik di mana mereka mulai hanya mengklik tombol apa saja untuk melewati kotak dialog (berapa banyak penginstal yang baru saja Anda klik berikutnya, berikutnya, berikutnya? ). Akibatnya, ini lebih aman, dan gesekan pengguna jauh lebih sedikit, jika Anda hanya melakukan penghapusan lunak, dan menyediakan kemampuan urung. Gmail menggunakan teknik ini untuk efek yang hebat.
Robert Harvey
5
Dapat diperdebatkan, tetapi dalam kasus apa pun, masalah yang sama akan muncul dalam kasus selain pesan konfirmasi tentang penghapusan, jadi jawaban ini sangat bersinggungan dengan pertanyaan tersebut.
Jay
50
saya memilih ini tanpa membacanya. saya selalu dapat membatalkannya nanti
Steven A. Lowe
6
@Robert Harvey: Mungkin apokrif, tetapi bertahun-tahun yang lalu saya membaca bahwa Lotus telah mengirimkan 40.000 unit Lotus Notes untuk Mac dan 60.000 dikembalikan. Antarmukanya sangat buruk bahkan orang yang telah membajaknya mengirimnya kembali.
Duncan
39

Bagaimana dengan:

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

Dengan begitu, Anda menghilangkan kesulitan perjanjian nomor, dan berakhir dengan pesan kesalahan yang lebih singkat dan lebih langsung untuk pengguna sebagai bonus. Kita semua tahu bahwa pengguna tidak membaca pesan kesalahan . Semakin pendek mereka, semakin besar kemungkinan mereka untuk setidaknya melirik pada teks.

Atau, dipersenjatai dengan pengetahuan bahwa pengguna tidak membaca pesan kesalahan, Anda dapat melakukan pendekatan ini dengan cara yang berbeda. Lewati pesan konfirmasi sama sekali, dan cukup sediakan fitur undo yang Just Works, apa pun yang telah dihapus. Sebagian besar pengguna sudah terbiasa membatalkan operasi ketika mereka menyadari bahwa itu bukan yang mereka inginkan, dan cenderung menganggap perilaku ini lebih alami daripada harus berurusan dengan munculan lain yang mengganggu.

Cody Grey
sumber
1
Jawaban yang bagus. Namun, dalam hal ini pelanggan diminta untuk memberikan pesan kesalahan untuk banyak kasus karena dia merasa itu adalah pendekatan terbaik. Tetapi mengubah teks setidaknya dapat meminimalkan masalah dan membuatnya tidak terlalu berantakan.
Øyvind Bråthen
@ Øyvind: Cukup adil. Karena Anda harus mengikuti pelanggan, saya akan mengambil pendekatan pertama yang saya usulkan atau menggunakan file Resources dengan fungsi handler. Saya hanya berpikir bahwa ada baiknya menunjukkan alternatif karena mudah dilupakan. Heck, saya bahkan tidak memikirkannya sampai saya mengirimkan tanggapan pertama saya.
Cody Gray
Alternatif sangat diterima. Itulah mengapa saya memberikannya +1 juga :)
Øyvind Bråthen
1
1 karena tidak mencoba memecahkan masalah yang tidak terpecahkan. Dan ingat hukum Steve Krug: Hapus separuh kata. Kemudian lakukan lagi. Saya menggunakan: "Hapus {x} item?"
Serge Wautier
20

Bagaimana dengan Java selama bertahun-tahun: java.text.MessageFormat dan ChoiceFormat? Lihat http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html untuk informasi lebih lanjut.

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.

Dalam kasus Anda, Anda menginginkan sesuatu yang lebih sederhana:

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

Keuntungan dari pendekatan ini adalah ia bekerja dengan baik dengan bundel i18n, dan Anda dapat memberikan terjemahan dengan benar untuk bahasa (seperti Jepang) yang tidak memiliki konsep kata jamak atau tunggal.

Berin Loritsch
sumber
1
Pendekatan ini bekerja dengan baik untuk menangani pluralitas tetapi sayangnya tidak menangani gender. Anda membutuhkan string berbeda untuk setiap jenis hal yang dapat dihapus.
Tuan Shiny dan Baru 安 宇
Jika Anda mengetahui kata benda, Anda dapat membuat kalimat agar sesuai dengan kata sifat yang tepat. Tapi ya, setelah mempelajari bahasa Yunani klasik, Anda memiliki bentuk kata yang berbeda berdasarkan kata benda maskulin, feminin, atau netral (kata sifat mengambil bentuk kata benda yang dimodifikasi), dan bentuknya berbeda berdasarkan fungsinya dalam kalimat ( subjek, objek, dll.). Kami selalu dapat menemukan kasus di mana satu solusi berfungsi dan solusi lainnya tidak. Ini adalah cara orang-orang Java mencoba memecahkan masalah tersebut. Anda tetap harus berhati-hati dengan cara Anda membentuk format pesan.
Berin Loritsch
Anda selalu dapat memberi makan solusi Java dua bilangan bulat, dengan yang kedua menunjukkan jenis kelamin. (Namun pada kenyataannya, kesepakatan gender biasanya kurang menjadi perhatian hanya karena kasus penggunaan pemasangan objek yang berbeda ke dalam pesan lebih jarang daripada menyesuaikan nomor yang berbeda dari objek yang sama ke dalam pesan)
Ken Bloom
12

Saya akan pergi dengan tidak melakukan hardcoding pesan, tetapi memberikan dua pesan dalam file Resource yang terpisah. Suka

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?";

dan kemudian memasukkannya ke dalam String.Format like

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

string message = String.Format(messageTemplate, noofitemsselected)

Saya pikir pendekatan ini lebih mudah dilokalkan dan dipelihara. Semua pesan UI akan berada di satu lokasi.

Jens
sumber
+1, Saya suka pendekatan ini. Meskipun demikian, Anda perlu melacak nama sumber daya yang setara.
Default
11

Anda dapat menghindari masalah sepenuhnya dengan menyusun pesan secara berbeda.

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

Hal pertama yang saya sarankan adalah: gunakan string.Format. Itu memungkinkan Anda melakukan sesuatu seperti ini:

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

Lebih lanjut, di aplikasi WPF, saya telah melihat sistem di mana string sumber daya akan dipisahkan dengan tanda pipa untuk memiliki dua pesan: pesan tunggal dan jamak (atau pesan nol / tunggal / banyak, bahkan). Sebuah konverter khusus kemudian dapat digunakan untuk mengurai sumber daya ini dan menggunakan string yang relevan (diformat), jadi Xaml Anda adalah seperti ini:

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

Untuk bahasa Inggris, banyak jawaban di atas. Untuk bahasa lain itu lebih sulit, karena bentuk jamak bergantung pada jenis kelamin kata benda dan akhir kata. Beberapa contoh dalam bahasa Prancis:

Maskulin biasa:

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

Feminin biasa

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

Maskulin tidak beraturan (diakhiri dengan 's')

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

Masalah yang sama terjadi di sebagian besar bahasa Latin dan menjadi lebih buruk di Jerman atau Rusia, di mana ada 3 jenis kelamin (makuline, feminin dan netral).

Anda harus berhati-hati jika tujuan Anda adalah menguasai lebih dari sekedar bahasa Inggris.

penyeringai
sumber
Setidaknya dalam kasus saya, ini sebenarnya bukan masalah. Untuk setiap teks yang ingin saya masukkan nomornya, saya akan tahu apa kata benda saat membuat string. Tetapi untuk membuat solusi yang lebih umum, saya setuju dengan Anda, bahwa membuatnya berfungsi untuk "semua" bahasa mungkin merupakan tugas yang sangat sulit, bahkan mustahil.
Øyvind Bråthen
1
Atau ambil bahasa Polandia, di mana bentuk jamak dari kata benda yang digunakan berbeda tergantung pada nomornya! : /
UpTheCreek
5

Untuk dapat memiliki pesan jamak yang memungkinkan untuk dilokalkan dengan baik, menurut saya adalah bijaksana untuk terlebih dahulu membuat lapisan tipuan antara nomor dan pesan.

Misalnya, gunakan semacam konstanta untuk menentukan pesan mana yang ingin Anda tampilkan. Ambil pesan menggunakan beberapa fungsi yang akan menyembunyikan detail implementasi.

get_message(DELETE_WARNING, quantity)

Selanjutnya, buat kamus yang menampung pesan dan variasi yang mungkin, dan buat variasi tahu kapan harus digunakan.

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?'
}

Sekarang Anda dapat dengan mudah menemukan kunci yang sesuai dengan quantitydan menginterpolasi nilai quantitydengan pesan itu.

Contoh yang terlalu disederhanakan dan naif ini, tetapi saya tidak benar-benar melihat cara lain yang waras untuk melakukan ini dan dapat memberikan dukungan yang baik untuk L10N dan I18N.

Davor Lucic
sumber
5

Anda harus menerjemahkan fungsi di bawah ini dari VBA ke C #, tetapi penggunaan Anda akan berubah menjadi:

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

Saya memiliki fungsi VBA yang saya gunakan di MS Access untuk melakukan apa yang Anda bicarakan. Saya tahu saya akan diretas berkeping-keping karena memposting VBA, tapi ini dia. Algoritme harus terlihat dari komentar:

'---------------------------------------------------------------------------------------'
' 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

Penggunaannya terpotong sedikit di komentar kode di atas, jadi saya akan mengulanginya di sini:

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."

Ya, solusi ini mengabaikan bahasa selain bahasa Inggris. Apakah itu penting tergantung pada kebutuhan Anda.

mwolfe02
sumber
4

Anda dapat membuat bentuk jamak secara otomatis, lihat mis. generator jamak .

Untuk aturan pembangkitan jamak, lihat wikipedia

string msg = "Do you want to delete " + numItems + GetPlural(" item", numItems) + "?";
kunci jempol
sumber
Saya suka menggunakan metode ini jika aplikasi tidak diinternasionalkan. Puralising menghasilkan aplikasi yang lebih halus.
cspolton
1
Sangat sulit untuk menginternasionalkan ini, dan sering gagal dalam bahasa Inggris misalnya "Anda memiliki pesanan + numMice + GetPlural (" mouse ", numMice)"
James Anderson
@ James Anderson: Nah, itu bukan contoh terbaik secara tata bahasa kan ;-) Jangan terjebak dalam pemikiran bahwa menggunakan metode GetPural adalah satu - satunya metode yang boleh Anda gunakan.
cspolton
ditambah dengan beberapa fungsi lagi untuk menangani beberapa kasus sudut lagi, saya rasa ini adalah solusi yang sangat baik, meskipun tidak lebih singkat.
lalli
4

Bagaimana dengan cara yang lebih umum. Hindari pluralisasi di kalimat kedua:

Jumlah item yang dipilih untuk dihapus: tidak ada item yang dipilih.
Apakah kamu yakin

Saya menemukan bahwa melakukannya dengan cara ini menempatkan angka di akhir baris yang sangat mudah dikenali. Solusi ini akan bekerja dengan logika yang sama dalam bahasa apa pun.

Danosaure
sumber
"Item yang dipilih untuk dihapus:" kedengarannya tidak benar, kalimat menunjukkan daftar nama, tetapi nomor dicetak. Meskipun diubah menjadi "Jumlah item yang akan dihapus:", "item" masih canggung.
lalli
@lalli: Ya, kata-katanya tidak sempurna, dan tidak ada solusi yang diberikan terdengar sempurna. Saya hanya menyarankan untuk meletakkannya dalam bentuk seperti label dan nilai. Anda benar tentang menambahkan Number(saya menjawab sambil menggendong bayi saya untuk tidur).
Danosaure
4

Pendekatan umum saya adalah menulis "fungsi tunggal / jamak", seperti ini:

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

Kemudian di badan pesan saya memanggil fungsi ini:

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

Ini tidak jauh lebih baik, tapi setidaknya itu, (a) menempatkan keputusan dalam sebuah fungsi dan dengan demikian mengurai kode sedikit, dan (b) cukup fleksibel untuk menangani bentuk jamak yang tidak beraturan. yaitu cukup mudah untuk mengatakan kata benda (n, "anak", "anak") dan sejenisnya.

Tentu saja ini hanya berfungsi untuk bahasa Inggris, tetapi konsep ini siap dikembangkan ke bahasa dengan akhiran yang lebih kompleks.

Terpikir oleh saya bahwa Anda dapat membuat parameter terakhir opsional untuk kasus mudah:

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;
}
Jay
sumber
1
Saya suka bagian terakhir Anda di mana Anda menggunakan nilai default untuk "mengurai" kode dalam kasus operasi default menambahkan s untuk membuat pluralisasi kata benda.
Øyvind Bråthen
4

Penginternasionalan

Saya berasumsi Anda menginginkan dukungan internasionalisasi, dalam hal ini bahasa yang berbeda memiliki pola yang berbeda untuk bentuk jamak (misalnya bentuk jamak khusus untuk 2 sesuatu, atau bahasa yang lebih rumit seperti Polandia), dan Anda tidak dapat mengandalkan penerapan beberapa pola sederhana pada string Anda untuk memperbaikinya.

Anda dapat menggunakan ngettextfungsi GNU Gettext dan memberikan dua pesan bahasa Inggris di kode sumber Anda. Gettext akan menyediakan infrastruktur untuk memilih dari pesan lain (berpotensi lebih) ketika diterjemahkan ke bahasa lain. Lihat http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html untuk penjelasan lengkap tentang dukungan jamak gettext GNU.

GNU Gettext berada di bawah LGPL. ngettextdinamai GettextResourceManager.GetPluralStringdi port C # Gettext.

(Jika Anda tidak memerlukan dukungan pelokalan, dan tidak ingin langsung menggunakan Gettext, tulis fungsi Anda sendiri yang melakukan ini untuk bahasa Inggris, dan berikan dua pesan lengkap ke sana, dengan begitu jika Anda membutuhkan l10n nanti, Anda dapat tambahkan dengan menulis ulang satu fungsi.)

Ken Bloom
sumber
3

Bagaimana menulis fungsi seperti

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

.. dan menggunakannya kapan pun Anda butuhkan?

string message = "You have selected " + GetOutputMessage(noofitemsselected,"item","items") + ". Are you sure you want to delete it/them?";
Pavel Morshenyuk
sumber
3
Anda tidak berpikir tentang itu kan lol, Anda memiliki fungsi untuk mengalikan atau tidak untuk kalimat tersebut kemudian Anda meletakkan "itu / mereka" di akhir lol
Barkermn01
Anda hanya perlu meneruskan dua pesan untuk seluruh kalimat ke fungsi ini.
Ken Bloom
Itu hanya sebuah contoh. Saya menyadari bahwa variasi untuk mengirim kalimat utuh lebih tepat.
Pavel Morshenyuk
3

Untuk soal pertama maksud saya Pluralize bisa menggunakan Inflector .

Dan yang kedua, Anda bisa menggunakan extension representasi string dengan nama seperti ToPronounString.

Yogesh
sumber
3

Saya memiliki pertanyaan yang sama persis dengan yang diajukan kepada saya kemarin oleh anggota tim kami.

Sejak itu muncul lagi di sini di StackOverflow, saya membayangkan alam semesta memberi tahu saya untuk mengadakan pesta dalam menghasilkan solusi yang layak.

Saya telah dengan cepat mengumpulkan sesuatu dan itu tidak sempurna namun mungkin berguna atau memicu beberapa diskusi / pengembangan.

Kode ini didasarkan pada gagasan bahwa bisa ada 3 pesan. Satu untuk nol item, satu untuk satu item dan satu untuk lebih dari satu item yang mengikuti struktur berikut:

singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural

Saya telah membuat kelas internal untuk diuji agar dapat meniru kelas sumber daya. Saya belum menguji ini menggunakan file sumber daya yang sebenarnya jadi saya belum melihat hasil lengkapnya.

Berikut kodenya (saat ini saya telah menyertakan beberapa obat generik di mana saya tahu saya dapat menentukan parameter ketiga hanya sebagai Jenis dan juga parameter kedua adalah string, saya pikir ada cara untuk menggabungkan kedua parameter ini menjadi sesuatu yang lebih baik tetapi saya ' Saya akan kembali ke hal itu ketika saya memiliki waktu luang.

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

Menguji kelas sumber daya:

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

dan metode eksekusi cepat saya

void Main()
{
    var message = GetMessage(56, "Tester",typeof(TestMessenger));
    message.Dump();
}
Jamie Dixon
sumber
Jika Anda ingin ini benar-benar lengkap, Anda juga harus menambahkan pesan untuk singlePropertyName_Allmembuatnya lebih jelas.
Danosaure
2

Dari sudut pandang saya, solusi pertama Anda adalah yang paling sesuai. Mengapa saya mengatakan itu adalah, jika Anda membutuhkan aplikasi untuk mendukung banyak bahasa, opsi kedua bisa melelahkan. Dengan pendekatan pertama, mudah untuk melokalkan teks tanpa banyak usaha.

Iluminati
sumber
2

Anda bisa menggunakan pesan yang lebih umum seperti 'Apakah Anda yakin ingin menghapus item yang dipilih'.

Peter
sumber
3
Ini pasti berhasil, tetapi menurut saya ide penanya untuk menunjukkan jumlah item yang akan dihapus secara sekilas adalah ide yang bagus. Lebih dari sekali, saya mencoba menghapus file dari desktop saya dan secara tidak sengaja menghapus lebih dari satu file itu.
Cody Gray
2

Saya bergantung pada seberapa bagus pesan yang ingin Anda terima. Dari yang termudah hingga tersulit:

  1. Tulis ulang pesan kesalahan Anda untuk menghindari pluralisasi. Tidak sebaik untuk pengguna Anda, tetapi lebih cepat.

  2. Gunakan bahasa yang lebih umum tetapi tetap menyertakan nomor.

  3. Gunakan sistem "pluralisasi" dan inflektor ala Rails, sehingga Anda bisa mengatakan pluralize(5,'bunch')dan mendapatkan 5 bunches. Rel memiliki pola yang bagus untuk ini.

  4. Untuk internasionalisasi, Anda perlu melihat apa yang disediakan Java. Itu akan mendukung berbagai macam bahasa, termasuk yang memiliki bentuk kata sifat yang berbeda dengan 2 atau 3 item. Solusi "s" sangat berpusat pada bahasa Inggris.

Opsi mana yang Anda gunakan bergantung pada tujuan produk Anda. - ndp

ndp
sumber
2

Mengapa Anda ingin menyajikan pesan yang benar-benar dapat dipahami pengguna? Ini bertentangan dengan 40 tahun sejarah pemrograman. Tidaaaaaaak, kami memiliki hal yang baik, jangan merusaknya dengan pesan yang bisa dimengerti .


(j / k)

John Alexiou
sumber
+1: Senang melihat humor di dalam sini juga. Tetapi bahkan jika Anda bercanda, saya mengerti maksud Anda. Banyak program yang dibuat selama bertahun-tahun memiliki pesan yang sangat buruk. Biasanya karena mereka mendapatkan cara teknis bagi pengguna biasa untuk memahaminya.
Øyvind Bråthen
Poin yang bagus. Saya selalu menyukainya ketika saya mendapatkan pesan seperti "Kesalahan 494-B pada input pengguna" - ini menambahkan sedikit misteri tentang apa yang salah yang membuat hidup jauh lebih menarik. Saya baru-baru ini mendapat kesalahan saat mencoba membuat kata sandi yang hanya mengatakan, "Kata sandi tidak memenuhi persyaratan keamanan". Tidak ada petunjuk tentang persyaratan apa yang tidak saya penuhi. Kata sandi saya termasuk huruf besar dan kecil serta beberapa digit. Saya mencoba menambahkan karakter secial. Masih tidak. Itu akhirnya berlalu ketika saya MENGHAPUS karakter. Saya pikir mereka memiliki aturan bahwa Anda tidak boleh memiliki karakter yang sama dua kali berturut-turut.
Jay
2

Lakukan seperti yang dilakukan di World of Warcraft:

BILLING_NAG_WARNING = "Your play time expires in %d |4minute:minutes;";
Thomas Bonini
sumber
0

Ini menjadi sedikit lebih pendek dengan

string message = "Are you sure you want to delete " + noofitemsselected + " item" + (noofitemsselected>1 ? "s" : "") + "?";
Jonas Elfström
sumber
0

Satu pendekatan yang belum pernah saya lihat sebutkan adalah penggunaan tag pengganti / pilih (misalnya, sesuatu seperti "Anda akan squash {0} [? I ({0} = 1): / cactus / cacti /]". (dengan kata lain, memiliki ekspresi seperti format tentukan substitusi berdasarkan apakah argumen nol, diambil sebagai integer, sama dengan 1). Saya telah melihat tag seperti itu digunakan pada hari-hari sebelumnya .net; Saya tidak mengetahui adanya standar untuk mereka dalam .net, saya juga tidak tahu cara terbaik untuk memformatnya.

supercat
sumber
0

Saya akan berpikir di luar kotak sebentar, semua saran di sini adalah melakukan pluralisasi (dan khawatir tentang lebih dari 1 tingkat pluralisasi, jenis kelamin, dll) atau tidak menggunakannya sama sekali dan memberikan pengurungan yang bagus.

Saya akan menggunakan cara non-bahasa dan menggunakan antrian visual untuk itu. misalnya bayangkan sebuah aplikasi Iphone Anda memilih item dengan menyeka jari Anda. sebelum menghapusnya menggunakan tombol hapus utama, ini akan "mengguncang" item yang dipilih dan menampilkan tanda tanya bertuliskan kotak dengan tombol V (ok) atau X (batal) ...

Atau, di dunia 3D Kinekt / Move / Wii - bayangkan memilih file, gerakkan tangan Anda ke tombol hapus dan disuruh menggerakkan tangan Anda di atas kepala untuk mengonfirmasi (menggunakan simbol visual yang sama seperti yang saya sebutkan sebelumnya. meminta Anda menghapus 3 file? ini akan menampilkan 3 file dengan X merah transparan setengah melayang di atas dan meminta Anda melakukan sesuatu untuk mengonfirmasi.

Eran Medan
sumber