Pluralità nei messaggi degli utenti


106

Molte volte, quando si generano i messaggi di mostrare all'utente, il messaggio conterrà una serie di qualcosa che voglio informare il cliente circa.

Faccio un esempio: il cliente ha selezionato un numero di articoli da 1 in su e ha fatto clic su Elimina. Ora voglio dare un messaggio di conferma al cliente e voglio menzionare il numero di articoli che ha selezionato per ridurre al minimo la possibilità che commetta un errore selezionando un gruppo di articoli e facendo clic su Elimina quando vuole eliminare solo uno di loro.

Un modo è rendere il messaggio generico in questo modo:

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

Il "problema" qui è il caso in cui noofitemselectedè 1, e dobbiamo scrivere item and it invece di items e loro .

La mia soluzione normale sarà qualcosa del genere

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

Questo diventa piuttosto lungo e piuttosto sgradevole molto velocemente se ci sono molti riferimenti alla pluralità dei numeri all'interno del codice e il messaggio effettivo diventa difficile da leggere.

Quindi le mie domande sono semplici. Esistono modi migliori per generare messaggi come questo?

MODIFICARE

Vedo che molte persone si sono bloccate nel caso in cui ho menzionato che il messaggio dovrebbe essere visualizzato all'interno di una finestra di messaggio e ha semplicemente dato una risposta su come evitare del tutto di utilizzare la finestra di messaggio, e va bene .

Ma ricorda che il problema della pluralizzazione si applica anche ai testi in altri punti del programma oltre alle finestre di messaggio. Ad esempio, un'etichetta accanto a una griglia che mostra il numero di righe selezionate nella griglia avrà lo stesso problema per quanto riguarda la pluralizzazione.

Quindi questo fondamentalmente si applica alla maggior parte del testo che viene emesso in qualche modo dai programmi, e quindi la soluzione non è così semplice come cambiare semplicemente il programma per non emettere più testo :)


6
@ 0xA3: Non so davvero se ogni lingua ha una pluralizzazione che può essere facilmente espressa come "item (s)".
Jens

5
Probabilmente dovresti pensare anche alla localizzazione. Questo problema può peggiorare molto.
Alex Brown

4
@ Jens: di solito non lo fanno, nei modi meno convenienti possibile. Alcune lingue, ad esempio, hanno pluralizzazioni diverse per 2-4 rispetto a 5-infinito, tutto ciò a seconda del sesso. "Natural Languages: Localization Madness! Prossimamente su un computer vicino a te!"
Piskvor ha lasciato l'edificio il

29
IMO, niente fa sembrare i programmatori più pigri per gli utenti della cattiva pluralità.
Greg

4
@ Øyvind: +1 per la tua modifica. Sembra che molti dei "rispondenti" qui siano più intenzionati a dimostrare che la tua domanda è sbagliata, piuttosto che offrire una soluzione giusta. Anti-soluzioni, se vuoi.
mwolfe02

Risposte:


53

Se c'è qualche possibilità, non importa quanto piccola, che questa app debba essere tradotta in altre lingue, allora entrambi si sbagliano. Il modo corretto per farlo è:

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

Questo perché lingue diverse gestiscono la pluralità in modo diverso. Alcuni come il malese non hanno nemmeno i plurali sintattici, quindi le corde sarebbero generalmente identiche. La separazione delle due stringhe rende più facile supportare altre lingue in seguito.

Altrimenti, se questa app è pensata per essere utilizzata dal grande pubblico e si suppone che sia facile da usare, è preferibile il secondo metodo. Mi dispiace ma non conosco un modo più breve per farlo.

Se questa app è pensata per essere utilizzata solo internamente dalla tua azienda, fai la scorciatoia "item(s)". Non devi davvero impressionare nessuno quando scrivi un codice aziendale. Ma sconsiglio di farlo per le app pubblicamente consumate perché questo dà l'impressione che il programmatore sia pigro e quindi abbassi la sua opinione sulla qualità dell'app. Credimi, piccole cose come questa contano.


35
Pur essendo d'accordo con la premessa, stai ignorando le lingue che hanno più di due gradi di pluralità. (Prendi il russo per esempio. Tre modi diversi di dire a seconda che sia 1, <5, o> = 5 e anche questo dipende da cosa stai parlando esattamente). Fondamentalmente sto dicendo che hai bisogno di una dichiarazione condizionale più forte e non solo di un operatore ternario.
crasic

