Plurality in user messages

前端 未结 25 1507
没有蜡笔的小新
没有蜡笔的小新 2021-01-30 01:53

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 a

相关标签:
25条回答
  • 2021-01-30 02:48

    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.

    0 讨论(0)
  • 2021-01-30 02:48

    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.

    0 讨论(0)
  • 2021-01-30 02:48

    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();
    }
    
    0 讨论(0)
  • 2021-01-30 02:49

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

    0 讨论(0)
  • 2021-01-30 02:49

    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?";
    
    0 讨论(0)
  • 2021-01-30 02:49

    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.

    0 讨论(0)
提交回复
热议问题