Nhiều trong tin nhắn của người dùng


106

Nhiều khi tạo tin nhắn để hiển thị cho người dùng, tin nhắn sẽ chứa một số điều mà tôi muốn thông báo cho khách hàng.

Tôi sẽ đưa ra một ví dụ: Khách hàng đã chọn một số mục từ 1 trở lên và đã nhấp vào xóa. Bây giờ tôi muốn đưa ra một thông báo xác nhận cho khách hàng và tôi muốn đề cập đến số lượng mục mà anh ấy đã chọn để giảm thiểu khả năng anh ấy mắc lỗi bằng cách chọn một loạt các mục và nhấp vào xóa khi anh ấy chỉ muốn xóa một trong số chúng.

Một cách là tạo thông điệp chung chung như sau:

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

"Vấn đề" ở đây là trường hợp noofitemselectedlà 1, và chúng ta phải viết mục thay vì các mụcchúng .

Giải pháp bình thường của tôi sẽ như thế này

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

Quá trình này diễn ra khá dài và khá nhanh nếu có nhiều tham chiếu đến các số bên trong mã và thông báo thực tế sẽ khó đọc.

Vì vậy, câu hỏi của tôi chỉ đơn giản. Có cách nào tốt hơn để tạo các tin nhắn như thế này không?

BIÊN TẬP

Tôi thấy nhiều người đã rất bối rối trong trường hợp mà tôi đã đề cập rằng thông báo nên được hiển thị bên trong hộp tin nhắn và chỉ đơn giản là đưa ra câu trả lời về cách tránh sử dụng hộp tin nhắn, và điều đó là tốt .

Nhưng hãy nhớ rằng vấn đề đa dạng hóa cũng áp dụng cho các văn bản ở những vị trí khác trong chương trình ngoài hộp tin nhắn. Ví dụ: một nhãn dọc theo lưới hiển thị số dòng được chọn trong lưới sẽ có cùng một vấn đề liên quan đến đa dạng hóa.

Vì vậy, điều này về cơ bản áp dụng cho hầu hết văn bản được xuất ra theo một cách nào đó từ các chương trình, và sau đó giải pháp không đơn giản là chỉ cần thay đổi chương trình để không xuất văn bản nữa :)


6
@ 0xA3: Tôi thực sự không biết liệu mọi ngôn ngữ đều có tính đa dạng hóa dễ diễn đạt như "(các) mục".
Jens

5
Bạn có lẽ cũng nên nghĩ về bản địa hóa. Vấn đề này có thể trở nên tồi tệ hơn rất nhiều.
Alex Brown,

4
@Jens: Họ thường không, theo những cách ít thuận tiện nhất có thể. Một số ngôn ngữ có ví dụ đa dạng khác nhau cho 2-4 so với 5-infinity, tất cả điều đó tùy thuộc vào giới tính. "Natural Languages: Localization Madness! Sắp có máy tính ở gần bạn!"
Piskvor rời tòa nhà vào

29
IMO, không có gì khiến các lập trình viên trông lười biếng hơn đối với người dùng hơn là sự đa số tồi.
Greg

4
@ Øyvind: +1 cho Chỉnh sửa của bạn. Có vẻ như nhiều "người trả lời" ở đây có ý định chứng minh rằng câu hỏi của bạn là sai, hơn là đưa ra một giải pháp đúng. Các giải pháp chống, nếu bạn muốn.
mwolfe02

Câu trả lời:


53

Nếu có bất kỳ cơ hội nào, dù nhỏ đến mức nào, ứng dụng này sẽ cần được dịch sang các ngôn ngữ khác thì cả hai đều sai. Cách chính xác để làm điều này là:

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

Điều này là do các ngôn ngữ khác nhau xử lý số nhiều khác nhau. Một số như tiếng Mã Lai thậm chí không có số nhiều cú pháp nên các chuỗi nói chung sẽ giống hệt nhau. Tách hai chuỗi giúp hỗ trợ các ngôn ngữ khác sau này dễ dàng hơn.

