用户消息中存在多个

发布于 2024-10-03 21:38:47 字数 1104 浏览 10 评论 0原文

很多时候,当生成向用户显示的消息时,该消息将包含许多我想告知客户的内容。

我举个例子:客户从 1 个及以上选择了多个商品,并单击了删除。现在我想向客户发出确认消息,并且我想提及他选择的项目数量,以最大程度地减少他犯错误的机会,通过选择一堆项目并在他只想删除其中一个项目时单击删除他们。

一种方法是像这样制作通用消息:

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

这里的“问题”是 noofitemselected 为 1 的情况,我们必须编写 itemit< /em> 而不是项目它们

我的正常解决方案将是这样的

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

如果代码中存在许多对数字复数的引用,并且实际消息变得难以阅读,那么这会变得相当长并且非常令人讨厌。

所以我的问题很简单。有没有更好的方法来生成这样的消息?

编辑

我看到很多人对我提到的消息应该显示在消息框中的情况感到非常困惑,并且只是给出了如何避免使用消息框的答案无论如何,那都很好。

但请记住,除了消息框之外,复数问题也适用于程序中其他位置的文本。例如,网格旁边的标签显示网格中所选行的数量,在复数方面也会出现相同的问题。

所以这基本上适用于程序以某种方式输出的大多数文本,然后解决方案并不像仅仅将程序更改为不再输出文本那么简单:)

Many times, when generating messages to show to the user, the message will contain a number of something that I want to inform the customer about.

I'll give an example: The customer has selected a number of items from 1 and up, and has clicked delete. Now I want to give a confirmation message to the customer, and I want to mention the number of items he has selected to minimize the chance of him making a mistake by selecting a bunch of items and clicking delete when he only wants to delete one of them.

One way is to make the generic message like this:

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

The "problem" here is the case where noofitemselected is 1, and we have to write item and it instead of items and them.

My normal solution will be something like this

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

This gets quite long and quite nasty really fast if there are many references to the numbers plurality inside the code, and the actual message gets hard to read.

So my questions is simply. Are there any better ways of generating messages like this?

EDIT

I see a lot of persons has got very hung up in the case that I mentioned that the message should be displayed inside a message box, and has simply given an answer of how to avoid using the message box at all, and that is all good.

But remember that the problem of pluralization also apply to texts other places in the program in addition to message boxes. For example, a label alongside a grid displaying the number of lines selected in the grid will have the same problem regarding pluralization.

So this basically apply to most text that is outputted in some way from programs, and then the solution is not as simple as to just change the program to not output text anymore :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(25

秋凉 2024-10-10 21:38:47

您可以通过仅删除不带任何消息的项目并为用户提供非常好的撤消功能来避免所有这些混乱的复数。 用户从不阅读任何内容。无论如何,您应该建立一个良好的撤消工具作为您计划的一部分。

当您创建全面的撤消工具时,您实际上可以获得两个好处。第一个好处是允许用户纠正错误并尽量减少阅读,从而使他/她的生活变得更轻松。第二个好处是,您的应用程序通过允许逆转重要的工作流程(而不仅仅是错误)来反映现实生活。

我曾经编写过一个应用程序,但没有使用单个对话框或确认消息。这需要认真思考,并且比使用确认类型消息更难实现。但根据最终用户的说法,最终结果相当好用。

You can avoid all of this messy plurality by just deleting the items without any message and giving the user a really good Undo facility. Users never read anything. You should build a good Undo facility as part of your program anyway.

You actually get 2 benefits when you createe a comprehensive Undo facility. The first benefit makes the user's life easier by allowing him/her to reverse mistakes and minimise reading. The second benefit is that your app is reflecting real life by allowing the reversal of non-trivial workflow (not just mistakes).

I once wrote an app without using a single dialog or confirmation message. It took some serious thinking and was significantly harder to implement than using confirmation-type messages. But the end result was rather nice to use according to its end-users.

想你的星星会说话 2024-10-10 21:38:47

如果有任何机会,无论多么小,这个应用程序需要翻译成其他语言,那么两者都是错误的。正确的做法是:

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)”操作。在编写企业代码时,您实际上不必给任何人留下深刻的印象。但我建议不要对公共使用的应用程序这样做,因为这会给人留下程序员懒惰的印象,从而降低他们对应用程序质量的看法。相信我,像这样的小事很重要。

