Pluralité dans les messages des utilisateurs


106

Plusieurs fois, lors de la génération de messages à montrer à l'utilisateur, le message contiendra un certain nombre de choses que je souhaite informer le client.

Je vais donner un exemple: le client a sélectionné un certain nombre d'articles de 1 et plus, et a cliqué sur supprimer. Maintenant, je veux donner un message de confirmation au client, et je veux mentionner le nombre d'articles qu'il a sélectionnés pour minimiser le risque qu'il fasse une erreur en sélectionnant un groupe d'articles et en cliquant sur supprimer lorsqu'il ne veut supprimer qu'un des leur.

Une façon est de rendre le message générique comme ceci:

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

Le "problème" ici est le cas où noofitemselectedest 1, et nous devons écrire item et it à la place des items et eux .

Ma solution normale sera quelque chose comme ça

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

Cela devient assez long et assez désagréable très rapidement s'il y a beaucoup de références à la pluralité de nombres dans le code et que le message réel devient difficile à lire.

Mes questions sont donc simples. Existe-t-il de meilleures façons de générer des messages comme celui-ci?

ÉDITER

Je vois que beaucoup de personnes ont été très accrochées dans le cas où j'ai mentionné que le message devrait être affiché dans une boîte de message, et a simplement donné une réponse sur la façon d'éviter d'utiliser la boîte de message du tout, et c'est très bien .

Mais rappelez-vous que le problème de la pluralisation s'applique également aux textes à d'autres endroits du programme en plus des boîtes de message. Par exemple, une étiquette à côté d'une grille affichant le nombre de lignes sélectionnées dans la grille aura le même problème de pluralisation.

Donc, cela s'applique fondamentalement à la plupart du texte qui est produit d'une manière ou d'une autre à partir de programmes, et la solution n'est pas aussi simple que de simplement changer le programme pour ne plus afficher de texte :)


6
@ 0xA3: Je ne sais pas vraiment si chaque langue a une pluralisation qui s'exprime aussi facilement que "item (s)".
Jens

5
Vous devriez probablement aussi penser à la localisation. Ce problème peut être bien pire.
Alex Brown

4
@Jens: Ils ne le font généralement pas, de la manière la moins pratique possible. Certaines langues ont par exemple des pluralisations différentes pour 2-4 et pour 5-infini, tout cela en fonction du sexe. "Langages naturels: folie de localisation! Bientôt sur un ordinateur près de chez vous!"
Piskvor a quitté le bâtiment

29
OMI, rien ne rend les programmeurs plus paresseux aux yeux des utilisateurs qu'une mauvaise pluralité.
Greg

4
@ Øyvind: +1 pour votre édition. Il semble que bon nombre des «répondants» ici sont plus déterminés à prouver que votre question est fausse, plutôt qu'à offrir une solution qui est juste. Anti-solutions, si vous voulez.
mwolfe02

Réponses:


53

S'il y a une chance, aussi petite soit-elle, que cette application doive être traduite dans d'autres langues, les deux sont fausses. La bonne façon de procéder est:

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

En effet, différentes langues gèrent la pluralité différemment. Certains comme le malais n'ont même pas de pluriel syntaxique, donc les chaînes seraient généralement identiques. La séparation des deux chaînes facilite la prise en charge ultérieure d'autres langues.

Sinon, si cette application est destinée à être utilisée par le grand public et qu'elle est censée être conviviale, la deuxième méthode est préférable. Désolé mais je ne connais pas vraiment une manière plus courte de faire cela.

Si cette application est destinée à être utilisée uniquement en interne par votre entreprise, faites le raccourci "item(s)". Vous n'avez pas vraiment besoin d'impressionner qui que ce soit lorsque vous écrivez un code d'entreprise. Mais je déconseille de faire cela pour une application consommée publiquement, car cela donne l'impression que le programmeur est paresseux et diminue ainsi son opinion sur la qualité de l'application. Croyez-moi, de petites choses comme ça comptent.


35
Bien que je sois d'accord avec la prémisse, vous ignorez les langues qui ont plus de deux degrés de pluralité. (Prenons le russe par exemple. Trois manières différentes de dire selon que c'est 1, <5 ou> = 5 et même cela dépend de ce dont vous parlez exactement). Fondamentalement, je dis que vous avez besoin d'une instruction conditionnelle plus forte et pas seulement d'un opérateur ternaire.
crasic