Mặt khác, nếu ứng dụng này được sử dụng bởi công chúng và được cho là thân thiện với người dùng thì phương pháp thứ hai sẽ thích hợp hơn. Xin lỗi, tôi không thực sự biết một cách ngắn hơn để làm điều này.

Nếu ứng dụng này chỉ được sử dụng trong nội bộ công ty của bạn thì hãy làm theo cách tắt "item(s)". Bạn không thực sự phải gây ấn tượng với bất kỳ ai khi viết mã enterprisy. Nhưng tôi khuyên bạn không nên làm điều này đối với ứng dụng được sử dụng công khai vì điều này tạo ấn tượng rằng lập trình viên lười biếng và do đó hạ thấp quan điểm của họ về chất lượng của ứng dụng. Tin tôi đi, những việc nhỏ nhặt như thế này.


35
Trong khi tôi đồng ý với tiền đề, Bạn đang bỏ qua các ngôn ngữ có nhiều hơn hai mức độ. (Lấy ví dụ như tiếng Nga. Ba cách nói khác nhau tùy thuộc vào việc 1, <5 hay> = 5 của nó và thậm chí điều đó phụ thuộc vào chính xác những gì bạn đang nói). Về cơ bản, tôi đang nói rằng bạn cần một câu lệnh điều kiện mạnh hơn và không chỉ là một toán tử bậc ba.
crashic

4
Bạn thậm chí có thể tối ưu hóa noofitemsselectedtrong ví dụ này cho tùy chọn đầu tiên; vì bạn biết nó là 1.
Mặc định

16
Trong khi chúng ta đang ở đó, tiếng Do Thái có thể có các đa nguyên khác nhau cho 1, 2, 3-10 và 11+.
Joel Spolsky

3
@Joel, tiếng Do Thái có thể có nhiều đa nguyên khác nhau? לא ידעתי (Tôi không biết)! Modern Hebrew cũng giống như tiếng Anh như xa như số nhiều đi (mặc dù cổ Hebrew cũng có một hình thức kép.)
Ken Bloom

3
Trong tiếng Anh, số 0 được coi như số nhiều (0 mục, 2 mục); điều gì xảy ra với số 0 trong tiếng Do Thái, tiếng Nga, tiếng Romania? Có cách nào đơn giản để xác định các phạm vi không? Tôi đoán rằng thông tin phải được xác định theo ngôn ngữ, vì vậy bất kỳ hệ thống nào dựa trên tệp tin nhắn đều phải xử lý số lượng đa dạng khác nhau trong một nhóm thông báo. Ôi chao! Việc thiết lập các bản dịch cũng sẽ phức tạp - cần có số lượng thông báo khác nhau cho các ngôn ngữ khác nhau.
Jonathan Leffler

94

Bạn có thể tránh tất cả mớ hỗn độn này bằng cách chỉ xóa các mục mà không có bất kỳ thông báo nào và cung cấp cho người dùng một cơ sở Hoàn tác thực sự tốt. Người dùng không bao giờ đọc bất cứ thứ gì . Dù sao thì bạn cũng nên xây dựng một cơ sở Hoàn tác tốt như một phần của chương trình của mình.

Bạn thực sự nhận được 2 lợi ích khi bạn tạo một cơ sở Hoàn tác toàn diện. Lợi ích đầu tiên làm cho cuộc sống của người dùng dễ dàng hơn bằng cách cho phép họ sửa lỗi và giảm thiểu việc đọc. Lợi ích thứ hai là ứng dụng của bạn phản ánh cuộc sống thực bằng cách cho phép đảo ngược quy trình làm việc không tầm thường (không chỉ là những sai lầm).

Tôi đã từng viết một ứng dụng mà không sử dụng một hộp thoại hoặc thông báo xác nhận nào. Nó cần một số suy nghĩ nghiêm túc và khó thực hiện hơn đáng kể so với việc sử dụng thông báo loại xác nhận. Nhưng kết quả cuối cùng là khá tốt để sử dụng theo người dùng cuối của nó.


12
Vì một số lý do, tôi thực sự cảm thấy như tôi đồng ý với điều này và nên ủng hộ nó.
Cody Grey

