ความหลากหลายในข้อความของผู้ใช้


106

หลายครั้งเมื่อสร้างข้อความเพื่อแสดงต่อผู้ใช้ข้อความนั้นจะมีบางสิ่งที่ฉันต้องการแจ้งให้ลูกค้าทราบ

ฉันจะยกตัวอย่าง: ลูกค้าได้เลือกรายการตั้งแต่ 1 ขึ้นไปและได้คลิกลบ ตอนนี้ฉันต้องการส่งข้อความยืนยันให้กับลูกค้าและฉันต้องการพูดถึงจำนวนรายการที่เขาเลือกเพื่อลดโอกาสที่เขาจะทำผิดพลาดโดยการเลือกรายการจำนวนมากและคลิกลบเมื่อเขาต้องการลบเพียงรายการเดียว พวกเขา

วิธีหนึ่งคือทำให้ข้อความทั่วไปเป็นดังนี้:

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

"ปัญหา" ที่นี่คือกรณีที่noofitemselected1 และเราจะต้องเขียนรายการและมันแทนรายการและพวกเขา

ทางออกปกติของฉันจะเป็นแบบนี้

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

สิ่งนี้จะค่อนข้างยาวและค่อนข้างน่ารังเกียจอย่างรวดเร็วหากมีการอ้างอิงตัวเลขจำนวนมากภายในรหัสและข้อความจริงอ่านยาก

ดังนั้นคำถามของฉันเป็นเพียง มีวิธีที่ดีกว่าในการสร้างข้อความเช่นนี้หรือไม่?

แก้ไข

ฉันเห็นว่ามีคนจำนวนมากวางสายอย่างมากในกรณีที่ฉันพูดถึงว่าควรแสดงข้อความในกล่องข้อความและได้รับคำตอบว่าจะหลีกเลี่ยงการใช้กล่องข้อความได้อย่างไรและนั่นก็เป็นเรื่องดี .

แต่อย่าลืมว่าปัญหาของการทำให้เป็นพหูพจน์ยังใช้กับข้อความที่อื่น ๆ ในโปรแกรมนอกเหนือจากกล่องข้อความด้วย ตัวอย่างเช่นป้ายกำกับข้างเส้นตารางที่แสดงจำนวนบรรทัดที่เลือกในกริดจะมีปัญหาเดียวกันเกี่ยวกับการทำให้เป็นพหูพจน์

ดังนั้นโดยทั่วไปจะใช้กับข้อความส่วนใหญ่ที่ถูกส่งออกมาจากโปรแกรมไม่ทางใดก็ทางหนึ่งแล้ววิธีแก้ปัญหาก็ไม่ง่ายเหมือนแค่เปลี่ยนโปรแกรมให้ไม่แสดงข้อความอีกต่อไป :)


6
@ 0xA3: ฉันไม่รู้จริงๆว่าทุกภาษามีพหูพจน์ที่แสดงเป็น "item (s)" ได้อย่างง่ายดายหรือไม่
Jens

5
คุณน่าจะคิดเกี่ยวกับการแปลภาษาด้วย ปัญหานี้อาจเลวร้ายลงมาก
Alex Brown

4
@Jens: พวกเขามักจะไม่สะดวกอย่างน้อยที่สุดเท่าที่จะทำได้ บางภาษามีคำพหูพจน์ที่แตกต่างกันเช่น 2-4 มากกว่าสำหรับ 5 อินฟินิตี้ขึ้นอยู่กับเพศ "Natural Languages: Localization Madness! เร็ว ๆ นี้บนคอมพิวเตอร์ที่อยู่ใกล้คุณ!"
Piskvor ออกจากอาคาร

29
IMO ไม่มีอะไรที่ทำให้โปรแกรมเมอร์ดูเกียจคร้านต่อผู้ใช้มากกว่าส่วนใหญ่ที่ไม่ดี
Greg

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)"สิ่ง คุณไม่จำเป็นต้องสร้างความประทับใจให้ใครเลยจริงๆเมื่อเขียนโค้ด Enterprisy แต่ฉันไม่แนะนำให้ทำสิ่งนี้สำหรับแอปที่ใช้งานแบบสาธารณะเพราะจะทำให้รู้สึกว่าโปรแกรมเมอร์ขี้เกียจและทำให้ความคิดเห็นเกี่ยวกับคุณภาพของแอปลดลง เชื่อใจฉันเรื่องเล็ก ๆ เช่นเรื่องนี้


