Øyv*_*hen 106 c# string localization pluralize
很多时候,当生成要向用户显示的消息时,该消息将包含一些我想要通知客户的内容.
我举一个例子:客户从1开始选择了多个项目,并点击了删除.现在我想给客户一个确认信息,我想提一下他选择的项目数量,以便通过选择一堆项目并在他只想删除其中一项时单击删除来最大限度地减少他犯错误的可能性.他们.
一种方法是制作如下通用消息:
int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " item(s). Are you sure you want to delete it/them?";
Run Code Online (Sandbox Code Playgroud)
"问题"这里是哪里的情况下noofitemselected是1,我们必须编写项目和它,而不是项目和它们.
我的正常解决方案将是这样的
int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " " + (noofitemsselected==1?"item" : "items") + ". Are you sure you want to delete " + (noofitemsselected==1?"it" : "them") + "?";
Run Code Online (Sandbox Code Playgroud)
如果代码中有许多对数字的引用,并且实际的消息难以阅读,那么这会非常长且非常讨厌.
所以我的问题很简单.有没有更好的方法来生成这样的消息?
编辑
我看到很多人在我提到消息应该显示在消息框中的情况下已经非常挂断了,并且简单地给出了如何避免使用消息框的答案,这一切都很好.
但请记住,除了消息框之外,复数化问题也适用于程序中其他地方的文本.例如,在显示网格中选择的行数的网格旁边的标签将具有与复数相同的问题.
所以这基本上适用于从程序中以某种方式输出的大多数文本,然后解决方案就不再那么简单,只需将程序更改为不再输出文本:)
Roa*_*ior 94
您可以通过删除没有任何消息的项目并为用户提供非常好的撤消功能来避免所有这些混乱的数据.用户从不读任何东西.无论如何,你应该建立一个良好的撤销设施作为你的程序的一部分.
当您创建一个全面的撤消设施时,您实际上可以获得2个好处.第一个好处是让用户改变错误并尽量减少阅读,从而使用户的生活更轻松.第二个好处是,您的应用程序通过允许逆转非平凡的工作流程(而不仅仅是错误)来反映现实生活.
我曾经在不使用单个对话框或确认消息的情况下编写应用程序.它花了一些认真的思考,并且比使用确认类型的消息更难实现.但最终结果是根据其最终用户使用相当不错.
sle*_*man 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?"
);
Run Code Online (Sandbox Code Playgroud)
这是因为不同的语言处理多个不同的.像马来语这样的人甚至没有语法复数,因此字符串通常是相同的.分离这两个字符串可以在以后更容易地支持其他语言.
否则,如果这个应用程序是由一般公众使用并且应该是用户友好的,那么第二种方法是更可取的.对不起,我真的不知道这样做的简短方法.
如果这个应用程序只能由您的公司内部使用,那么请执行快捷方式"item(s)".在编写企业代码时,你真的不必给任何人留下深刻的印象.但我建议不要为公开使用的应用程序执行此操作,因为这会给人一种程序员懒惰的印象,从而降低他们对应用程序质量的看法.相信我,像这件小事.
Cod*_*ray 39
怎么样:
string message = "Are you sure you want to delete " + noofitemsselected + " item(s)?"
Run Code Online (Sandbox Code Playgroud)
这样,您就可以消除号码协议的困难,并最终为用户提供更短,更准确的错误消息作为奖励.我们都知道用户无论如何都不会阅读错误消息.它们越短,他们就越有可能至少浏览一下文本.
或者,凭借用户不会阅读错误消息的知识,您可以采用不同的方式.完全跳过确认消息,只提供Just Works的撤消功能,无论删除了什么.大多数用户已经习惯于在他们发现不是他们想要的操作时撤消操作,并且很可能发现这种行为比处理另一个恼人的弹出窗口更自然.
Ber*_*sch 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.
Run Code Online (Sandbox Code Playgroud)
在你的情况下,你想要一些更简单的东西:
MessageFormat form = new MessageFormat("Are you sure you want to delete {0,choice,1#one item,1<{0,number.integer} files}?");
Run Code Online (Sandbox Code Playgroud)
这种方法的优点是它可以很好地与i18n包一起使用,并且您可以为没有复数或单数词概念的语言(如日语)提供正确的翻译.
Jen*_*ens 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?";
Run Code Online (Sandbox Code Playgroud)
然后将它们送入String.Format之类
if(noofitemsselected == 1)
messageTemplate = MessageResources.DELETE_SINGLE;
else
messageTemplate = MessageResources.DELETE_MULTI;
string message = String.Format(messageTemplate, noofitemsselected)
Run Code Online (Sandbox Code Playgroud)
我认为这种方法更容易本地化和维护.所有UI消息都位于单个位置.
gde*_*ohn 11
您可以通过不同地表达消息来完全回避问题.
string message = "The number of selected items is " + noofitemsselected + ". Are you sure you want to delete everything in this selection?";
Run Code Online (Sandbox Code Playgroud)
Dan*_*zey 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);
Run Code Online (Sandbox Code Playgroud)
此外,在WPF应用程序中,我见过系统,其中资源字符串将被管道分隔以具有两个消息:单个和多个消息(或者甚至是零/单个/多个消息).然后可以使用自定义转换器来解析此资源并使用相关的(格式化的)字符串,因此您的Xaml是这样的:
<TextBlock Text="{Binding numOfItems, Converter={StaticResource c:NumericMessageFormatter}, ConverterParameter={StaticResource s:SuitableMessageTemplate}}" />
Run Code Online (Sandbox Code Playgroud)
对于英语,上面有很多答案.对于其他语言来说,它更加困难,因为复数取决于名词的性别和结尾这个词.法语中的一些例子:
经常男性化:
Vous avez choisi 1 compte. Voulez-vous vraiment le supprimer.
Vous avez choisi 2 comptes. Voulez-vous vraiment les supprimer.
Run Code Online (Sandbox Code Playgroud)
经常女人味
Vous avez choisi 1 table. Voulez-vous vraiment la supprimer.
Vous avez choisi 2 tables. Voulez-vous vraiment les supprimer.
Run Code Online (Sandbox Code Playgroud)
不规则的男性化(用's'完成)
Vous avez choisi 1 pays. Voulez-vous vraiment le supprimer.
Vous avez choisi 2 pays. Voulez-vous vraiment les supprimer?
Run Code Online (Sandbox Code Playgroud)
在大多数拉丁语言中存在同样的问题,并且在德语或俄语中变得更糟,其中有3种性别(maculine,女性和中性).
如果你的目标是处理的不仅仅是英语,你需要小心.
为了能够有多个可以正确本地化的消息,我的观点是,首先在数字和消息之间创建一个间接层是明智的.
例如,使用某种常量来指定要显示的消息.使用一些隐藏实现细节的函数来获取消息.
get_message(DELETE_WARNING, quantity)
Run Code Online (Sandbox Code Playgroud)
接下来,创建一个包含可能的消息和变体的字典,并使变体知道何时应该使用它们.
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?'
}
Run Code Online (Sandbox Code Playgroud)
现在您可以简单地找到与该消息对应的键quantity并插入该quantity消息的值.
这个过于简单和天真的例子,但我真的没有看到任何其他理智的方式,并能够为L10N和I18N提供良好的支持.
您必须将以下函数从VBA转换为C#,但您的使用将更改为:
int noofitemsselected = SomeFunction();
string message = Pluralize("You have selected # item[s]. Are you sure you want to delete [it/them]?", noofitemsselected);
Run Code Online (Sandbox Code Playgroud)
我有一个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
Run Code Online (Sandbox Code Playgroud)
在上面的代码注释中,使用情况有所减少,所以我将在此处重复:
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."
Run Code Online (Sandbox Code Playgroud)
是的,此解决方案忽略了非英语语言.这是否重要取决于您的要求.
| 归档时间: |
|
| 查看次数: |
4770 次 |
| 最近记录: |