If there is ever any chance, no matter how small, that this app will need to be translated to other languages then both are wrong. The correct way of doing this is:

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

This is because different languages handle plurality differently. Some like Malay don't even have syntactic plurals so the strings would generally be identical. Separating the two strings makes it easier to support other languages later on.

Otherwise if this app is meant to be consumed by the general public and is supposed to be user friendly then the second method is preferable. Sorry but I don't really know a shorter way of doing this.

If this app is meant to be consumed only internally by your company then do the shortcut "item(s)" thing. You don't really have to impress anybody when writing enterprisy code. But I'd advise against doing this for publicly consumed app because this gives the impression that the programmer is lazy and thus lower their opinion of the quality of the app. Trust me, small things like this matter.

满栀 2024-10-10 21:38:47

怎么样:

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

这样,您就可以消除号码协议困难,并最终为用户提供更短、更中肯的错误消息作为奖励。我们都知道用户无论如何也不会阅读错误消息。它们越短,他们就越有可能至少浏览文本。

或者,知道用户不会阅读错误消息,您就可以采用不同的方式来解决此问题。完全跳过确认消息,只提供一个可以正常工作的撤消功能,无论删除了什么。大多数用户已经习惯于在发现操作不是他们想要的时撤消操作,并且可能会发现这种行为比处理另一个烦人的弹出窗口更自然。

How about just:

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

That way, you eliminate the number agreement difficulties, and end up with an even shorter, more to-the-point error message for the user as a bonus. We all know users don't read error messages anyway. The shorter they are, the more likely they are to at least glance at the text.

Or, armed with this knowledge that users don't read error messages, you could approach this a different way. Skip the confirmation message altogether, and just provide an undo feature that Just Works, regardless of what was deleted. Most users are already accustomed to undoing an operation when they notice it was not what they wanted, and are likely to find this behavior more natural than having to deal with another annoying pop-up.

仙女山的月亮 2024-10-10 21:38:47

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 捆绑包配合使用,并且您可以为没有复数或单数单词概念的语言(例如日语)提供正确的翻译。

What about what Java has had for years: java.text.MessageFormat and ChoiceFormat? See http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html for more information.

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.

In your case you want something somewhat simpler:

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

The advantage of this approach is that it works well with the i18n bundles, and you can provide translations properly for languages (like Japanese) that have no concept of plural or singular words.

对你的占有欲 2024-10-10 21:38:47

我不会对消息进行硬编码,而是在单独的资源文件中提供两条消息。就像

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)

我认为这种方法更容易本地化和维护。所有 UI 消息都将位于一个位置。

I'd go with not hardcoding the message, but providing two messages in an seperate Resource file. Like

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

and then feeding them into String.Format like

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

string message = String.Format(messageTemplate, noofitemsselected)

I think that this approach is easier to localize and maintain. All UI messages would be at a single locaion.

盗梦空间 2024-10-10 21:38:47

您可以通过以不同的方式措辞消息来完全回避这个问题。

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

You can sidestep the issue entirely by phrasing the message differently.

string message = "The number of selected items is " + noofitemsselected + ". Are you sure you want to delete everything in this selection?";
安静被遗忘 2024-10-10 21:38:47

我建议的第一件事是:使用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}}" />

The first thing I'd suggest is: use string.Format. That allows you to do something like this:

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

Further, in WPF apps, I've seen systems where a resource string would be pipe-delimited to have two messages: a singular and a plural message (or a zero/single/many message, even). A custom converter could then be used to parse this resource and use the relevant (formatted) string, so your Xaml is something like this:

<TextBlock Text="{Binding numOfItems, Converter={StaticResource c:NumericMessageFormatter}, ConverterParameter={StaticResource s:SuitableMessageTemplate}}" />
软的没边 2024-10-10 21:38:47