4
Puoi anche ottimizzare noofitemsselectedin questo esempio per la prima opzione; dato che sai che è 1.
Predefinito

16
Già che ci siamo, l'ebraico può avere pluralità diverse per 1, 2, 3-10 e 11+.
Joel Spolsky

3
@ Joel, l'ebraico può avere così tante pluralità diverse? לא ידעתי (non lo sapevo)! L'ebraico moderno è come l'inglese per quanto riguarda i plurali (sebbene anche l'ebraico antico avesse una doppia forma).
Ken Bloom,

3
In inglese, lo zero viene trattato come un plurale (0 elementi, 2 elementi); cosa succede con zero in ebraico, russo, rumeno? C'è un modo semplice per identificare gli intervalli? Immagino che le informazioni debbano essere determinate in base alla lingua, quindi qualsiasi sistema basato su file di messaggi deve gestire quantità variabili di pluralità in un insieme di messaggi. Ahia! Anche l'impostazione delle traduzioni sarebbe complicata: sono necessari diversi numeri di messaggi per lingue diverse.
Jonathan Leffler

94

Puoi evitare tutta questa disordinata pluralità semplicemente eliminando gli elementi senza alcun messaggio e offrendo all'utente un ottimo strumento di annullamento. Gli utenti non leggono mai nulla . Dovresti comunque creare una buona funzione di annullamento come parte del tuo programma.

In realtà ottieni 2 vantaggi quando crei una struttura completa di annullamento. Il primo vantaggio semplifica la vita dell'utente consentendogli di invertire gli errori e ridurre al minimo la lettura. Il secondo vantaggio è che la tua app riflette la vita reale consentendo l'inversione del flusso di lavoro non banale (non solo errori).

Una volta ho scritto un'app senza utilizzare una sola finestra di dialogo o un messaggio di conferma. Ci sono voluti alcuni pensieri seri ed è stato significativamente più difficile da implementare rispetto all'utilizzo di messaggi di conferma. Ma il risultato finale è stato piuttosto piacevole da usare secondo i suoi utenti finali.


12
Per qualche ragione, mi sento davvero d'accordo con questo e dovrei votarlo positivamente.
Cody Grey

4
@ Øyvind, Ecco perché: i messaggi che chiedono all'utente la verifica sono costosi per l'utente, specialmente quando vengono presentati sotto forma di una finestra di dialogo modale che interrompe tutto finché l'utente non risponde alla finestra di dialogo. Ciò infastidisce molti utenti, al punto che iniziano a fare clic su qualsiasi pulsante per superare la finestra di dialogo (quanti programmi di installazione hai appena cliccato dopo, dopo, dopo? ). Di conseguenza, è più sicuro e c'è molto meno attrito da parte dell'utente, se si esegue solo un'eliminazione soft e si fornisce una capacità di annullamento. Gmail utilizza questa tecnica con ottimi risultati.
Robert Harvey,

5
Discutibile, ma in ogni caso lo stesso problema si presenterà in casi diversi da un messaggio di conferma su una cancellazione, quindi questa risposta è davvero tangenziale alla domanda.
Jay

50
ho votato positivamente senza leggerlo. posso sempre annullarlo più tardi
Steven A. Lowe

6
@Robert Harvey: Probabilmente apocrifo, ma molti anni fa ho letto che Lotus aveva spedito 40.000 unità di Lotus Notes per Mac e 60.000 sono state restituite. L'interfaccia era così pessima che persino le persone che l'avevano piratata l'hanno rimandata indietro.
Duncan

39

Che ne dici di:

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

In questo modo, elimini le difficoltà di accordo sul numero e ti ritroverai con un messaggio di errore ancora più breve e preciso per l'utente come bonus. Sappiamo tutti che gli utenti non leggono comunque i messaggi di errore . Più sono brevi, più è probabile che guardino almeno il testo.