4
@ Øyvind, Đây là lý do tại sao: Các tin nhắn yêu cầu người dùng xác minh rất tốn kém đối với người dùng, đặc biệt là khi chúng được trình bày dưới dạng một hộp thoại phương thức dừng mọi thứ cho đến khi người dùng trả lời hộp thoại. Điều này gây khó chịu cho nhiều người dùng, đến mức họ bắt đầu chỉ cần nhấp vào bất kỳ nút nào để vượt qua hộp thoại (có bao nhiêu trình cài đặt bạn vừa nhấp tiếp theo, tiếp theo, tiếp theo? ). Do đó, nó an toàn hơn và ít gây khó chịu cho người dùng hơn nhiều nếu bạn chỉ thực hiện thao tác xóa nhẹ và cung cấp khả năng hoàn tác. Gmail sử dụng kỹ thuật này rất hiệu quả.
Robert Harvey

5
Có thể gỡ bỏ, nhưng trong mọi trường hợp, vấn đề tương tự sẽ xuất hiện trong các trường hợp khác với thông báo xác nhận về việc xóa, vì vậy câu trả lời này thực sự phù hợp với câu hỏi.
Jay

50
tôi đã ủng hộ cái này mà không đọc nó. i luôn có thể lùi lại nó sau này
Steven A. Lowe

6
@Robert Harvey: Có lẽ là ngụy tạo, nhưng nhiều năm trước, tôi đọc rằng Lotus đã vận chuyển 40.000 đơn vị Lotus Notes cho Mac và 60.000 đã được trả lại. Giao diện tệ đến nỗi ngay cả những người đã vi phạm bản quyền đã gửi nó trở lại.
Duncan

39

Làm thế nào về chỉ:

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

Bằng cách đó, bạn sẽ loại bỏ những khó khăn trong thỏa thuận số và kết thúc bằng một thông báo lỗi thậm chí ngắn hơn, trọng điểm hơn cho người dùng như một phần thưởng. Chúng ta đều biết người dùng không đọc thông báo lỗi . Chúng càng ngắn thì càng có nhiều khả năng ít nhất là họ lướt qua văn bản.

Hoặc, trang bị kiến ​​thức rằng người dùng không đọc thông báo lỗi, bạn có thể tiếp cận điều này theo một cách khác. Bỏ qua hoàn toàn thông báo xác nhận và chỉ cung cấp tính năng hoàn tác Just Works, bất kể nội dung đã bị xóa. Hầu hết người dùng đã quen với việc hoàn tác một thao tác khi họ nhận thấy đó không phải là điều họ muốn và có khả năng thấy hành vi này tự nhiên hơn so với việc phải đối phó với một cửa sổ bật lên gây phiền nhiễu khác.


1
Câu trả lời tốt. Tuy nhiên, trong trường hợp này, khách hàng đã yêu cầu cung cấp thông báo lỗi cho nhiều trường hợp vì anh ta cảm thấy đó là cách tiếp cận tốt nhất. Nhưng thay đổi văn bản ít nhất có thể giảm thiểu vấn đề và làm cho nó bớt lộn xộn hơn.
Øyvind Bråthen

@ Øyvind: Đủ công bằng. Vì bạn phải theo dõi khách hàng, tôi sẽ thực hiện cách tiếp cận đầu tiên mà tôi đã đề xuất hoặc sử dụng tệp Tài nguyên có chức năng xử lý. Tôi chỉ nghĩ rằng nó đáng để chỉ ra một giải pháp thay thế vì nó rất dễ bị lãng quên. Heck, tôi thậm chí còn không nghĩ về nó cho đến khi tôi gửi phản hồi đầu tiên của mình.
Cody Grey

Các lựa chọn thay thế được hoan nghênh nhất. Đó là lý do tại sao tôi cũng đã cho nó +1 :)
Øyvind Bråthen

1
+1 vì không cố gắng giải quyết vấn đề nan giải. Và hãy nhớ định luật Steve Krug: Bỏ đi một nửa số từ. Sau đó làm lại. Tôi sử dụng: "Xóa {x} mục?"
Serge Wautier