35
ในขณะที่ฉันเห็นด้วยกับหลักฐานคุณกำลังเพิกเฉยต่อภาษาที่มีความหลากหลายมากกว่าสองระดับ (ยกตัวอย่างเช่นภาษารัสเซีย 3 วิธีที่แตกต่างกันในการพูดขึ้นอยู่กับว่า 1, <5 หรือ> = 5 และขึ้นอยู่กับสิ่งที่คุณกำลังพูดถึง) โดยทั่วไปฉันกำลังบอกว่าคุณต้องการคำสั่งเงื่อนไขที่แข็งแกร่งกว่าไม่ใช่แค่ตัวดำเนินการที่เกี่ยวข้อง
ปัญหา

4
คุณยังสามารถเพิ่มประสิทธิภาพnoofitemsselectedในตัวอย่างนี้สำหรับตัวเลือกแรก ตั้งแต่คุณรู้ว่ามันคือ 1
ค่าเริ่มต้น

16
ในขณะที่เรากำลังทำอยู่ภาษาฮีบรูอาจมีพหูพจน์ที่แตกต่างกันสำหรับ 1, 2, 3-10 และ 11+
Joel Spolsky

3
@ โจเอลฮีบรูสามารถมีพหูพจน์ได้หลายแบบ לאידעתי (ไม่รู้)! ภาษาฮิบรูสมัยใหม่ก็เหมือนกับภาษาอังกฤษพอ ๆ กับพหูพจน์ (แม้ว่าภาษาฮีบรูโบราณจะมีรูปแบบคู่)
Ken Bloom

3
ในภาษาอังกฤษศูนย์จะถือว่าเป็นพหูพจน์ (0 items, 2 items); เกิดอะไรขึ้นกับศูนย์ในภาษาฮิบรูรัสเซียโรมาเนีย มีวิธีง่ายๆในการระบุช่วงหรือไม่? ฉันคาดเดาว่าข้อมูลจะต้องถูกกำหนดตามภาษาดังนั้นระบบใด ๆ ที่ใช้ไฟล์ข้อความจะต้องจัดการกับจำนวนส่วนใหญ่ที่แตกต่างกันในชุดข้อความ อุ๊ย! การตั้งค่าการแปลจะยุ่งยากเช่นกัน - ต้องใช้จำนวนข้อความที่แตกต่างกันสำหรับภาษาต่างๆ
Jonathan Leffler

94

คุณสามารถหลีกเลี่ยงความยุ่งเหยิงทั้งหมดนี้ได้เพียงแค่ลบรายการโดยไม่มีข้อความใด ๆ และให้สิ่งอำนวยความสะดวกในการเลิกทำที่ดีแก่ผู้ใช้ ผู้ใช้ไม่เคยอ่านอะไรเลย คุณควรสร้างสิ่งอำนวยความสะดวกในการเลิกทำที่ดีเป็นส่วนหนึ่งของโปรแกรมของคุณอยู่ดี

คุณจะได้รับประโยชน์ 2 ต่อเมื่อคุณสร้างสิ่งอำนวยความสะดวกเลิกทำที่ครอบคลุม ประโยชน์ประการแรกทำให้ชีวิตของผู้ใช้ง่ายขึ้นโดยอนุญาตให้ย้อนกลับข้อผิดพลาดและลดการอ่าน ประโยชน์ประการที่สองคือแอปของคุณสะท้อนชีวิตจริงโดยอนุญาตให้ย้อนกลับขั้นตอนการทำงานที่ไม่สำคัญ (ไม่ใช่แค่ความผิดพลาด)

ฉันเคยเขียนแอปโดยไม่ใช้ข้อความโต้ตอบหรือข้อความยืนยันเลยแม้แต่ครั้งเดียว ต้องใช้ความคิดอย่างจริงจังและยากกว่าการใช้ข้อความประเภทการยืนยัน แต่ผลลัพธ์ก็ค่อนข้างดีที่จะใช้ตามผู้ใช้ปลายทาง