Oppure, armati di questa consapevolezza che gli utenti non leggono i messaggi di errore, potresti avvicinarti a questo in un modo diverso. Salta del tutto il messaggio di conferma e fornisci solo una funzione di annullamento che funziona correttamente, indipendentemente da ciò che è stato eliminato. La maggior parte degli utenti è già abituata ad annullare un'operazione quando si accorge che non era ciò che desiderava e probabilmente troverà questo comportamento più naturale rispetto a dover affrontare un altro fastidioso pop-up.


1
Buona risposta. Tuttavia, in questo caso è stato richiesto dal cliente di fornire messaggi di errore per molti molti casi perché riteneva che fosse l'approccio migliore. Ma cambiare il testo può almeno minimizzare il problema e renderlo meno disordinato.
Øyvind Bråthen

@ Øyvind: abbastanza giusto. Dato che devi seguire il cliente, adotterò il primo approccio che ho proposto o utilizzerei un file di risorse con una funzione di gestione. Ho solo pensato che valesse la pena indicare un'alternativa perché è così facile da dimenticare. Diamine, non ci ho nemmeno pensato fino a dopo aver inviato la mia prima risposta.
Cody Grey

Le alternative sono le benvenute. Ecco perché ho dato anche un +1 :)
Øyvind Bråthen

1
+1 per non aver tentato di risolvere un problema irrisolvibile. E ricorda la legge di Steve Krug: rimuovi metà delle parole. Quindi fallo di nuovo. Uso: "Eliminare {x} articolo / i?"
Serge Wautier

20

Che dire di ciò che Java ha avuto per anni: java.text.MessageFormat e ChoiceFormat? Vedere http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html per ulteriori informazioni.

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.

Nel tuo caso vuoi qualcosa di un po 'più semplice:

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

Il vantaggio di questo approccio è che funziona bene con i pacchetti i18n e puoi fornire traduzioni adeguate per lingue (come il giapponese) che non hanno il concetto di parole plurali o singolari.


1
Questo approccio funziona bene per gestire la pluralità, ma purtroppo non gestisce il genere. Hai bisogno di una stringa diversa per ogni tipo di cosa che può essere cancellata.
Mr. Shiny and New 安 宇

Se conosci il nome, puoi modellare le frasi in modo che funzionino con l'aggettivo appropriato. Ma sì, avendo studiato il greco classico, hai una forma diversa della parola basata su sostantivi maschili, femminili o neutri (l'aggettivo assume la forma del sostantivo che modifica), e la forma differisce in base alla sua funzione nella frase ( soggetto, oggetto, ecc.). Possiamo sempre trovare casi in cui una soluzione funziona e un'altra no. Questo è il modo in cui la gente di Java ha tentato di risolvere il problema. Devi ancora fare attenzione al modo in cui formi i formati dei messaggi.
Berin Loritsch

Puoi sempre alimentare la soluzione Java con due numeri interi, dove il secondo indica il sesso. (Ma in realtà, l'accordo di genere di solito è meno preoccupante semplicemente perché il caso d'uso di inserire oggetti diversi in un messaggio è meno frequente che inserire numeri diversi dello stesso oggetto in un messaggio)
Ken Bloom

12

Vorrei non codificare il messaggio, ma fornire due messaggi in un file di risorse separato. Piace

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

e quindi inserirli in String.Format come

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

string message = String.Format(messageTemplate, noofitemsselected)

Penso che questo approccio sia più facile da localizzare e mantenere. Tutti i messaggi dell'interfaccia utente sarebbero in un'unica posizione.


+1, mi piace questo approccio. Tuttavia, dovresti tenere traccia degli equivalenti del nome della risorsa.
Predefinito

11

Puoi eludere completamente il problema formulando il messaggio in modo diverso.

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

10

La prima cosa che suggerirei è: usa string.Format. Ciò ti consente di fare qualcosa del genere:

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

Inoltre, nelle app WPF, ho visto sistemi in cui una stringa di risorse sarebbe delimitata da pipe per avere due messaggi: un messaggio singolare e un messaggio plurale (o un messaggio zero / singolo / molti, anche). Un convertitore personalizzato potrebbe quindi essere utilizzato per analizzare questa risorsa e utilizzare la stringa (formattata) pertinente, quindi il tuo Xaml è qualcosa del genere:

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

7