20

Còn những gì Java đã có trong nhiều năm: java.text.MessageFormat và ChoiceFormat? Xem http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html để biết thêm thông tin.

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.

Trong trường hợp của bạn, bạn muốn một cái gì đó đơn giản hơn một chút:

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

Ưu điểm của cách tiếp cận này là nó hoạt động tốt với các gói i18n và bạn có thể cung cấp bản dịch phù hợp cho các ngôn ngữ (như tiếng Nhật) không có khái niệm về từ số nhiều hoặc số ít.


1
Cách tiếp cận này hoạt động tốt để xử lý số nhiều nhưng không xử lý giới tính, thật đáng buồn. Bạn cần một chuỗi khác nhau cho từng loại thứ có thể bị xóa.
Ông Shiny và Mới 安 宇

Nếu bạn biết danh từ, bạn có thể sắp xếp các câu để làm việc với tính từ thích hợp. Nhưng đúng vậy, sau khi học tiếng Hy Lạp cổ điển, bạn có một dạng khác của từ dựa trên danh từ giống đực, giống cái hoặc danh từ riêng (tính từ mang hình thức của danh từ mà nó bổ sung) và hình thức khác nhau dựa trên chức năng của nó trong câu ( chủ thể, tân ngữ, v.v.). Chúng tôi luôn có thể đưa ra các trường hợp giải pháp này hoạt động và giải pháp khác thì không. Đây là cách mà những người Java đã cố gắng giải quyết vấn đề. Bạn vẫn phải cẩn thận với cách bạn tạo các định dạng tin nhắn.
Berin Loritsch

Bạn luôn có thể cung cấp giải pháp Java hai số nguyên, trong đó số nguyên thứ hai cho biết giới tính. (Tuy nhiên, trong thực tế, thỏa thuận về giới thường là ít hơn của một mối quan tâm đơn giản chỉ vì các trường hợp sử dụng phù hợp đối tượng khác nhau vào một tin nhắn là ít thường xuyên hơn phù hợp các số khác nhau của cùng một đối tượng vào một tin nhắn)
Ken Bloom

12

Tôi không muốn mã hóa thư cứng mà cung cấp hai thư trong một tệp Tài nguyên riêng biệt. Giống

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

và sau đó đưa chúng vào String.Format như

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

string message = String.Format(messageTemplate, noofitemsselected)

Tôi nghĩ rằng cách tiếp cận này dễ dàng hơn để bản địa hóa và duy trì. Tất cả các thông báo giao diện người dùng sẽ ở một vị trí duy nhất.


+1, tôi thích cách tiếp cận này. Mặc dù, bạn sẽ cần phải theo dõi các tên tài nguyên tương đương.
Mặc định

11

Bạn có thể tránh hoàn toàn vấn đề bằng cách diễn đạt thông điệp theo cách khác.

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

10

Điều đầu tiên tôi đề nghị là: sử dụng string.Format. Điều đó cho phép bạn làm điều gì đó như sau:

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

Hơn nữa, trong các ứng dụng WPF, tôi đã thấy các hệ thống trong đó một chuỗi tài nguyên sẽ được phân cách bằng dấu sổ đứng để có hai thông báo: một thông báo số ít và số nhiều (hoặc một thông báo không / đơn / nhiều, thậm chí). Sau đó, một trình chuyển đổi tùy chỉnh có thể được sử dụng để phân tích cú pháp tài nguyên này và sử dụng chuỗi (đã định dạng) có liên quan, vì vậy Xaml của bạn giống như sau:

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

7

Đối với tiếng Anh, rất nhiều câu trả lời ở trên. Đối với các ngôn ngữ khác thì khó hơn, vì số nhiều phụ thuộc vào giới tính của danh từ và đuôi từ. Một số ví dụ bằng tiếng Pháp:

Nam tính thường xuyên:

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

Nữ tính thường xuyên

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

Nam tính bất thường (kết thúc bằng 's')

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