12
ด้วยเหตุผลบางประการฉันรู้สึกว่าฉันเห็นด้วยกับสิ่งนี้จริงๆและควรโหวตให้คะแนน
โคดี้เกรย์

4
@ Øyvindนี่คือเหตุผล: ข้อความที่ขอให้ผู้ใช้ตรวจสอบยืนยันนั้นมีราคาแพงสำหรับผู้ใช้โดยเฉพาะอย่างยิ่งเมื่อนำเสนอในรูปแบบของกล่องโต้ตอบโมดอลที่หยุดทุกอย่างจนกว่าผู้ใช้จะตอบกล่องโต้ตอบ สิ่งนี้สร้างความรำคาญให้กับผู้ใช้จำนวนมากจนถึงจุดที่พวกเขาเริ่มต้นเพียงคลิกปุ่มใดก็ได้เพื่อผ่านกล่องโต้ตอบ (คุณเพิ่งคลิกตัวติดตั้งกี่ตัวถัดไปถัดไปถัดไป ) ดังนั้นจึงปลอดภัยกว่าและมีแรงเสียดทานของผู้ใช้น้อยกว่ามากหากคุณทำการลบแบบนุ่มนวลและให้ความสามารถในการเลิกทำ Gmail ใช้เทคนิคนี้เพื่อให้ได้ผลดี
Robert Harvey

5
สามารถถกเถียงกันได้ แต่ในกรณีใด ๆ ปัญหาเดียวกันนี้จะเกิดขึ้นในกรณีอื่นที่ไม่ใช่ข้อความยืนยันในการลบดังนั้นคำตอบนี้จึงเป็นสิ่งที่ตรงกันกับคำถาม
เจย์

50
ฉันโหวตสิ่งนี้โดยไม่ได้อ่าน ฉันสามารถเลิกทำได้ในภายหลัง
Steven A. Lowe

6
@ โรเบิร์ตฮาร์วีย์: น่าจะเป็นคัมภีร์ไบเบิล แต่เมื่อหลายปีก่อนฉันได้อ่านพบว่า Lotus ได้ส่งมอบ Lotus Notes จำนวน 40,000 เครื่องสำหรับ Mac และส่งคืน 60,000 เครื่อง อินเทอร์เฟซแย่มากถึงขนาดคนที่ละเมิดลิขสิทธิ์ส่งมันกลับมา
Duncan

39

แล้วแค่:

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

ด้วยวิธีนี้คุณจะขจัดปัญหาในการตกลงหมายเลขและจบลงด้วยข้อความแสดงข้อผิดพลาดที่สั้นและตรงประเด็นยิ่งขึ้นสำหรับผู้ใช้เป็นโบนัส เราทุกคนรู้ผู้ใช้ไม่ได้อ่านข้อความผิดพลาดอยู่แล้ว ยิ่งสั้นมากเท่าไหร่พวกเขาก็มีโอกาสที่จะมองดูข้อความได้มากขึ้นเท่านั้น

หรือด้วยความรู้ที่ว่าผู้ใช้ไม่ได้อ่านข้อความแสดงข้อผิดพลาดคุณสามารถใช้วิธีนี้ได้หลายวิธี ข้ามข้อความยืนยันไปเลยและเพียงแค่ระบุคุณลักษณะการเลิกทำที่ Just Works โดยไม่คำนึงถึงสิ่งที่ถูกลบ ผู้ใช้ส่วนใหญ่คุ้นเคยกับการยกเลิกการดำเนินการเมื่อสังเกตเห็นว่าไม่ใช่สิ่งที่ต้องการและมีแนวโน้มที่จะพบว่าพฤติกรรมนี้เป็นธรรมชาติมากกว่าการต้องจัดการกับป๊อปอัปที่น่ารำคาญอื่น ๆ


