Pluralizzazione per JavaScript

Il 71% degli utenti attuali di internet non parla inglese come prima lingua e questo numero continua a crescere, ma nonostante ciò, poche persone si specializzano nell’internazionalizzazione. Come risultato, la maggior parte dei siti sbaglia perché le cose che sembrano semplici sono spesso tutto tranne quello.

L’articolo prosegue sotto

Prendiamo per esempio la pluralizzazione. Mettere al plurale singole parole all’interno di stringhe diventa rapidamente complesso, anche in inglese, dove la maggior parte delle parole plurali finisce con una s. Per esempio, ho lavorato ad una app per condivisione di foto che supporta due lingue, inglese e cinese. Aggiungere una s per mostrare “X like[s]” o “Y comment[s]” è stato semplice, ma cosa sarebbe successo se avessimo avuto bisogno di pluralizzare “foot” o “inch” o “quiz”? La nostra semplice soluzione sarebbe diventata un hack malfunzionante.

Per di più, l’inglese è un caso relativamente semplice. Molte lingue hanno più di due forme plurali: l’arabo, per esempio, ne ha sei e molte lingue slave ne hanno più di tre. In effetti, almeno 39 lingue hanno più di due forme plurali. Alcune lingue hanno una forma, come il cinese e il giapponese, il che implica che i nomi singolari e plurali sono identici.

Come possiamo dare un senso a tali complesse questioni riguardanti la pluralizzazione e risolverle nei nostri progetti? In questo articolo, vi mostrerò alcuni dei più comuni problemi di pluralizzazione e vi spiegherò come superarli.

Problemi con la pluralizzazione#section1

La pluralizzazione è addirittura ancora più complicata: ogni lingua ha anche le sue regole per definire ogni forma di plurale. Una regola per il plurale definisce una forma di plurale usando una formula che include un contatore. Un contatore è un numero di oggetti che si sta cercando di rendere al plurale. Supponiamo che stiamo lavorando con “2 conigli”. Il numero prima di “conigli“ è il contatore, che in questo caso ha valore 2. Ora, se prendiamo l’inglese come esempio, ha due forme plurali: singolare e plurale. Pertanto, le nostre regole avranno questo aspetto:

  • Se il contatore ha il valore intero 1, usa il singolare: “rabbit”.
  • Se il contatore ha un valore diverso da 1, usa il plurale: “rabbits”.

Tuttavia, non si può affermare lo stesso per il polacco, in cui la stessa parola, “rabbit” o “królik”, può avere più di forme:

  • Se il contatore ha il valore intero 1, usate “królik”.
  • Se il contatore ha un valore che finisce in 2–4, esclusi 12–14, usate “królika”.
  • Se il contatore non è 1 e ha un valore che finisce in 0 o 1, oppure il contatore termina in 5–9, o il contatore termina in 12–14, usate “królików”.
  • Se il contatore ha un valore diverso da quelli elencati prima, usate “króliki”.

E questo solo per il “singolare” e per il “plurale”. Per le lingue con tre o più forme di plurale, abbiamo bisogno di etichette più specifiche.

Diverse lingue usano diversi tipi di numeri#section2

Potreste anche dover mostrare il contatore con il nome pluralizzato, come ad esempio “You have 3 rabbits”. Tuttavia, non tutte le lingue usano i numeri arabi a cui potreste essere abituati. Per esempio, l’arabo usa i numeri Indo-Arabi, ٠١٢٣٤٥٦٧٨٩:

  • 0 libri: ٠ كتاب
  • 1 libro: كتاب
  • 3 libri: ٣ كتب
  • 11 libri: ١١ كتابًا
  • 100 libri: ١٠٠ كتاب

Diverse lingue o differenti regioni usano formati numerici diversi#section3

Spesso, abbiamo anche come obiettivo quello di rendere più leggibili i numeri molto grossi aggiungendo dei separatori, come quando mostriamo il numero 1000 come “1,000” in inglese. Ma molte lingue e regioni usano diversi frazionari e separatori per le migliaia. Per esempio, il tedesco rende il numero 1000 come “1.000”. Altre lingue non raggruppano i numero per le migliaia, ma per decine di migliaia.

Soluzione: il MessageFormat di ICU#section4