Vấn đề tương tự cũng tồn tại trong hầu hết các ngôn ngữ Latinh và trở nên tồi tệ hơn ở tiếng Đức hoặc tiếng Nga, nơi có 3 giới tính (maculine, nữ tính và ngoại lai).

Bạn sẽ cần phải cẩn thận nếu mục tiêu của bạn là xử lý nhiều thứ hơn là chỉ tiếng Anh.


Ít nhất trong trường hợp của tôi, đây không thực sự là một vấn đề. Đối với mỗi văn bản tôi muốn chèn số, tôi sẽ biết danh từ là gì khi tạo chuỗi. Nhưng để đưa ra một giải pháp chung hơn, tôi đồng ý với bạn, rằng để làm cho nó hoạt động cho "tất cả" ngôn ngữ có thể là một nhiệm vụ rất khó, nếu không muốn nói là bất khả thi.
Øyvind Bråthen

1
Hoặc lấy tiếng Ba Lan, trong đó hình thức số nhiều của danh từ được sử dụng là khác nhau tùy thuộc vào số lượng! : /
UpTheCreek,

5

Để có thể có các tin nhắn đa tập trung có thể được bản địa hóa đúng cách, ý kiến ​​của tôi là trước tiên nên tạo một lớp chuyển hướng giữa số và một tin nhắn.

Ví dụ: sử dụng một hằng số của một số loại để chỉ định thông báo bạn muốn hiển thị. Tìm nạp thư bằng một số chức năng sẽ ẩn chi tiết triển khai.

get_message(DELETE_WARNING, quantity)

Tiếp theo, tạo một từ điển chứa các thông điệp và biến thể có thể có, đồng thời tạo các biến thể để biết khi nào chúng nên được sử dụng.

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

Bây giờ bạn có thể đơn giản tìm khóa tương ứng với quantityvà nội suy giá trị của quantityvới thông báo đó.

Ví dụ đơn giản và ngây thơ này, nhưng tôi thực sự không thấy bất kỳ cách nào khác lành mạnh để làm điều này và có thể cung cấp hỗ trợ tốt cho L10N và I18N.


5

Bạn sẽ phải dịch hàm bên dưới từ VBA sang C #, nhưng cách sử dụng của bạn sẽ thay đổi thành:

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

Tôi có một hàm VBA mà tôi sử dụng trong MS Access để thực hiện chính xác những gì bạn đang nói. Tôi biết mình sẽ bị tấn công vì đăng VBA, nhưng dù sao đi nữa. Thuật toán phải rõ ràng từ các nhận xét:

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

Việc sử dụng đã bị cắt một chút trong các bình luận mã ở trên, vì vậy tôi sẽ lặp lại nó ở đây:

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

Có, giải pháp này bỏ qua các ngôn ngữ không phải là tiếng Anh. Điều đó quan trọng hay không tùy thuộc vào yêu cầu của bạn.


4

Bạn có thể tạo số nhiều tự động, xem ví dụ. bộ tạo số nhiều .

Để biết quy tắc tạo số nhiều, hãy xem wikipedia

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

Tôi thích sử dụng phương pháp này nếu ứng dụng không được quốc tế hóa. Puralising dẫn đến một ứng dụng bóng bẩy hơn.
cspolton

1
Nó thực sự khó khăn để quốc tế hóa này, và nó thường không bằng tiếng Anh ví dụ: "Bạn có đơn đặt hàng + numMice + GetPlural (" chuột "numMice)"
James Anderson

@James Anderson: Bây giờ, đó không phải là ví dụ tốt nhất về mặt ngữ pháp ;-) Đừng rơi vào bẫy khi nghĩ rằng sử dụng phương thức GetPural là phương pháp duy nhất mà bạn được phép sử dụng.
cspolton

cùng với một vài chức năng khác để xử lý một vài trường hợp góc hơn, tôi nghĩ đây là một giải pháp rất tốt, không ngắn hơn.
lalli

4

Làm thế nào về một cách chung chung hơn. Tránh đa nghĩa trong câu thứ hai:

Số mục đã chọn sẽ bị xóa: noofitemsselected.
Bạn có chắc không?

Tôi phát hiện ra rằng làm theo cách này đặt số ở cuối dòng, điều này thực sự dễ dàng nhận ra. Giải pháp này sẽ hoạt động với cùng một logic trong bất kỳ ngôn ngữ nào.


"Các mục được chọn sẽ bị xóa:" nghe không ổn, câu chỉ ra một danh sách tên, nhưng một con số được in ra. Ngay cả khi được thay đổi thành "Số mục cần xóa:", thì "mục" vẫn là điều khó xử.
lalli

@lalli: Vâng, từ ngữ không hoàn hảo và không có giải pháp nào được cung cấp âm thanh hoàn hảo. Tôi chỉ đề nghị đặt nó ở dạng như nhãn và giá trị. Bạn nói đúng Number(tôi đã trả lời trong khi đung đưa con tôi ngủ).
Danosaure

4

Cách tiếp cận chung của tôi là viết một "hàm đơn / số nhiều", như sau:

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

Sau đó, trong phần nội dung của tin nhắn, tôi gọi hàm này:

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

Điều này không tốt hơn nhiều, nhưng ít nhất nó, (a) đưa ra quyết định trong một hàm và do đó, cắt ngắn mã một chút, và (b) đủ linh hoạt để xử lý số nhiều bất thường. tức là nó đủ dễ dàng để nói danh từ (n, "con", "trẻ em") và tương tự.

Tất nhiên điều này chỉ phù hợp với tiếng Anh, nhưng khái niệm này có thể dễ dàng mở rộng sang các ngôn ngữ có phần cuối phức tạp hơn.

Tôi xảy ra với tôi rằng bạn có thể đặt tham số cuối cùng là tùy chọn cho trường hợp dễ dàng:

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
Tôi thích phần cuối cùng của bạn, nơi bạn sử dụng một giá trị mặc định để "bỏ sắp xếp" mã trong trường hợp hoạt động mặc định thêm một chữ s để phân bổ danh từ.
Øyvind Bråthen

4

Quốc tế hóa

Tôi giả sử bạn muốn hỗ trợ quốc tế hóa, trong trường hợp đó các ngôn ngữ khác nhau có các mẫu số nhiều khác nhau (ví dụ: dạng số nhiều đặc biệt cho 2 trong số đó hoặc các ngôn ngữ phức tạp hơn như tiếng Ba Lan) và bạn không thể dựa vào việc áp dụng một số mẫu đơn giản cho chuỗi của mình để sửa chữa nó.

Bạn có thể sử dụng ngettextchức năng của GNU Gettext và cung cấp hai thông báo tiếng Anh trong mã nguồn của bạn. Gettext sẽ cung cấp cơ sở hạ tầng để chọn từ các thư khác (có thể nhiều hơn) khi được dịch sang các ngôn ngữ khác. Xem http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html để biết mô tả đầy đủ về hỗ trợ số nhiều của GNU gettext.

GNU Gettext thuộc LGPL. ngettextđược đặt tên GettextResourceManager.GetPluralStringtrong cổng C # của Gettext.

(Nếu bạn không cần hỗ trợ bản địa hóa và không muốn sử dụng Gettext ngay lập tức, thì hãy viết hàm của riêng bạn để thực hiện điều này cho tiếng Anh và chuyển hai thông báo đầy đủ cho nó, theo cách đó nếu sau này bạn cần l10n, bạn có thể thêm bằng cách viết lại một chức năng.)


3

Cách viết hàm như thế nào

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

.. và sử dụng nó bất cứ khi nào bạn cần?

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

3
bạn không nghĩ về điều đó đã làm bạn lol, bạn có một chức năng để sắp xếp ra nhân lên hay không cho các câu sau đó bạn đi một đặt "nó / họ" ở cuối dòng lol
Barkermn01

Bạn chỉ nên chuyển hai thông báo cho toàn bộ câu cho chức năng này.
Ken Bloom

Đó chỉ là một ví dụ. Tôi nhận thấy rằng biến thể để gửi toàn bộ câu là đúng hơn.
Pavel Morshenyuk