1
คำตอบที่ดี. อย่างไรก็ตามในกรณีนี้ลูกค้าได้ร้องขอให้ส่งข้อความแสดงข้อผิดพลาดสำหรับหลาย ๆ กรณีเนื่องจากเขารู้สึกว่าเป็นแนวทางที่ดีที่สุด แต่การเปลี่ยนข้อความอย่างน้อยสามารถลดปัญหาและทำให้ยุ่งน้อยลง
ØyvindBråthen

@ Øyvind: พอใช้ เนื่องจากคุณต้องติดตามลูกค้าฉันจึงควรใช้แนวทางแรกที่ฉันเสนอหรือใช้ไฟล์ทรัพยากรที่มีฟังก์ชันตัวจัดการ ฉันแค่คิดว่ามันคุ้มค่าที่จะชี้ให้เห็นทางเลือกอื่นเพราะมันลืมง่ายมาก ห่าฉันไม่ได้คิดเลยจนกระทั่งหลังจากที่ฉันส่งคำตอบครั้งแรก
โคดี้เกรย์

ทางเลือกอื่นยินดีต้อนรับมากที่สุด นั่นเป็นเหตุผลที่ฉันให้ +1 ด้วย :)
ØyvindBråthen

1
+1 ที่ไม่พยายามแก้ปัญหาที่ไม่สามารถแก้ไขได้ และจำกฎของ Steve Krug: ลบคำครึ่งหนึ่ง แล้วทำอีกครั้ง. ฉันใช้: "ลบ {x} รายการ?"
Serge Wautier

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
วิธีนี้ใช้ได้ผลดีในการจัดการกับความหลากหลาย แต่ไม่สามารถจัดการกับเพศสภาพได้ คุณต้องมีสตริงที่แตกต่างกันสำหรับแต่ละประเภทที่สามารถลบได้
Mr. Shiny and New 安宇

หากคุณรู้จักคำนามคุณสามารถนำประโยคมาใช้กับคำคุณศัพท์ที่เหมาะสมได้ แต่ใช่เมื่อเรียนภาษากรีกคลาสสิกคุณมีรูปแบบที่แตกต่างกันไปตามคำนามผู้ชายผู้หญิงหรือเพศสัมพันธ์ (คำคุณศัพท์ใช้รูปแบบของคำนามที่ปรับเปลี่ยน) และรูปแบบจะแตกต่างกันไปตามหน้าที่ในประโยค ( เรื่องวัตถุ ฯลฯ ) เราสามารถหากรณีที่วิธีแก้ปัญหาหนึ่งใช้ได้ผลและอีกวิธีหนึ่งใช้ไม่ได้ นี่เป็นวิธีที่ชาว Java พยายามแก้ปัญหา คุณยังคงต้องระวังวิธีจัดรูปแบบข้อความ
Berin Loritsch

คุณสามารถป้อนโซลูชัน Java ได้สองจำนวนเต็มโดยที่ตัวที่สองระบุเพศ (แต่ในความเป็นจริงแล้วข้อตกลงเรื่องเพศมักจะไม่น่ากังวลเพียงเพราะกรณีการใช้งานของการปรับวัตถุต่างๆให้เข้ากับข้อความนั้นมีน้อยกว่าการใส่ตัวเลขที่แตกต่างกันของวัตถุเดียวกันลงในข้อความ)
Ken Bloom

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 รูปแบบเช่น

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

string message = String.Format(messageTemplate, noofitemsselected)

ฉันคิดว่าวิธีนี้ง่ายกว่าในการแปลและบำรุงรักษา ข้อความ UI ทั้งหมดจะอยู่ที่ตำแหน่งที่ตั้งเดียว


+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?

ปัญหาเดียวกันนี้เกิดขึ้นในภาษาละตินส่วนใหญ่และจะแย่ลงในภาษาเยอรมันหรือรัสเซียซึ่งมี 3 เพศ (ผู้ชายผู้ชายผู้หญิงและเพศหญิง)

คุณจะต้องดูแลว่าวัตถุประสงค์ของคุณคือจัดการมากกว่าภาษาอังกฤษหรือไม่