La pluralizzazione è un problema complesso da risolvere, perlomeno se volete gestire tutti i casi limite. Recentemente l’International Components for Unicode (ICU) ha fatto proprio questo con MessageFormat. Il MessageFormat di ICU è un linguaggio di markup creato specificatamente per la localizzazione. Permette di definire, in maniera dichiarativa, il modo in cui i nomi dovrebbero essere resi in varie forme plurali. Classifica al posto vostro tutte le forme plurali e relative regole e formatta i numeri in maniera corretta. Sfortunatamente, molti di voi non avranno ancora sentito parlare di MessageFormat, perché è perlopiù utilizzato da persone che lavorano specificamente con l’internazionalizzazione, noti agli addetti ai lavori come i18n e JavaScript si è evoluto solo recentemente per gestirlo.

Vediamo come funziona

Usare CLDR per la forma plurale#section5

CLDR sta per Common Locale Data Repository ed è un repository che aziende come Google, IBM e Apple usano per avere informazioni sulla formattazione di numeri, date e tempo. Il CLDR contiene anche dati sulle forme plurali e regole per molte lingue. È probabilmente il locale data repository più grande al mondo, il che lo rende ideale come base per ogni tool di internazionalizzazione JavaScript.

Il CLDR definisce fino a sei forme diverse di plurale. A ogni forma è assegnato un nome: zero, one, two, few, many, o other. Non tutte le locali hanno bisogno di ogni forma: ricordate, l’inglese ne ha solo due: one e other. Il nome di ogni forma è basato sulla sua regola plurale corrispondente. Ecco un esempio CLDR per la lingua polacca, versione leggermente modificata delle nostre regole precedenti per il contatore:

  • Se il contatore ha il valore intero 1, usa la forma plurale one.
  • Se il contatore ha un valore che termina in 2–4, esclusi 12–14, usa la forma plurale few.
  • Se il contatore non è 1 e ha un valore che termina in 0 o 1, o il contatore finisce in 5–9, o il contatore termina in 12–14, usa la forma plurale many.
  • Se il contatore ha un qualsiasi altro valore diverso dai precedenti, usa la forma plurale other.

Invece di implementare a mano le forme plurali del CLDR, potete usare dei tool e delle librerie. Per esempio, ho creato L10ns, che compila il codice al posto vostro, FormatJS di Yahoo ha tutte le forme plurali al suo interno. Il grande vantaggio di questi tool e di queste librerie è che scalano bene perché estraggono la geestione della forma plurale. Se scegliete di fare voi stessi la codifica delle forme plurali, finirete con l’esaurire voi stessi e i vostri compagni di team, perché dovrete tenere traccia di tutte le varie forme e regole e definirle più e più volte ogni volta e in ogni posto in cui vorrete formattare una stringa plurale.

MessageFormat#section6

MessageFormat è un linguaggio domain-specific che usa CLDR ed è specificatamente creato per localizzare le stringhe. Si definisce il markup inline. Per esempio, vogliamo formattare il messaggio “I have X rabbit[s]” usando la forma plurale giusta per la parola “rabbit”:


var message = 'I have {rabbits, plural, one{# rabbit} other{# rabbits}}';

Come potete vedere, un formato plurale è definito all’interno di parentesi graffe {}. Prende un contatore, rabbits, come primo argomento. Il secondo argomento definisce il tipo di formattazione; il terzo argomento include la forma plurale (one, many) del CLDR. Dovete definire un sotto-messaggio all’interno delle parentesi graffe corrispondente a ciascuna forma plurale. Potete anche passargli il simbolo # per rendere il contatore con il formato del corretto numero e con il corretto sistema di numerazione, così da risolvere i problemi che abbiamo identificato in precedenza con il sistema di numeri indo-arabico e con la formattazione dei numeri.

Qui facciamo il parsi del messaggio nella local en-US e abbiamo in uscita diversi messaggi a seconda della forma di plurale che assume la variabile rabbits:


var message = 'I have {rabbits, plural, one{# rabbit} other{# rabbits}}.';
var messageFormat = new MessageFormat('en-US');
var output = messageFormat.parse(message);

// Will output "I have 1 rabbit."
console.log(output({ rabbits: 1 }));

// Will output "I have 10 rabbits."
console.log(output({ rabbits: 10 }));

Vantaggi dell’inline#section7

Come potete vedere nel messaggio precedente, abbiamo definito il formato plurale inline. Se non fosse stato inline, avremmo avuto bisogno di ripetere le parole “I have…” per tutte le forme plurali invece di scriverle una sola volta. Immaginate se aveste bisogno di usare ancora più parole, come nel seguente esempio:


{
  one: 'My name is Emily and I got 1 like in my latest post.'
  other:  'My name is Emily and I got # likes in my latest post.'
}

Senza l’inline, dovremmo ripetere “My name is Emily and I got…in my latest post” ogni singola volta. Si tratta di molte parole.