Per l'inglese, molte risposte sopra. Per altre lingue è più difficile, poiché i plurali dipendono dal genere del sostantivo e dalla fine della parola. Alcuni esempi in francese:

Maschile regolare:

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

Femminile regolare

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

Maschile irregolare (finisce con 's')

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

Lo stesso problema esiste nella maggior parte delle lingue latine e peggiora in tedesco o russo, dove ci sono 3 generi (maculine, femminile e neutro).

Dovrai fare attenzione se il tuo obiettivo è gestire qualcosa di più dell'inglese.


Almeno nel mio caso, questo non è davvero un problema. Per ogni testo che voglio inserire il numero, saprò qual è il nome durante la generazione della stringa. Ma per fare una soluzione più generale sono d'accordo con te, che farlo funzionare per "tutte" le lingue potrebbe essere un compito molto difficile, se non impossibile.
Øyvind Bråthen

1
Oppure prendi il polacco, dove la forma plurale del nome usato è diversa a seconda del numero! : /
UpTheCreek

5

Per poter avere messaggi pluralizzati che sarà possibile localizzare correttamente, la mia opinione è che sarebbe saggio creare prima uno strato di riferimento indiretto tra il numero e un messaggio.

Ad esempio, utilizzare una costante di qualche tipo per specificare quale messaggio si desidera visualizzare. Recupera il messaggio utilizzando una funzione che nasconda i dettagli di implementazione.

get_message(DELETE_WARNING, quantity)

Successivamente, crea un dizionario che contenga i possibili messaggi e variazioni e fai in modo che le variazioni sappiano quando dovrebbero essere utilizzate.

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

Ora potresti semplicemente trovare la chiave che corrisponde a quantitye interpolare il valore di quantitycon quel messaggio.

Questo esempio semplicistico e ingenuo, ma non vedo nessun altro modo sensato per farlo ed essere in grado di fornire un buon supporto per L10N e I18N.


5

Dovrai tradurre la funzione di seguito da VBA a C #, ma il tuo utilizzo cambierebbe in:

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

Ho una funzione VBA che utilizzo in MS Access per fare esattamente ciò di cui stai parlando. So che verrò fatto a pezzi per aver pubblicato VBA, ma qui va comunque. L'algoritmo dovrebbe essere evidente dai commenti:

'---------------------------------------------------------------------------------------'
' 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'utilizzo è stato leggermente interrotto nei commenti sul codice sopra, quindi lo ripeterò qui:

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

Sì, questa soluzione ignora le lingue che non sono l'inglese. Se questo è importante dipende dalle tue esigenze.


4

Potresti generare il plurale automaticamente, vedi ad es. generatore plurale .

Per le regole di generazione plurale vedere wikipedia

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

Mi piace usare questo metodo se l'applicazione non è internazionalizzata. La purificazione si traduce in un'applicazione più lucida.
cspolton

1
È davvero difficile internazionalizzarlo e spesso fallisce in inglese, ad esempio "You have orders + numMice + GetPlural (" mouse ", numMice)"
James Anderson

@ James Anderson: Ora, questo non è il miglior esempio grammaticale, è vero ;-) Non cadere nella trappola di pensare che l'uso di un metodo GetPural sia l' unico metodo che puoi usare.
cspolton

insieme ad alcune funzioni in più per gestire altri casi d'angolo, penso che questa sia un'ottima soluzione, anche se non più breve.
lalli

4

Che ne dici di un modo più generico. Evita la pluralizzazione nella seconda frase:

Numero di elementi selezionati da eliminare: noofitemsselected.
Sei sicuro?

Ho scoperto che in questo modo si mette il numero alla fine della riga che è davvero facile da individuare. Questa soluzione funzionerebbe con la stessa logica in qualsiasi lingua.


"Elementi selezionati da eliminare:" non suona bene, la frase indica un elenco di nomi, ma viene stampato un numero. Anche se modificato in "Numero di elementi da eliminare:", ancora "elementi" è scomodo.
lalli

@lalli: Sì, la formulazione non è perfetta e nessuna delle soluzioni fornite sembra perfetta. Sto solo suggerendo di metterlo in una forma come etichetta e valore. Hai ragione sull'aggiunta Number(stavo rispondendo mentre cullavo il mio bambino per addormentarlo).
Danosaure