4
Vous pouvez même optimiser le noofitemsselecteddans cet exemple pour la première option; puisque vous savez qu'il est 1.
Par défaut

16
Tant que nous y sommes, l'hébreu peut avoir différentes pluralités pour 1, 2, 3-10 et 11+.
Joel Spolsky

3
@Joel, l'hébreu peut avoir autant de pluralités différentes? לא ידעתי (je ne savais pas)! L'hébreu moderne est comme l'anglais en ce qui concerne les pluriels (bien que l' hébreu ancien ait également une forme double.)
Ken Bloom

3
En anglais, zéro est traité comme un pluriel (0 élément, 2 éléments); que se passe-t-il avec zéro en hébreu, russe, roumain? Existe-t-il un moyen simple d'identifier les plages? Je suppose que les informations doivent être déterminées par langue, donc tout système basé sur des fichiers de messages doit faire face à des quantités variables de pluralité dans un ensemble de messages. Aie! La configuration des traductions serait également délicate - différents nombres de messages sont nécessaires pour différentes langues.
Jonathan Leffler

94

Vous pouvez éviter toute cette pluralité désordonnée en supprimant simplement les éléments sans aucun message et en donnant à l'utilisateur une très bonne fonction d'annulation. Les utilisateurs ne lisent jamais rien . Vous devriez quand même créer une bonne fonction d'annulation dans le cadre de votre programme.

Vous obtenez en fait 2 avantages lorsque vous créez une fonction d'annulation complète. Le premier avantage facilite la vie de l'utilisateur en lui permettant d'inverser les erreurs et de minimiser la lecture. Le deuxième avantage est que votre application reflète la vie réelle en permettant l'inversion d'un flux de travail non trivial (pas seulement des erreurs).

Une fois, j'ai écrit une application sans utiliser une seule boîte de dialogue ou un seul message de confirmation. Il a fallu une réflexion sérieuse et était beaucoup plus difficile à mettre en œuvre que l'utilisation de messages de type confirmation. Mais le résultat final était plutôt agréable à utiliser selon ses utilisateurs finaux.


12
Pour une raison quelconque, je sens vraiment que je suis d'accord avec cela et que je devrais voter pour.
Cody Gray

4
@ Øyvind, Voici pourquoi: Les messages demandant une vérification à l'utilisateur sont chers à l'utilisateur, surtout lorsqu'ils se présentent sous la forme d'une boîte de dialogue modale qui arrête tout jusqu'à ce que l'utilisateur réponde à la boîte de dialogue. Cela agace de nombreux utilisateurs, au point où ils commencent simplement à cliquer sur n'importe quel bouton pour passer la boîte de dialogue (combien d'installateurs avez-vous juste cliqué sur suivant, suivant, suivant? ). Par conséquent, il est plus sûr, et il y a beaucoup moins de friction avec l'utilisateur, si vous ne faites qu'une suppression logicielle et fournissez une capacité d'annulation. Gmail utilise cette technique à bon escient.
Robert Harvey

5
Débattable, mais dans tous les cas, le même problème se posera dans les cas autres qu'un message de confirmation lors d'une suppression, donc cette réponse est vraiment tangentielle à la question.
Jay

50
J'ai voté pour cela sans le lire. Je peux toujours l'annuler plus tard
Steven A. Lowe

6
@Robert Harvey: Probablement apocryphe, mais il y a de nombreuses années, j'ai lu que Lotus avait expédié 40 000 unités de Lotus Notes pour Mac et 60 000 avaient été renvoyées. L'interface était si mauvaise que même les personnes qui l'avaient piratée l'ont renvoyée.
Duncan

39

Que diriez-vous simplement:

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

De cette façon, vous éliminez les difficultés d'accord de nombre et vous vous retrouvez avec un message d'erreur encore plus court et plus précis pour l'utilisateur en prime. Nous savons tous que les utilisateurs ne lisent pas les messages d'erreur de toute façon . Plus ils sont courts, plus ils sont susceptibles de jeter au moins un coup d'œil sur le texte.