อย่างน้อยในกรณีของฉันนี่ไม่ใช่ปัญหาจริงๆ สำหรับแต่ละข้อความที่ฉันต้องการแทรกตัวเลขฉันจะรู้ว่าคำนามคืออะไรเมื่อสร้างสตริง แต่ในการหาวิธีแก้ปัญหาทั่วไปฉันเห็นด้วยกับคุณว่าการทำให้มันใช้ได้กับภาษา "ทั้งหมด" อาจเป็นงานที่ยากมากหากไม่ใช่เรื่องที่เป็นไปไม่ได้
ØyvindBrå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) + "?";

ฉันชอบใช้วิธีนี้หากแอปพลิเคชันไม่เป็นสากล Puralising ส่งผลให้แอปพลิเคชันมีความสวยงามมากขึ้น
cspolton

1
มันยากมากที่จะทำให้เป็นสากลและมักจะล้มเหลวในภาษาอังกฤษเช่น "คุณมีคำสั่งซื้อ + numMice + GetPlural (" mouse ", numMice)"
James Anderson

@ เจมส์แอนเดอร์สัน: ตอนนี้นั่นไม่ใช่ตัวอย่างที่ดีที่สุดตามหลักไวยากรณ์แล้ว ;-) อย่าตกหลุมพรางของการคิดว่าการใช้เมธอด GetPural เป็นวิธีเดียวที่คุณได้รับอนุญาตให้ใช้
cspolton

เมื่อรวมกับฟังก์ชั่นอื่น ๆ อีกเล็กน้อยในการจัดการเคสเข้ามุมอีกสองสามตัวฉันคิดว่านี่เป็นทางออกที่ดีมากไม่ใช่สั้นกว่า
lalli

4

วิธีการทั่วไปมากขึ้น หลีกเลี่ยงการใช้พหูพจน์ในประโยคที่สอง:

จำนวนรายการที่เลือกที่จะลบ: noofitemsselected
คุณแน่ใจไหม?

ฉันพบว่าการทำแบบนี้ทำให้ตัวเลขอยู่ท้ายบรรทัดซึ่งง่ายต่อการมองเห็น โซลูชันนี้จะทำงานโดยใช้ตรรกะเดียวกันในทุกภาษา


"รายการที่เลือกที่จะลบ:" ฟังดูไม่ถูกต้องประโยคนี้ระบุรายชื่อ แต่มีการพิมพ์ตัวเลขไว้ แม้ว่าจะเปลี่ยนเป็น "จำนวนรายการที่จะลบ:" แต่ "รายการ" ก็ยังไม่สะดวก
lalli

@lalli: ใช่ข้อความไม่สมบูรณ์แบบและไม่มีวิธีแก้ปัญหาใดที่ฟังดูสมบูรณ์แบบ ฉันแนะนำให้ใส่ในรูปแบบป้ายกำกับและค่าเท่านั้น คุณพูดถูกเกี่ยวกับการเพิ่มNumber(ฉันกำลังตอบในขณะที่โยกลูกไปนอน)
Danosaure

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")+"!";

สิ่งนี้ไม่ได้ดีไปกว่านี้ แต่อย่างน้อย (a) ทำให้การตัดสินใจอยู่ในฟังก์ชันและคลายโค้ดออกเล็กน้อยและ (b) มีความยืดหยุ่นเพียงพอที่จะจัดการกับพหูพจน์ที่ผิดปกติ กล่าวคือง่ายพอที่จะพูดคำนาม (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;
}

1
ฉันชอบส่วนสุดท้ายของคุณที่คุณใช้ค่าเริ่มต้นในการ "unclutterize" รหัสในกรณีที่การดำเนินการเริ่มต้นของการเพิ่มsเพื่อทำให้คำนามเป็นพหูพจน์
ØyvindBråthen

4

ความเป็นสากล

ฉันคิดว่าคุณต้องการการสนับสนุนความเป็นสากลซึ่งในกรณีนี้ภาษาที่แตกต่างกันจะมีรูปแบบของพหูพจน์ที่แตกต่างกัน (เช่นรูปพหูพจน์พิเศษสำหรับ 2 สิ่งหรือภาษาที่ซับซ้อนกว่าเช่นโปแลนด์) และคุณไม่สามารถพึ่งพารูปแบบง่ายๆกับสตริงของคุณได้ เพื่อแก้ไข