4

Il mio approccio generale è scrivere una "funzione singola / plurale", come questa:

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

Quindi nel corpo del messaggio chiamo questa funzione:

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

Questo non è molto meglio, ma almeno, (a) mette la decisione in una funzione e quindi sgombra un po 'il codice, e (b) è abbastanza flessibile da gestire plurali irregolari. cioè è abbastanza facile dire nome (n, "bambino", "bambini") e simili.

Ovviamente funziona solo per l'inglese, ma il concetto è facilmente estendibile a lingue con finali più complessi.

Mi viene in mente che potresti rendere facoltativo l'ultimo parametro per il caso 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
Mi piace la tua ultima parte in cui usi un valore predefinito per "riordinare" il codice in caso dell'operazione predefinita di aggiunta di una s per pluralizzare il nome.
Øyvind Bråthen

4

Internazionalizzazione

Presumo che tu voglia il supporto per l'internazionalizzazione, nel qual caso lingue diverse hanno modelli diversi per i plurali (ad esempio una forma plurale speciale per 2 di qualcosa, o lingue più complicate come il polacco), e non puoi fare affidamento sull'applicazione di qualche semplice modello alla tua stringa per risolverlo.

Puoi usare la ngettextfunzione GNU Gettext e fornire due messaggi in inglese nel tuo codice sorgente. Gettext fornirà l'infrastruttura per scegliere tra altri (potenzialmente più) messaggi quando tradotti in altre lingue. Vedere http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html per una descrizione completa del supporto plurale di GNU gettext.

GNU Gettext è sotto LGPL. ngettextè denominato GettextResourceManager.GetPluralStringnel port C # di Gettext.

