2009-07-21 12 views
10

Supponiamo che tu stia creando un blog software e desideri mostrare il numero di commenti ricevuti da una voce. Si potrebbe fare in questo modo:Il modo più elegante di trattare single/plurali?

[Entry title] 
[Content........] 
[ <?php print($numComments;) ?> Comments] 

che potrebbe comportare:

[Entry title] 
[Content........] 
5 Comments 

Ma se una voce aveva solo 1 commento, voglio la linea per dire 'Commento' piuttosto che 'Commenti'. E in linea if/else s sono brutti e ripetitivi.

Qual è il modo migliore per affrontare questo?

+4

+1 Per il tuo nome utente, perché mi ha detto di farlo. È intelligente e sarei interessato a sapere quanti voti hai ottenuto solo per quello. :) – Dusty

+1

Sono mezzo tentato di downvotare solo per contrastare gli effetti delle persone che invitano lo –

risposta

13

Si prega di utilizzare la funzione ngettext per cose come questa. È che ti consente di gestire correttamente i plurali in inglese e altre lingue , una volta per tutte. Si utilizza in questo modo:

printf(ngettext("%d Comment", "%d Comments", $numComments), $numComments); 

La funzione ngettext restituirà la prima stringa di formato ("%d Comment") se v'è un solo commento e la seconda stringa di formato ("%d Comments") se ci sono più. La funzione printf sarà quindi inserire il numero nella stringa.

Questo potrebbe sembrare un sacco di lavoro, ma è molto potente: funziona con i linguaggi che hanno più di una forma plurale - hanno in realtà esistono (!). Il manuale PHP fornisce un esempio per la parola "finestra" che diventa "1 okno", "2 okna" e "5 oken" in qualche lingua esotica che non riconosco ...

Se siete conseguente sull'utilizzo ngettext, quindi i vostri futuri utenti da paesi lontani sarà molto grato a voi :-)

Edit: Come suggerito nei commenti, v'è una singola funzione al fare quanto sopra:

function pluralize($num, $singleWord, $pluralWord) { 
    return printf(ngettext($singleWord, $pluralWord, $num), $num); 
} 

per impostazione predefinita, xgettext riconoscono wont questa nuova funzione, ma si può aggiungerlo con la bandiera --keyword. Dato un file test.php con

echo ngettext("foo", "foos", 1); 
echo pluralize(2, "bar", "bars"); 

è possibile estrarre le corde con

xgettext --keyword=pluralize:2,3 test.php 

Il messages.po file risultante ha voci come queste:

#: test.php:7 
msgid "foo" 
msgid_plural "foos" 
msgstr[0] "" 
msgstr[1] "" 

#: test.php:8 
msgid "bar" 
msgid_plural "bars" 
msgstr[0] "" 
msgstr[1] "" 

Il traduttore si riempirà in ogni forma plurale e con una linea "Plural-Forms" correttamente formata nell'intestazione del catalogo messaggi, con correttamente, sarà per supportare tutte le lingue.

+0

sarebbe ripetitivo utilizzarlo con un printf tutto il tempo, ma forse è possibile scrivere una funzione wrapper che fa printf e% d. Forse potresti scrivere il corpo di questa funzione e aggiornare la tua risposta? 'function pluralize ($ num, $ singleWord, $ pluralWord = '')' –

+0

@Click Upvote: buona idea. Ho creato la funzione con tre argomenti obbligatori: la stringa plurale è necessaria in modo che xgettext possa riconoscere la chiamata alla funzione e trattarla correttamente. –

+0

Sarebbe slovacco. –

3

Creare una funzione che accetta un numero e una parola e restituisce una stringa contenente entrambi. Aggiungerà una "s" (o consulti un dizionario che costruisci) quando il numero è maggiore di 1.

+1

Farei la funzione aggiungere s se il numero non è 1, in modo che 0 ottenga anche il plurale. –

+0

Come chiameresti una funzione del genere? –