3

Đối với vấn đề đầu tiên, ý tôi là Pluralia, bạn có thể sử dụng Inflector .

Và đối với thứ hai, bạn có thể sử dụng một phần mở rộng đại diện chuỗi có tên chẳng hạn như ToPronounString.


3

Tôi đã có câu hỏi chính xác này được đặt ra cho tôi ngày hôm qua bởi một thành viên trong nhóm của chúng tôi.

Kể từ khi nó xuất hiện một lần nữa ở đây trên StackOverflow, tôi nhận ra rằng vũ trụ đang bảo tôi phải có một chút thời gian để tạo ra một giải pháp tốt.

Tôi đã nhanh chóng tập hợp một số thứ lại với nhau và nó không có nghĩa là hoàn hảo, tuy nhiên nó có thể được sử dụng hoặc châm ngòi cho một số cuộc thảo luận / phát triển.

Mã này dựa trên ý tưởng rằng có thể có 3 tin nhắn. Một cho không mục, một cho một mục và một cho nhiều hơn một mục tuân theo cấu trúc sau:

singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural

Tôi đã tạo một lớp nội bộ để kiểm tra nhằm bắt chước lớp tài nguyên. Tôi chưa kiểm tra điều này bằng cách sử dụng tệp tài nguyên thực tế nên tôi chưa thấy kết quả đầy đủ.