对于英语,上面有很多答案。对于其他语言来说,这更困难,因为复数取决于名词的性别和词尾。法语中的一些示例:

常规阳性:

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 种性别(男性、女性和中性)。

如果您的目标不仅仅是处理英语,那么您需要小心。

For English, plenty of answers above. For other languages it is more difficult, as plurals depend on the gender of the noun and the word ending. Some examples in French:

Regular masculine:

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

Regular feminine

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

Irregular masculine (finishes with 's')

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

The same problem exists in most Latin languages and gets worse in German or Russian, where there are 3 genders (maculine, feminine and neuter).

You'll need to take care if your objective is to handle more than just English.

春花秋月 2024-10-10 21:38:47

为了能够拥有能够正确本地化的多元化消息,我的观点是,首先在数字和消息之间创建一个间接层是明智的。

例如,使用某种常量来指定要显示的消息。使用一些隐藏实现细节的函数来获取消息。

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 提供良好的支持。

To be able to have pluralized messages which will be possible to localize properly, my opinion is that it would be wise to first create a layer of indirection between the number and a message.

For example, use a constant of some sort to specify which message you want to display. Fetch the message using some function that will hide the implementation details.

get_message(DELETE_WARNING, quantity)

Next, create a dictionary that holds the possible messages and variations, and make variations know when they should be used.

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

Now you could simply find the key that corresponds to the quantity and interpolate the value of the quantity with that message.

This oversimplified and naive example, but I don't really see any other sane way to do this and be able to provide good support for L10N and I18N.

水水月牙 2024-10-10 21:38:47

您必须将下面的函数从 VBA 转换为 C#,但您的用法将更改为:

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

我有一个在 MS Access 中使用的 VBA 函数来准确执行您所讨论的操作。我知道我会因为发布 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."

是的,这个解决方案忽略了非英语的语言。这是否重要取决于您的要求。

You'll have to translate the function below from VBA to C#, but your usage would change to:

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

I have a VBA function that I use in MS Access to do exactly what you are talking about. I know I'll get hacked to pieces for posting VBA, but here goes anyway. The algorithm should be apparent from the comments:

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

The usage got cut off a bit in the code comments above, so I'll repeat it here:

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

Yes, this solution ignores languages that are not English. Whether that matters depends on your requirements.

云淡月浅 2024-10-10 21:38:47

您可以自动生成复数形式,请参见例如。 复数生成器

有关复数生成规则,请参阅 wikipedia

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

You could generate the plural automatically, see eg. plural generator.

For plural generating rules see wikipedia

string msg = "Do you want to delete " + numItems + GetPlural(" item", numItems) + "?";
金橙橙 2024-10-10 21:38:47

更通用的方法怎么样?避免在第二句中使用复数:

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

我发现这样做会将数字放在行尾,这非常容易发现。该解决方案在任何语言中都可以使用相同的逻辑。

How about a more generic way. Avoid pluralization in the second sentence:

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

I find out that doing it this way puts the number at the end of the line which is really easy to spot. This solution would work with the same logic in any language.

一腔孤↑勇 2024-10-10 21:38:47

我的一般方法是编写一个“单/复数函数”,如下所示:

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,“孩子”,“孩子”)等。

当然,这只适用于英语,但这个概念很容易扩展到具有更复杂结尾的语言。

我认为对于简单的情况,您可以将最后一个参数设置为可选:

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

My general approach is to write a "single/plural function", like this:

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

Then in the body of the message I call this function:

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

This isn't a whole lot better, but at least it, (a) puts the decision in a function and so unclutters the code a little, and (b) is flexible enough to handle irregular plurals. i.e. it's easy enough to say noun(n, "child", "children") and the like.

Of course this only works for English, but the concept is readily extensible to languages with more complex endings.

It occurs to me that you could make the last parameter optional for the easy case:

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;
}
生生不灭 2024-10-10 21:38:47

国际化

我假设您需要国际化支持,在这种情况下,不同的语言有不同的复数模式(例如,2 个某物的特殊复数形式,或更复杂的语言,如波兰语),并且您不能依赖于将一些简单的模式应用于您的语言。字符串来修复它。