คุณสามารถใช้ngettextฟังก์ชันของ GNU Gettext และระบุข้อความภาษาอังกฤษสองข้อความในซอร์สโค้ดของคุณ Gettext จะจัดเตรียมโครงสร้างพื้นฐานให้เลือกจากข้อความอื่น ๆ (อาจมากกว่านั้น) เมื่อแปลเป็นภาษาอื่น ดูhttp://www.gnu.org/software/hello/manual/gettext/Plural-forms.htmlสำหรับคำอธิบายทั้งหมดของการสนับสนุนพหูพจน์ของ GNU gettext

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

คุณควรส่งข้อความสองข้อความสำหรับทั้งประโยคไปยังฟังก์ชันนี้
Ken Bloom

มันเป็นเพียงตัวอย่าง ฉันตระหนักดีว่าตัวแปรที่จะส่งทั้งประโยคนั้นถูกต้องกว่า
Pavel Morshenyuk

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เพื่อให้ชัดเจนยิ่งขึ้น
Danosaure

2

จากมุมมองของฉันโซลูชันแรกของคุณเป็นวิธีที่เหมาะสมที่สุด ทำไมฉันถึงพูดอย่างนั้นก็คือในกรณีที่คุณต้องการแอปพลิเคชันที่รองรับหลายภาษาตัวเลือกที่สองอาจเป็นเรื่องยาก ด้วยวิธีกำปั้นทำให้ง่ายต่อการแปลข้อความโดยไม่ต้องใช้ความพยายามมากนัก


2

คุณสามารถไปที่ข้อความทั่วไปเช่น "คุณแน่ใจหรือไม่ว่าต้องการลบรายการที่เลือก"


3
สิ่งนี้ใช้ได้ผลอย่างแน่นอน แต่ฉันคิดว่าความคิดของผู้ถามในการแสดงจำนวนรายการที่จะถูกลบในพริบตานั้นเป็นสิ่งที่ดี มากกว่าหนึ่งครั้งฉันได้พยายามลบไฟล์จากเดสก์ท็อปและเผลอลบมากกว่าหนึ่งไฟล์
โคดี้เกรย์

2

ฉันขึ้นอยู่กับว่าคุณต้องการมีข้อความที่ดีแค่ไหน จากง่ายที่สุดไปหายากที่สุด:

  1. เขียนข้อความแสดงข้อผิดพลาดของคุณอีกครั้งเพื่อหลีกเลี่ยงการทำให้เป็นพหูพจน์ ไม่ดีสำหรับผู้ใช้ของคุณ แต่เร็วกว่า

  2. ใช้ภาษาทั่วไปมากขึ้น แต่ยังคงรวมตัวเลขไว้

  3. ใช้ "pluralization" และระบบการ Inflector Ala ทางรถไฟเพื่อให้คุณสามารถพูดได้และได้รับpluralize(5,'bunch') 5 bunchesรางมีรูปแบบที่ดีสำหรับสิ่งนี้

  4. สำหรับความเป็นสากลคุณต้องดูว่า Java ให้อะไรบ้าง ซึ่งจะรองรับภาษาที่หลากหลายรวมถึงภาษาที่มีคำคุณศัพท์ในรูปแบบต่างๆด้วย 2 หรือ 3 รายการ การแก้ปัญหา "s" เป็นภาษาอังกฤษมาก

ตัวเลือกที่คุณเลือกขึ้นอยู่กับเป้าหมายผลิตภัณฑ์ของคุณ - ndp


2

ทำไมคุณถึงต้องการนำเสนอข้อความที่ผู้ใช้สามารถเข้าใจได้จริง? มันขัดกับประวัติศาสตร์การเขียนโปรแกรม 40 ปี Nooooo เรามีสิ่งดีๆเกิดขึ้นอย่าทำให้เสียด้วยข้อความที่เข้าใจได้


(j / k)