Đây là đoạn mã (hiện tại tôi đã bao gồm một số thông số chung mà tôi biết rằng tôi có thể chỉ định tham số thứ ba chỉ đơn giản là Loại và cũng tham số thứ hai là một chuỗi, tôi nghĩ có cách để kết hợp hai tham số này thành một thứ gì đó tốt hơn nhưng tôi ' Tôi sẽ quay lại điều đó khi tôi có thời gian rảnh rỗi.

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

Kiểm tra lớp tài nguyên:

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

và phương pháp thực thi nhanh chóng của tôi

void Main()
{
    var message = GetMessage(56, "Tester",typeof(TestMessenger));
    message.Dump();
}

Nếu bạn muốn điều này thực sự hoàn chỉnh, bạn cũng nên thêm thông báo cho singlePropertyName_Allđể làm cho nó rõ ràng hơn.
Danosaure

2

Theo quan điểm của tôi, giải pháp đầu tiên của bạn là giải pháp phù hợp nhất. Tại sao tôi lại nói như vậy, trong trường hợp bạn cần ứng dụng hỗ trợ nhiều ngôn ngữ, thì tùy chọn thứ hai có thể khó. Với cách tiếp cận nắm tay, bạn có thể dễ dàng khoanh vùng văn bản mà không cần nỗ lực nhiều.


2

Bạn có thể tìm một thông báo chung chung hơn như 'Bạn có chắc chắn muốn xóa (các) mục đã chọn'.


3
Điều này chắc chắn hiệu quả, nhưng tôi nghĩ ý tưởng của người hỏi về việc hiển thị số lượng mục sắp bị xóa trong nháy mắt là một ý tưởng hay. Nhiều lần, tôi đã cố gắng xóa một tệp khỏi màn hình của mình và vô tình xóa nhiều tệp đó.
Cody Grey

2

Tôi phụ thuộc vào mức độ tốt đẹp của một thông điệp bạn muốn có. Từ dễ nhất đến khó nhất:

  1. Viết lại thông báo lỗi của bạn để tránh đa dạng hóa. Không tốt cho người dùng của bạn, nhưng nhanh hơn.

  2. Sử dụng ngôn ngữ chung hơn nhưng vẫn bao gồm (các) số.

  3. Sử dụng hệ thống "đa năng hóa" và hệ thống cảm biến ala Rails, vì vậy bạn có thể nói pluralize(5,'bunch')và nhận 5 bunches. Rails có một mô hình tốt cho việc này.

  4. Để quốc tế hóa, bạn cần xem những gì Java cung cấp. Điều đó sẽ hỗ trợ nhiều loại ngôn ngữ, bao gồm cả những ngôn ngữ có các dạng tính từ khác nhau với 2 hoặc 3 mục. Giải pháp "s" rất tập trung vào tiếng Anh.

Lựa chọn nào bạn chọn tùy thuộc vào mục tiêu sản phẩm của bạn. - ndp


2

Tại sao bạn muốn trình bày một thông điệp mà người dùng thực sự có thể hiểu được? Nó đi ngược lại lịch sử 40 năm lập trình. Nooooo, chúng ta có một chuyện tốt đang diễn ra, đừng làm hỏng nó bằng những tin nhắn dễ hiểu .


(j / k)


+1: cũng tốt khi thấy một số hài hước bên trong đây. Nhưng ngay cả khi bạn đang đùa, tôi hiểu điểm cơ bản của bạn. Nhiều chương trình được tạo ra trong nhiều năm có thông điệp cực kỳ xấu. Thông thường bởi vì họ có cách để người dùng bình thường hiểu được.
Øyvind Bråthen

Điểm tốt. Tôi luôn thích nó khi tôi nhận được một thông báo như "Lỗi 494-B khi người dùng nhập" - nó bổ sung thêm một bí ẩn nhỏ về những gì sai khiến cuộc sống trở nên thú vị hơn rất nhiều. Gần đây, tôi đã gặp lỗi khi cố tạo mật khẩu có nội dung đơn giản là "Mật khẩu không đáp ứng yêu cầu bảo mật". Không có gợi ý nào về yêu cầu mà tôi không đáp ứng được. Mật khẩu của tôi bao gồm cả chữ hoa và chữ thường và một số chữ số. Tôi đã thử thêm một ký tự đặc biệt. Vẫn không có. Cuối cùng nó đã trôi qua khi tôi XÓA một ký tự. Tôi nghĩ rằng họ đã có một quy tắc rằng bạn không thể có cùng một ký tự hai lần liên tiếp.
Jay

2

Làm điều đó giống như đã làm trong World of Warcraft:

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

0

Nó ngắn hơn một chút với

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

0

Một cách tiếp cận mà tôi chưa thấy đề cập sẽ là sử dụng thẻ thay thế / chọn (ví dụ như "Bạn sắp sửa {0} [? I ({0} = 1): / cactus / cacti /]". (nói cách khác, có một biểu thức giống như định dạng chỉ định sự thay thế dựa trên việc đối số bằng 0, được coi là số nguyên, bằng 1). Tôi đã thấy các thẻ như vậy được sử dụng trong những ngày trước .net; Tôi không biết bất kỳ tiêu chuẩn cho chúng trong .net, tôi cũng không biết cách tốt nhất để định dạng chúng.


0

Tôi sẽ nghĩ ra trong vòng một phút, tất cả các đề xuất ở đây là thực hiện đa dạng hóa (và lo lắng về hơn 1 cấp độ đa dạng hóa, giới tính, v.v.) hoặc không sử dụng nó và cung cấp một hoàn tác tốt.

Tôi sẽ đi theo cách không ngôn ngữ và sử dụng hàng đợi trực quan cho điều đó. Ví dụ: hãy tưởng tượng một ứng dụng Iphone bạn chọn các mục bằng cách lau ngón tay của bạn. trước khi xóa chúng bằng nút xóa chính, nó sẽ "lắc" các mục đã chọn và hiển thị cho bạn một hộp có tiêu đề dấu chấm hỏi với các nút V (ok) hoặc X (hủy) ...

Hoặc, trong thế giới 3D của Kinekt / Move / Wii - hãy tưởng tượng chọn tệp, di chuyển bàn tay của bạn đến nút xóa và được yêu cầu di chuyển bàn tay của bạn trên đầu để xác nhận (sử dụng các biểu tượng trực quan giống như tôi đã đề cập trước đây. Ví dụ: yêu cầu bạn xóa 3 tệp? nó sẽ hiển thị cho bạn 3 tệp có dấu X màu đỏ nửa trong suốt đang lơ lửng và yêu cầu bạn làm điều gì đó để xác nhận.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.