您可以使用 GNU Gettext 的 ngettext 函数并在源代码中提供两条英文消息。 Gettext 将提供基础设施,以便在翻译成其他语言时从其他(可能更多)消息中进行选择。请参阅 http://www.gnu.org/software/hello/ Manual/gettext/Plural-forms.html 了解 GNU gettext 复数支持的完整描述。

GNU Gettext 遵循 LGPL。 ngettext 在 Gettext 的 C# 端口中被命名为 GettextResourceManager.GetPluralString

(如果您不需要本地化支持,并且不想立即使用 Gettext,则可以编写自己的函数来对英语执行此操作,并向其传递两条完整消息,这样如果稍后需要 l10n,可以通过重写单个函数来添加。)

Internationalization

I assume you want internationalization support, in which case different languages have different patterns for plurals (e.g. a special plural form for 2 of something, or more complicated languages like Polish), and you can't rely on applying some simple pattern to your string to fix it.

You can use GNU Gettext's ngettext function and provide two English messages in your source code. Gettext will provide the infrastructure to choose from other (potentially more) messages when translated into other languages. See http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html for a full description of GNU gettext's plural support.

GNU Gettext is under the LGPL. ngettext is named GettextResourceManager.GetPluralString in the C# port of Gettext.

(If you don't need localization support, and don't want to use Gettext right away, then write your own function that does this for English, and pass two full messages to it, that way if you need l10n later, you can add by rewriting a single function.)

離殇 2024-10-10 21:38:47

编写像

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

How about to write function like

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

.. and use it whenever you need?

string message = "You have selected " + GetOutputMessage(noofitemsselected,"item","items") + ". Are you sure you want to delete it/them?";
夜深人未静 2024-10-10 21:38:47

对于第一个问题,我的意思是 Pluralize,您可以使用 Inflector

对于第二个,您可以使用名称为 ToPronounString 的字符串表示扩展。

For the first problem , I mean Pluralize, you can use Inflector.

And for the second, you can use a string representation extension with a name such as ToPronounString.

羁拥 2024-10-10 21:38:47

昨天我们团队的一名成员向我提出了完全相同的问题。

自从它在 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();
}

I had this exact same question posed to me yesterday by a member of our team.

Since it came up again here on StackOverflow I figured the universe was telling me to have a bash at producing a decent solution.

I've quickly put something together and it's by no means perfect however it might be of use or spark some discussion/development.

This code is based on the idea that there can be 3 messages. One for zero items, one for one item and one for more than one item which follow the following structure:

singlePropertyName

singlePropertyName_Zero

singlePropertyName_Plural

I've created an internal class to test with in order to mimick the resource class. I haven't tested this using an actual resource file yet so I'm yet to see the full result.

Here's the code (currently i've included some generics where I know I could have specified the third param simply as a Type and also the second param is a string, I think there's a way to combine these two parameters into something better but I'll come back to that when I have a spare moment.

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

Test resource class:

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

and my quick executing method

void Main()
{
    var message = GetMessage(56, "Tester",typeof(TestMessenger));
    message.Dump();
}
提笔书几行 2024-10-10 21:38:47

从我的角度来看,您的第一个解决方案是最合适的。我之所以这样说是因为,如果您需要应用程序支持多种语言,那么第二种选择可能会很困难。使用第一种方法,无需太多努力即可轻松本地化文本。

From my point of view, your first solution is the most suited one. Why I say that is, in case you need the application to support multiple languages, the second option can be painstaking. With the fist approach it is easy to localize the text without much effort.

无语# 2024-10-10 21:38:47

您可以选择更通用的消息,例如“您确定要删除所选项目吗”。

You could go for a more generic message like 'Are you sure you want to delete the selected item(s)'.

血之狂魔 2024-10-10 21:38:47

我取决于你想收到多好的消息。从最简单到最难:

  1. 重写错误消息以避免复数。对您的用户来说不太好,但更快。

  2. 使用更通用的语言,但仍包含数字。

  3. 使用“复数化”和变形系统ala Rails,这样你就可以说pluralize(5,'bunch')并得到5串。 Rails 有一个很好的模式。

  4. 对于国际化,你需要看看Java提供了什么。这将支持多种语言,包括那些具有不同形式的形容词和 2 或 3 个项目的语言。 “s”解决方案非常以英语为中心。