Ou, armé de cette connaissance que les utilisateurs ne lisent pas les messages d'erreur, vous pouvez aborder cela d'une manière différente. Ignorez complètement le message de confirmation et fournissez simplement une fonction d'annulation qui fonctionne parfaitement, indépendamment de ce qui a été supprimé. La plupart des utilisateurs sont déjà habitués à annuler une opération lorsqu'ils remarquent que ce n'était pas ce qu'ils voulaient, et trouveront probablement ce comportement plus naturel que d'avoir à gérer une autre fenêtre contextuelle ennuyeuse.


1
Bonne réponse. Cependant, le client a demandé dans ce cas de fournir des messages d'erreur dans de nombreux cas, car il estimait que c'était la meilleure approche. Mais changer le texte peut au moins minimiser le problème et le rendre moins compliqué.
Øyvind Bråthen

@ Øyvind: Très bien. Puisque vous devez suivre le client, je choisirais la première approche que j'ai proposée ou utiliserais un fichier Resources avec une fonction de gestionnaire. Je pensais juste que cela valait la peine de souligner une alternative car elle est si facile à oublier. Heck, je n'y ai même pas pensé avant d'avoir soumis ma première réponse.
Cody Gray

Les alternatives sont les bienvenues. C'est pourquoi je lui ai donné un +1 également :)
Øyvind Bråthen

1
+1 pour ne pas essayer de résoudre un problème insoluble. Et rappelez-vous la loi de Steve Krug: supprimez la moitié des mots. Puis recommencez. J'utilise: "Supprimer {x} élément (s)?"
Serge Wautier

20

Qu'en est-il de ce que Java a depuis des années: java.text.MessageFormat et ChoiceFormat? Voir http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html pour plus d'informations.

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.

Dans votre cas, vous voulez quelque chose d'un peu plus simple:

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

L'avantage de cette approche est qu'elle fonctionne bien avec les bundles i18n, et vous pouvez fournir des traductions correctement pour les langues (comme le japonais) qui n'ont pas de concept de mots au pluriel ou au singulier.


1
Cette approche fonctionne bien pour gérer la pluralité, mais ne gère malheureusement pas le genre. Vous avez besoin d'une chaîne différente pour chaque type de chose qui peut être supprimée.
Mr. Shiny and New 安 宇

Si vous connaissez le nom, vous pouvez façonner les phrases pour qu'elles fonctionnent avec l'adjectif approprié. Mais oui, après avoir étudié le grec classique, vous avez une forme différente du mot basée sur des noms masculins, féminins ou neutres (l'adjectif prend la forme du nom qu'il modifie), et la forme diffère en fonction de sa fonction dans la phrase ( sujet, objet, etc.). Nous pouvons toujours proposer des cas où une solution fonctionne et une autre non. C'est ainsi que les gens de Java ont tenté de résoudre le problème. Vous devez toujours faire attention à la façon dont vous formez les formats de message.
Berin Loritsch

Vous pouvez toujours fournir à la solution Java deux nombres entiers, le second indiquant le sexe. (Mais en réalité, l'accord de genre est généralement moins préoccupant simplement parce que le cas d'utilisation de l'ajustement de différents objets dans un message est moins fréquent que l'ajustement de différents nombres du même objet dans un message)
Ken Bloom

12

J'irais sans coder en dur le message, mais en fournissant deux messages dans un fichier de ressources séparé. Comme

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

puis les alimenter dans String.

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

string message = String.Format(messageTemplate, noofitemsselected)

Je pense que cette approche est plus facile à localiser et à maintenir. Tous les messages de l'interface utilisateur seraient à un seul endroit.


+1, j'aime cette approche. Cependant, vous devrez garder une trace des équivalents de nom de ressource.
Par défaut

11

Vous pouvez contourner le problème entièrement en formulant le message différemment.

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

10

La première chose que je suggérerais est: utiliser string.Format. Cela vous permet de faire quelque chose comme ceci:

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

De plus, dans les applications WPF, j'ai vu des systèmes dans lesquels une chaîne de ressources serait délimitée par un tube pour avoir deux messages: un message singulier et un message pluriel (ou même un message zéro / unique / plusieurs). Un convertisseur personnalisé pourrait ensuite être utilisé pour analyser cette ressource et utiliser la chaîne appropriée (formatée), donc votre Xaml est quelque chose comme ceci:

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

7

Pour l'anglais, beaucoup de réponses ci-dessus. Pour d'autres langues, c'est plus difficile, car les pluriels dépendent du sexe du nom et de la fin du mot. Quelques exemples en français:

Masculin régulier:

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

Féminin régulier

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