+1: ดีใจที่ได้เห็นอารมณ์ขันภายในที่นี่ด้วย แต่ถึงคุณจะล้อเล่นฉันก็เข้าใจจุดสำคัญของคุณ โปรแกรมจำนวนมากที่สร้างขึ้นในช่วงหลายปีมีข้อความที่ไม่ดีอย่างมาก มักจะเป็นเพราะพวกเขาได้รับวิธีการทางเทคนิคสำหรับผู้ใช้ทั่วไปที่จะเข้าใจอยู่แล้ว
ØyvindBråthen

จุดดี. ฉันมักจะชอบเมื่อได้รับข้อความเช่น "ข้อผิดพลาด 494-B ในการป้อนข้อมูลของผู้ใช้" - มันเพิ่มความลึกลับเล็ก ๆ น้อย ๆ เกี่ยวกับสิ่งที่ผิดพลาดที่ทำให้ชีวิตน่าสนใจมากขึ้น เมื่อเร็ว ๆ นี้ฉันได้รับข้อผิดพลาดในการพยายามสร้างรหัสผ่านที่กล่าวว่า "รหัสผ่านไม่ตรงตามข้อกำหนดด้านความปลอดภัย" ไม่มีคำใบ้ว่าฉันไม่ได้ทำตามข้อกำหนดอะไร รหัสผ่านของฉันประกอบด้วยตัวอักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กและตัวเลขหลายหลัก ฉันลองเพิ่มอักขระพิเศษ ยังคงไม่. ในที่สุดมันก็ผ่านไปเมื่อฉันลบตัวละคร ฉันคิดว่าพวกเขามีกฎว่าคุณไม่สามารถมีตัวละครเดียวกันสองครั้งติดต่อกันได้
เจย์


0

มันจะสั้นลงเล็กน้อยด้วย

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

0

แนวทางหนึ่งที่ฉันไม่เคยเห็นมาก่อนคือการใช้แท็กการแทนที่ / เลือก (เช่น "คุณกำลังจะสควอช {0} [? i ({0} = 1): / cactus / cacti /]" (กล่าวอีกนัยหนึ่งคือมีนิพจน์ที่เหมือนรูปแบบระบุการแทนที่โดยพิจารณาจากว่าอาร์กิวเมนต์เป็นศูนย์ซึ่งใช้เป็นจำนวนเต็มเท่ากับ 1) ฉันเคยเห็นแท็กดังกล่าวที่ใช้ในวันก่อน. net ฉันไม่ทราบเกี่ยวกับ มาตรฐานสำหรับพวกเขาใน. net และฉันไม่รู้วิธีที่ดีที่สุดในการจัดรูปแบบ


0

ฉันจะคิดนอกกรอบสักครู่คำแนะนำทั้งหมดที่นี่อาจเป็นการใช้พหูพจน์ (และกังวลเกี่ยวกับการพหูพจน์มากกว่า 1 ระดับเพศ ฯลฯ ) หรือไม่ใช้เลยและให้การเลิกทำที่ดี

ฉันจะใช้วิธีที่ไม่ใช้ภาษาและใช้คิวภาพสำหรับสิ่งนั้น เช่นลองนึกภาพแอพ Iphone ที่คุณเลือกรายการโดยการเช็ดนิ้วของคุณ ก่อนที่จะลบโดยใช้ปุ่มลบหลักมันจะ "เขย่า" รายการที่เลือกและแสดงเครื่องหมายคำถามที่ชื่อกล่องพร้อมปุ่ม V (ok) หรือ X (ยกเลิก) ...

หรือในโลก 3 มิติของ Kinekt / Move / Wii - ลองนึกภาพการเลือกไฟล์เลื่อนมือของคุณไปที่ปุ่มลบและได้รับคำสั่งให้เลื่อนมือของคุณขึ้นเหนือศีรษะเพื่อยืนยัน (โดยใช้สัญลักษณ์ภาพเดียวกันกับที่ฉันได้กล่าวไว้ก่อนหน้านี้เช่นแทน หากขอให้คุณลบ 3 ไฟล์มันจะแสดงไฟล์ 3 ไฟล์โดยมี X สีแดงใสครึ่งหนึ่งวางอยู่และบอกให้คุณทำบางอย่างเพื่อยืนยัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.