Ver índice de contenidos del libro

15.6. Pluralizando

La pluralización de mensajes es un tema difícil puesto que las reglas pueden ser bastante complejas en función de cada idioma. Por ejemplo, aquí tienes la representación matemática de las reglas de pluralización del idioma ruso:

(($number % 10 == 1) && ($number % 100 != 11))
    ? 0
    : ((($number % 10 >= 2)
        && ($number % 10 <= 4)
        && (($number % 100 < 10)
        || ($number % 100 >= 20)))
            ? 1
            : 2
);

Como puedes ver, en ruso existen tres formas diferentes del plural, dando a cada una un índice de 0, 1 o 2. El plural es diferente para todas las formas, por lo que la traducción también es diferente.

Cuando una traducción tiene diferentes formas debido a la pluralización, puedes proporcionar todas las variantes en una misma cadena de texto separada por una línea vertical (|):

'Hay una manzana|Hay %count% manzanas'

Para traducir mensajes pluralizados, utiliza el método transChoice:

$translated = $this->get('translator')->transChoice(
        'Hay una manzana|Hay %count% manzanas',
        10,
        array('%count%' => 10)
    );

El segundo argumento (10 en este ejemplo), es el número de objetos al que se refiere la frase y se utiliza tanto para determinar la traducción a usar como para rellenar el marcador de posición %count%.

En función del número indicado, el traductor de Symfony2 elige la forma plural adecuada. En inglés, la mayoría de las palabras tienen una forma singular cuando hay exactamente un objeto y una forma plural para todos los otros números (0, 2, 3...). Así pues, si count es 1, el traductor utilizará la primera cadena (Hay una manzana) como la traducción. De lo contrario, utilizará Hay %count% manzanas.

Aquí está la traducción al Francés::

'Il y a %count% pomme|Il y a %count% pommes'

Aunque en este caso la traducción tiene un aspecto similar al caso del inglés (se compone de dos subcadenas separadas por una línea vertical), las reglas francesas son diferentes: la primera forma (no plural) se utiliza cuando count es 0 o 1. Por lo tanto, el traductor utilizará automáticamente la primera cadena (Il y a %count% pomme) cuando count es 0 o 1.

Cada idioma tiene su propio conjunto de reglas, con algunos que tienen hasta seis formas diferentes de plural con reglas muy complejas. Las reglas son bastante simples para el inglés y el francés, pero para idiomas como el ruso puede ser útil tener alguna pista sobre la cadena que se va a utilizar en cada caso. Para ayudar a los traductores, puedes añadir una etiqueta al principio de cada cadena:

'one: There is one apple|some: There are %count% apples'
 
'none_or_one: Il y a %count% pomme|some: Il y a %count% pommes'

Las etiquetas solamente son pistas para los traductores y no afectan a la lógica utilizada para determinar qué forma plural usar. Las etiquetas pueden ser cualquier cadena de texto que termine con dos puntos (:). Además, las etiquetas no tienen por qué ser las mismas en el mensaje original y en la traducción.

Truco Como las etiquetas son opcionales, el servicio translator no las utiliza (el translator únicamente obtiene la cadena en función de su posición dentro de la cadena completa).

15.6.1. Intervalo explícito de pluralización

La forma más fácil de pluralizar un mensaje es dejar que Symfony2 utilice su lógica interna para elegir qué cadena se utiliza en función del número indicado. No obstante, en ocasiones necesitas un control más precios o quieres realizar una traducción diferente para algunos casos específicos (cuando el número es 0 o cuando es negativo, por ejemplo). Para estos casos, puedes utilizar intervalos matemáticos explícitos:

'{0} There are no apples|{1} There is one apple|]1,19] There are %count% apples|[20,Inf] There are many apples'

Los intervalos siguen la notación ISO 31-11. La cadena de texto anterior especifica cuatro intervalos diferentes: exactamente 0, exactamente 1, 2-19 y 20 o más.

También puedes mezclar reglas matemáticas explícitas con las reglas estándar. En este caso, si el número no corresponde con un intervalo específico, se aplican las reglas estándar después de eliminar las reglas matemáticas:

'{0} There are no apples|[20,Inf] There are many apples|There is one apple|a_few: There are %count% apples'

Para el número 1 por ejemplo, se utiliza la regla estándar There is one apple. Para un número entre 2 y 19, se utiliza la segunda regla estándar There are %count% apples.

Los intervalos pueden representar un conjunto finito de números:

{1,2,3,4}

Y también pueden representar a todos los números comprendidos entre los dos números indicados:

[1, +Inf[
]-1,2[

El delimitador izquierdo puede ser [ (inclusivo) o ] (exclusivo). El delimitador derecho puede ser [ (exclusivo) o ] (inclusivo). Además de números, puedes usar -Inf y +Inf para indicar el valor infinito.