+0

Pluralize sembra il nome più adatto. – Brandon

2

Non il più elegante, ma il più semplice da mostrare "Commento/i".

[Entry title] 
[Content........] 
1 Comment(s) 
+0

Facile, ma non funziona bene in tutte le situazioni –

+2

Come si nota, questo non è molto elegante ... Quando io vedere questo risultato, mi chiedo sempre perché il computer non ha speso il millisecondo in più per capire se la "s" dovrebbe essere lì o meno :-) –

+0

+1 Haha. Concordato. – Dusty

4

perché non prendere il tempo di umanizzare le cose ancora di più ....

switch ($numComments) 
{ 
    case 0: 
     echo "Be the first to write a comment"; 
     break; 
    case 1: 
     echo "Just one comment so far"; 
     break; 
    default: 
     echo "There are $numComments comments"; 

} 
+0

+1 Questo metodo eviterà la maggior parte dei problemi di localizzazione. – fishlips

+0

@fishlips: tranne quando una lingua ha tre o più forme plurali. Come spiegato di seguito, la funzione ngettext è la soluzione più generale. Permette a un traduttore di includere tutte le sue forme plurali nel file ".po" e quello di destra verrà selezionato in fase di runtime. –

3

Mi sorprende che nessuno ha suggerito che ancora, ma quello che faccio di solito è quello di utilizzare l'operatore condizionale:

string commentWord = numComments != 1 ? "Comments" : "Comment"; 

Nota: la stringa non deve naturalmente essere difficile codificato in questo modo a tutti, ma piuttosto caricati da alcuni repository di risorse, in cui è memorizzato con un segnaposto di formattazione per il numero, in modo da poter gestire lingue in cui il numero dovrebbe apparire ultima (o nel mezzo):

// should load "{0} Comments" or "{0} Comment" if we run in an English locale 
string comments = string.Format(
     numComments != 1 ? GetResource("Comments") : GetResource("Comment"), 
     numComments); 
+4

Questo non è il modo giusto per fare internazionalizzazione. La lingua diversa dall'inglese ha le sue regole per le forme plurali; per esempio. Il lituano ha tre diverse forme: "1 komentaras", "2 komentarai", "10 komentarų". Il framework gettext GNU popolare nei programmi C ha una soluzione per questo (la funzione ngettext). Non ho familiarità con Java/C#/PHP, quindi non posso dire quale sia la soluzione corretta canonica lì. –

+0

@ Mario: grazie per questa informazione. Non ero a conoscenza di quelle regole lituane. Ho fatto un po 'di software internazionale (evento realizzato un software di traduzione di testi dell'interfaccia utente per un grande cliente) ma non ho mai incontrato richieste del genere. Molto interessante! Non mi dilungherò nei dettagli qui però, volevo solo introdurre il concetto di raccogliere i testi da un repository di risorse, piuttosto che limitarsi a codificarli. –

+0

@Fredrik: Anch'io sono stato sorpreso la prima volta che ho sentito parlare di lingue con più di due forme plurali ... Sono danese e usavo solo due forme :-) Fortunatamente, la funzione ngettext può occuparsene, per favore vedi il mio rispondi da qualche altra parte su questa pagina. –

0

Controlla il Rails inflector module. Ciò fornisce una soluzione piacevole, centralizzata e configurabile a questo problema.

2

In C/C++, è possibile effettuare le seguenti operazioni. Potresti essere in grado di fare qualcosa di simile in PHP.

printf("%d %s\n", numComments, numComments == 1 ? "Comment" : "Comments"); 

Di seguito funziona anche, ma si può incorrere in problemi con \b (backspace) affidate in modo non corretto in diverse implementazioni.

printf("%d Comment%s\n", numComments, numComments == 1 ? " \b" : "s"); 

Utilizzando \0 (carattere nullo) per stampare nulla, invece, stampati uno spazio nella mia implementazione.

Problemi correlati