Masculin irrégulier (se termine par 's')

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

Le même problème existe dans la plupart des langues latines et s'aggrave en allemand ou en russe, où il y a 3 genres (maculine, féminin et neutre).

Vous devrez faire attention si votre objectif est de gérer plus que juste l'anglais.


Au moins dans mon cas, ce n'est pas vraiment un problème. Pour chaque texte que je veux insérer le nombre, je saurai quel est le nom lors de la génération de la chaîne. Mais pour faire une solution plus générale, je suis d'accord avec vous, que le faire fonctionner pour "toutes" les langues pourrait être une tâche très difficile, voire impossible.
Øyvind Bråthen

1
Ou prenez le polonais, où la forme plurielle du nom utilisé est différente selon le nombre! : /
UpTheCreek

5

Pour pouvoir disposer de messages pluralisés qu'il sera possible de localiser correctement, mon avis est qu'il serait judicieux de créer d'abord une couche d'indirection entre le numéro et un message.

Par exemple, utilisez une constante quelconque pour spécifier le message que vous souhaitez afficher. Récupérez le message en utilisant une fonction qui masquera les détails de l'implémentation.

get_message(DELETE_WARNING, quantity)

Ensuite, créez un dictionnaire qui contient les messages et les variantes possibles, et faites savoir aux variantes quand elles doivent être utilisées.

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

Maintenant, vous pouvez simplement trouver la clé qui correspond à quantityet interpoler la valeur de quantityavec ce message.

Cet exemple simpliste et naïf, mais je ne vois pas vraiment d'autre moyen sensé de le faire et de pouvoir fournir un bon support pour L10N et I18N.


5

Vous devrez traduire la fonction ci-dessous de VBA en C #, mais votre utilisation changerait en:

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

J'ai une fonction VBA que j'utilise dans MS Access pour faire exactement ce dont vous parlez. Je sais que je vais être piraté en morceaux pour avoir publié VBA, mais ici va quand même. L'algorithme doit être apparent à partir des commentaires:

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

L'utilisation a été un peu coupée dans les commentaires de code ci-dessus, je vais donc le répéter ici:

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

Oui, cette solution ignore les langues qui ne sont pas l'anglais. Que cela compte dépend de vos besoins.


4

Vous pouvez générer le pluriel automatiquement, voir par exemple. générateur pluriel .

Pour les règles de génération de pluriel, voir wikipedia

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

J'aime utiliser cette méthode si l'application n'est pas internationalisée. La purification donne une application plus soignée.
cspolton

1
C'est vraiment difficile de l'internationaliser, et cela échoue souvent en anglais, par exemple "You have orders + numMice + GetPlural (" mouse ", numMice)"
James Anderson

@James Anderson: Ce n'est pas le meilleur exemple grammaticalement ;-) Ne tombez pas dans le piège de penser que l'utilisation d'une méthode GetPural est la seule méthode que vous êtes autorisé à utiliser.
cspolton

couplé à quelques fonctions supplémentaires pour gérer quelques autres cas d'angle, je pense que c'est une très bonne solution, pas plus courte cependant.
lalli

4

Que diriez-vous d'une manière plus générique. Évitez la pluralisation dans la deuxième phrase:

Nombre d'éléments sélectionnés à supprimer: aucun élément sélectionné.
Êtes-vous sûr?

Je découvre que faire de cette façon met le nombre à la fin de la ligne qui est vraiment facile à repérer. Cette solution fonctionnerait avec la même logique dans n'importe quelle langue.


"Éléments sélectionnés à supprimer:" ne sonne pas correctement, la phrase indique une liste de noms, mais un nombre est imprimé. Même si changé en "Nombre d'éléments à supprimer:", "éléments" est toujours gênant.
lalli

@lalli: Oui, le libellé n'est pas parfait et aucune des solutions proposées ne semble parfaite. Je suggère seulement de le mettre sous une forme comme l'étiquette et la valeur. Vous avez raison d'ajouter Number(je répondais en berçant mon bébé pour qu'il s'endorme).
Danosaure

4

Mon approche générale est d'écrire une "fonction simple / plurielle", comme ceci:

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

Ensuite, dans le corps du message, j'appelle cette fonction:

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