选择哪个选项取决于您的产品目标。 - 国家发展计划

I depends on how nice a message you want to have. From easiest to hardest:

  1. Re-write your error message to avoid pluralization. Not as nice for your user, but faster.

  2. Use more general language but still include the number(s).

  3. Use a "pluralization" and inflector system ala Rails, so you can say pluralize(5,'bunch') and get 5 bunches. Rails has a good pattern for this.

  4. For internationalization, you need to look at what Java provides. That will support a wide variety of languages, including those that have different forms of adjectives with 2 or 3 items. The "s" solution is very English centric.

Which option you go with depends on your product goals. - ndp

寂寞笑我太脆弱 2024-10-10 21:38:47

为什么要呈现用户真正可以理解的消息?它违背了 40 年的编程历史。不,我们正在做一件好事,不要用可以理解的消息来破坏它。


(j/k)

Why would you want to present a message the users can actually understand? It goes against 40 years of programing history. Nooooo, we have a good thing going on, don't spoil it with understandable messages.


(j/k)

油焖大侠 2024-10-10 21:38:47

像魔兽世界中那样做:

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

Do it like it's done in World of Warcraft:

BILLING_NAG_WARNING = "Your play time expires in %d |4minute:minutes;";
辞旧 2024-10-10 21:38:47

它变得有点短

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

It gets a little bit shorter with

string message = "Are you sure you want to delete " + noofitemsselected + " item" + (noofitemsselected>1 ? "s" : "") + "?";
倾`听者〃 2024-10-10 21:38:47

我没有看到提及的一种方法是使用替换/选择标签(例如“您即将挤压 {0} [?i({0}=1):/cactus/cacti/]”)。 (换句话说,有一个类似格式的表达式根据参数零(作为整数)是否等于 1 来指定替换)。我在 .net 之前就见过这样的标签; .net 中的标准,我也不知道格式化它们的最佳方法。

One approach I haven't seen mentioned would be the use of a substitution/select tag (e.g. something like "You are about to squash {0} [?i({0}=1):/cactus/cacti/]". (in other words, have a format-like expression specify the substitution based upon whether argument zero, taken as an integer, equals 1). I've seen such tags used in the days before .net; I'm not aware of any standard for them in .net, nor do I know the best way to format them.

踏雪无痕 2024-10-10 21:38:47

我会开箱即用地思考一下,这里的所有建议要么进行复数化(并担心超过 1 级的复数化、性别等),要么根本不使用它并提供一个很好的撤消。

我会采用非语言方式并使用视觉队列。例如,想象一个 Iphone 应用程序,您通过擦拭手指来选择项目。在使用主删除按钮删除它们之前,它会“摇动”所选项目,并向您显示一个标题为问号的框,其中带有 V(确定)或 X(取消)按钮...

或者,在 Kinekt / Move 的 3D 世界中/ Wii - 想象一下选择文件,将手移至删除按钮,然后被告知将手移至头顶进行确认(使用与我之前提到的相同的视觉符号。例如,而不是要求您删除 3 个文件?它会显示您的 3 个文件上有一个悬停的半透明红色 X,并告诉您执行某些操作以进行确认。

I would think out of the box for a minute, all of the suggestions here are either do the pluralization (and worry about more than 1 level of pluralization, gender, etc) or not use it at all and provide a nice undo.

I would go the non lingual way and use visual queues for that. e.g. imagine an Iphone app you select items by wiping your finger. before deleting them using the master delete button, it will "shake" the selected items and show you a question mark titled box with a V (ok) or X (cancel) buttons...

Or, in the 3D world of Kinekt / Move / Wii - imagine selecting the files, moving your hand to the delete button and be told to move your hand above your head to confirm (using the same visual symbols as I mentioned before. e.g. instead of asking you delete 3 files? it will show you 3 files with a hovering half transparent red X on and tell you to do something to confirm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文