(Se non hai bisogno del supporto per la localizzazione e non vuoi usare subito Gettext, scrivi la tua funzione che lo faccia per l'inglese e passaci due messaggi completi , in questo modo se hai bisogno di l10n più tardi, puoi aggiungere riscrivendo una singola funzione.)


3

Che ne dici di scrivere la funzione come

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

.. e usarlo ogni volta che ne hai bisogno?

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

3
non ci hai pensato lol, hai una funzione per risolvere i moltiplicatori o meno per la frase quindi vai a mettere "it / them" alla fine lol
Barkermn01

Dovresti solo passare due messaggi per l'intera frase a questa funzione.
Ken Bloom

Era solo un esempio. Mi rendo conto che la variante per inviare frasi intere è più corretta.
Pavel Morshenyuk

3

Per il primo problema, intendo Pluralize, puoi usare Inflector .

E per il secondo, puoi usare un'estensione di rappresentazione di stringa con un nome come ToPronounString.


3

Ieri mi è stata posta la stessa identica domanda da un membro del nostro team.

Da quando è uscito di nuovo qui su StackOverflow, ho pensato che l'universo mi stesse dicendo di fare un salto nel produrre una soluzione decente.

Ho messo insieme rapidamente qualcosa e non è affatto perfetto, tuttavia potrebbe essere utile o innescare qualche discussione / sviluppo.

Questo codice si basa sull'idea che possono esserci 3 messaggi. Uno per zero articoli, uno per un articolo e uno per più di un articolo che seguono la seguente struttura:

singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural

Ho creato una classe interna con cui testare per imitare la classe di risorse. Non l'ho ancora testato utilizzando un file di risorse effettivo, quindi devo ancora vedere il risultato completo.

Ecco il codice (attualmente ho incluso alcuni generici in cui so che avrei potuto specificare il terzo parametro semplicemente come Tipo e anche il secondo parametro è una stringa, penso che ci sia un modo per combinare questi due parametri in qualcosa di meglio, ma io ' Tornerò su questo quando avrò un momento libero.

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

e il mio metodo di esecuzione rapida

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

Se vuoi che questo sia davvero completo, dovresti anche aggiungere un messaggio per singlePropertyName_Allrenderlo ancora più ovvio.
Danosaure

2

Dal mio punto di vista, la tua prima soluzione è quella più adatta. Perché dico questo è, nel caso in cui sia necessario che l'applicazione supporti più lingue, la seconda opzione può essere meticolosa. Con l'approccio pugno è facile localizzare il testo senza troppi sforzi.


2

Potresti usare un messaggio più generico come "Sei sicuro di voler eliminare gli elementi selezionati".


3
Questo certamente funziona, ma penso che l'idea del richiedente di mostrare il numero di elementi che stanno per essere cancellati a colpo d'occhio sia buona. Più di una volta ho provato a eliminare un file dal desktop e ho cancellato accidentalmente più di quel file.
Cody Grey

2

Dipende da quanto bel messaggio vuoi avere. Dal più semplice al più difficile:

  1. Riscrivi il tuo messaggio di errore per evitare il pluralismo. Non così piacevole per il tuo utente, ma più veloce.

  2. Usa un linguaggio più generale ma includi comunque i numeri.

  3. Usa un sistema di "pluralizzazione" e inflector come Rails, in modo da poter dire pluralize(5,'bunch')e ottenere 5 bunches. Rails ha un buon modello per questo.

  4. Per l'internazionalizzazione, è necessario esaminare ciò che fornisce Java. Ciò supporterà un'ampia varietà di lingue, comprese quelle che hanno diverse forme di aggettivi con 2 o 3 elementi. La soluzione "s" è molto incentrata sull'inglese.

L'opzione scelta dipende dagli obiettivi del prodotto. - ndp


2

Perché dovresti presentare un messaggio che gli utenti possano effettivamente capire? Va contro 40 anni di storia della programmazione. Nooooo, abbiamo una buona cosa in corso, non rovinarla con messaggi comprensibili .


(J / k)


+1: bello vedere un po 'di umorismo anche qui dentro. Ma anche se stai scherzando, capisco il tuo punto di fondo. Molti molti programmi creati nel corso degli anni hanno messaggi estremamente negativi. Di solito perché diventano tecnici per essere capiti comunque da un utente normale.
Øyvind Bråthen

Buon punto. Mi piace sempre quando ricevo un messaggio come "Errore 494-B sull'input dell'utente" - aggiunge quel piccolo mistero in più su cosa c'è che non va che rende la vita molto più interessante. Recentemente ho ricevuto un errore durante il tentativo di creare una password che diceva semplicemente "La password non soddisfa i requisiti di sicurezza". Nessun indizio su quale requisito non stavo soddisfacendo. La mia password includeva lettere maiuscole e minuscole e diverse cifre. Ho provato ad aggiungere un carattere seciale. Ancora no. Alla fine è passato quando ho ELIMINATO un personaggio. Penso che avessero una regola secondo cui non puoi avere lo stesso personaggio due volte di seguito.
Jay

2

Fallo come si fa in World of Warcraft:

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

0

Diventa un po 'più corto con

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

0

Un approccio che non ho visto menzionato sarebbe l'uso di un tag di sostituzione / selezione (ad esempio qualcosa come "Stai per schiacciare {0} [? I ({0} = 1): / cactus / cacti /]". (in altre parole, fai in modo che un'espressione simile al formato specifichi la sostituzione in base al fatto che l'argomento zero, preso come intero, sia uguale a 1). Ho visto tali tag utilizzati nei giorni precedenti .net; non ne sono a conoscenza standard per loro in .net, né conosco il modo migliore per formattarli.


0

Penserei fuori dagli schemi per un minuto, tutti i suggerimenti qui sono o fare la pluralizzazione (e preoccuparsi di più di 1 livello di pluralizzazione, genere, ecc.) O non usarlo affatto e fornire un bel annullamento.

Vorrei seguire il modo non linguale e utilizzare le code visive per questo. ad esempio, immagina un'app per Iphone in cui selezioni gli elementi pulendo il dito. prima di eliminarli utilizzando il pulsante di eliminazione principale, "agiterà" gli elementi selezionati e mostrerà una casella con un punto interrogativo con i pulsanti V (ok) o X (annulla) ...

Oppure, nel mondo 3D di Kinekt / Move / Wii: immagina di selezionare i file, spostare la mano sul pulsante Elimina e sentirti dire di spostare la mano sopra la testa per confermare (usando gli stessi simboli visivi che ho menzionato prima. Ad esempio invece di chiederti di eliminare 3 file? ti mostrerà 3 file con una X rossa semitrasparente e ti dirà di fare qualcosa per confermare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.