Ce n'est pas beaucoup mieux, mais au moins ça, (a) met la décision dans une fonction et donc désencombre un peu le code, et (b) est assez flexible pour gérer les pluriels irréguliers. c'est-à-dire qu'il est assez facile de dire un nom (n, "enfant", "enfants") et autres.

Bien sûr, cela ne fonctionne que pour l'anglais, mais le concept est facilement extensible aux langues avec des terminaisons plus complexes.

Il me vient à l'esprit que vous pourriez rendre le dernier paramètre facultatif pour le cas facile:

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
J'aime votre dernière partie où vous utilisez une valeur par défaut pour "désencombrer" le code dans le cas de l'opération par défaut d'ajout d'un s pour pluraliser le nom.
Øyvind Bråthen

4

Internationalisation

Je suppose que vous voulez une prise en charge de l'internationalisation, auquel cas différentes langues ont des modèles différents pour les pluriels (par exemple une forme plurielle spéciale pour 2 de quelque chose, ou des langues plus compliquées comme le polonais), et vous ne pouvez pas compter sur l'application d'un modèle simple à votre chaîne réparer.

Vous pouvez utiliser la ngettextfonction de GNU Gettext et fournir deux messages en anglais dans votre code source. Gettext fournira l'infrastructure pour choisir parmi d'autres messages (potentiellement plus) lorsqu'ils seront traduits dans d'autres langues. Voir http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html pour une description complète du support pluriel de GNU gettext.

GNU Gettext est sous la LGPL. ngettextest nommé GettextResourceManager.GetPluralStringdans le port C # de Gettext.

(Si vous n'avez pas besoin de support de localisation et que vous ne voulez pas utiliser Gettext tout de suite, écrivez votre propre fonction qui fait cela pour l'anglais, et passez-lui deux messages complets , de cette façon si vous avez besoin de l10n plus tard, vous pouvez ajouter en réécrivant une seule fonction.)


3

Que diriez-vous d'écrire une fonction comme

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

.. et l'utiliser quand vous en avez besoin?

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

3
tu n'as pas pensé à ça t'as lol, tu as une fonction pour trier les multiplications ou pas pour la phrase puis tu vas mettre "ça / eux" à la fin lol
Barkermn01

Vous devez simplement passer deux messages pour toute la phrase à cette fonction.
Ken Bloom

C'était juste un exemple. Je me rends compte que cette variante pour envoyer des phrases entières est plus correcte.
Pavel Morshenyuk

3

Pour le premier problème, je veux dire Pluralize, vous pouvez utiliser Inflector .

Et pour le second, vous pouvez utiliser une extension de représentation sous forme de chaîne avec un nom tel que ToPronounString.


3

J'ai eu cette même question qui m'a été posée hier par un membre de notre équipe.

Depuis qu'il est revenu ici sur StackOverflow, j'ai pensé que l'univers me disait de me donner une chance de produire une solution décente.

J'ai rapidement rassemblé quelque chose et ce n'est en aucun cas parfait, mais cela pourrait être utile ou susciter une discussion / développement.

Ce code est basé sur l'idée qu'il peut y avoir 3 messages. Un pour zéro article, un pour un article et un pour plus d'un article qui suivent la structure suivante:

singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural

J'ai créé une classe interne avec laquelle tester afin d'imiter la classe de ressources. Je n'ai pas encore testé cela en utilisant un fichier de ressources réel, donc je n'ai pas encore vu le résultat complet.