Di contro, l’inline nel MessageFormat di ICU semplifica le cose: invece di ripetere la frase per ogni forma plurale, tutto quello che dobbiamo fare è localizzare la parola “like”:


var message = 'My name is Emily and I got {likes, plural, one{# like} other{# likes}} in my latest post';

In questo caso non dobbiamo ripetere le parole “My name is Emily and I got…in my latest post” per ogni forma plurale. Al contrario dobbiamo semplicemente localizzare la parola “like”.

Vantaggi dell’annidamento dei messaggi#section8

La natura annidata di MessageFormat ci viene inoltre in aiuto dandoci possibilità infinite per definire una moltitudine di stringhe complesse. Qui definiamo un formato di select in un formato plurale per dimostrare quanto sia flessibile MessageFormat:


var message = '{likeRange, select,\
  range1{I got no likes}\
  range2{I got {likes, plural, one{# like} other{# likes}}}\
  other{I got too many likes}\
}';

Un formato select abbiana un insieme di casi e, a seconda del caso con cui fa coppia, dà in uscita il corrispondente sotto-messaggio. È perfetto per costruire messaggi basati su un range. Nell’esempio precedente, vogliamo costruire tre tipi di messaggio per ciascun range di like. Come potete vedere in range2, abbiamo definito un formato plurale per formattare il messaggio “I got X like[s]” e poi abbiamo annidato il formato plurale all’interno del formato select. Questo esempio mostra una formattazione molto complessa che pochissime sintassi possono ottenere, dimostrando la flessibilità di MessageFormat.

Con il formato di cui sopra, ecco i messaggi che possiamo ottenere:

  • “I got no likes,” se likeRange è nel range1.
  • “I got 1 like,” se likeRange è nel range2 e il numero di like è 1.
  • “I got 10 likes,” se likeRange è nel range2 e il numero di like è 10.
  • “I got too many likes,” se likeRange non è né in range1 né in range2.

Si tratta di concetti veramente difficili da localizzare: perfino uno dei più famosi tool di internazionalizzazione, gettext, non può fare questa cosa.

Storage e messaggi pre-compilati#section9

Tuttavia, invece di memorizzare i messaggi di MessageFormat in una variabile JavaScript, potreste dover usare qualche tipo di formato di memorizzazione, come più files JSON. Questo vi permetterà di pre-compilare i messaggi in semplici getter di localizzazione. Se non volete gestire questo da soli potreste provare L10ns, che gestisce lo storage e la pre-compilazione per voi, così come la sincronizzazione delle chiavi di traduzione tra sorgente e storage.

I traduttori devono conoscere MessageFormat?#section10

Potreste pensare che sia troppo pesante per traduttori non-programmatori conoscere MessageFormat e la forma plurale di CLDR, ma, per quella che è la mia esperienza, per insegnargli le basi di come appare il markup e quello che fa e cosa sono le forme plurali di CLDR ci vogliono solo alcuni minuti e dà sufficienti informazioni ai traduttori per svolgere il loro lavoro usando MessageFormat. L’interfaccia web di L10ns mostra anche i numeri di esempio per ogni forma plurale di CLDR per farvi riferimento facilmente.

Screenshot dell'intefaccia di L10ns, che mostra le variabili plurali per la frase 'I got X likes.

La pluralizzazione non è facile ma ne vale la pena#section11

Sì, la pluralizzazione ha moltissimi casi limite che non sono risolvibili facilmente, ma il MessageFormat di ICU mi ha aiutato tantissimo nel mio lavoro, dandomi una flessibilità infinita nel tradurre le stringhe plurali. Muovendoci verso un mondo più connesso, dobbiamo per forza localizzare le applicazioni in più lingue. Dobbiamo conoscere i problemi generali di localizzazione e gli strumenti per risolverli. Dobbiamo localizzare le app perché il mondo è più connesso ma possiamo anche localizzare le app per contribuire a rendere il mondo più connesso.

Illustrazioni: {carlok}

Sull’autore

Tingan Ho

Tingan Ho è un designer, un programmatore e un intellettuale che vive in Svezia. Ama il web e tutte le soluzioni innovative e open source che gli ruotano attorno. Scrive librerie e tools per svolgere in maniera più efficiente il lavoro con le tecnologie web quotidianamente. Potete scoprire quello che ha da dire sul web su @tingan87.

Nessun commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Altro da ALA

Webwaste

In questo estratto da World Wide Waste, Gerry McGovern esamina l'impatto ambientale di siti web pieni zeppi di asset inutili. Digital is physical. Sembra economico e gratis ma non lo è: ci costa la Terra.
Industry