Voici le code (actuellement, j'ai inclus des génériques dans lesquels je sais que j'aurais pu spécifier le troisième paramètre simplement en tant que type et le deuxième paramètre est une chaîne, je pense qu'il existe un moyen de combiner ces deux paramètres en quelque chose de mieux mais je '' J'y reviendrai quand j'aurai un moment libre.

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

Classe de ressources de test:

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

et ma méthode d'exécution rapide

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

Si vous voulez que cela soit vraiment complet, vous devez également ajouter un message pour singlePropertyName_Allle rendre encore plus évident.
Danosaure

2

De mon point de vue, votre première solution est la plus adaptée. Pourquoi je dis cela, au cas où vous auriez besoin de l'application pour prendre en charge plusieurs langues, la deuxième option peut être laborieuse. Avec la première approche, il est facile de localiser le texte sans trop d'effort.


2

Vous pouvez opter pour un message plus générique comme «Êtes-vous sûr de vouloir supprimer les éléments sélectionnés».


3
Cela fonctionne certainement, mais je pense que l'idée du demandeur de montrer le nombre d'éléments sur le point d'être supprimés en un coup d'œil est bonne. Plus d'une fois, j'ai essayé de supprimer un fichier de mon bureau et j'ai accidentellement supprimé plus d'un fichier.
Cody Gray

2

Je dépend de la gentillesse du message que vous voulez avoir. Du plus simple au plus difficile:

  1. Réécrivez votre message d'erreur pour éviter la pluralisation. Pas aussi agréable pour votre utilisateur, mais plus rapide.

  2. Utilisez un langage plus général tout en incluant le (s) nombre (s).

  3. Utilisez un système de «pluralisation» et d'inflecteurs comme Rails, pour que vous puissiez dire pluralize(5,'bunch')et obtenir 5 bunches. Les rails ont un bon modèle pour cela.

  4. Pour l'internationalisation, vous devez examiner ce que fournit Java. Cela prendra en charge une grande variété de langues, y compris celles qui ont différentes formes d'adjectifs avec 2 ou 3 éléments. La solution "s" est très centrée sur l'anglais.

L'option choisie dépend de vos objectifs de produit. - ndp


2

Pourquoi voudriez-vous présenter un message que les utilisateurs peuvent réellement comprendre? Cela va à l'encontre de 40 ans d'histoire de la programmation. Nooooo, nous avons une bonne chose en cours, ne la gâchez pas avec des messages compréhensibles .


(j / k)


+1: bon de voir un peu d'humour à l'intérieur ici aussi. Mais même si vous plaisantez, je comprends votre point sous-jacent. De nombreux programmes créés au cours des années ont des messages extrêmement mauvais. Habituellement, parce qu'ils parviennent à un niveau technique pour un utilisateur normal de toute façon.
Øyvind Bråthen

Bon point. J'adore toujours quand je reçois un message comme "Erreur 494-B sur la saisie de l'utilisateur" - cela ajoute ce petit mystère supplémentaire sur ce qui ne va pas qui rend la vie tellement plus intéressante. J'ai récemment eu une erreur en essayant de créer un mot de passe qui disait simplement «Le mot de passe ne répond pas aux exigences de sécurité». Aucune indication sur les exigences auxquelles je ne répondais pas. Mon mot de passe comprenait des lettres majuscules et minuscules et plusieurs chiffres. J'ai essayé d'ajouter un caractère sécial. Toujours pas. Il est finalement passé quand j'ai SUPPRIMÉ un personnage. Je pense qu'ils avaient une règle selon laquelle vous ne pouvez pas avoir le même personnage deux fois de suite.
Jay

2

Faites-le comme dans World of Warcraft:

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

0

Cela devient un peu plus court avec

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

0

Une approche que je n'ai pas vue mentionnée serait l'utilisation d'une balise de substitution / sélection (par exemple quelque chose comme "Vous êtes sur le point d'écraser {0} [? I ({0} = 1): / cactus / cacti /]". (en d'autres termes, une expression de format spécifie la substitution en fonction du fait que l'argument zéro, pris comme entier, est égal à 1). J'ai vu de telles balises utilisées dans les jours précédant .net; je n'en connais aucune standard pour eux en .net, et je ne connais pas la meilleure façon de les formater.


0

Je penserais hors de la boîte pendant une minute, toutes les suggestions ici sont soit faire la pluralisation (et s'inquiéter de plus d'un niveau de pluralisation, genre, etc.) ou ne pas l'utiliser du tout et fournir une belle annulation.

J'irais de la manière non linguale et utiliserais des files d'attente visuelles pour cela. Par exemple, imaginez une application Iphone que vous sélectionnez des éléments en essuyant votre doigt. avant de les supprimer à l'aide du bouton de suppression principal, il "secouera" les éléments sélectionnés et vous montrera un point d'interrogation intitulé boîte avec un bouton V (ok) ou X (annuler) ...

Ou, dans le monde 3D de Kinekt / Move / Wii - imaginez sélectionner les fichiers, déplacer votre main vers le bouton de suppression et être invité à déplacer votre main au-dessus de votre tête pour confirmer (en utilisant les mêmes symboles visuels que ceux mentionnés précédemment. de vous demander de supprimer 3 fichiers? il vous montrera 3 fichiers avec un X rouge à moitié transparent et vous dira de faire quelque chose pour confirmer.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.