example - Internacionalización de Java(i18n) con plurales adecuados
i18n java (2)
Bueno, ya has etiquetado la pregunta correctamente, así que supongo que sabes algo sobre la ICU .
Con la UCI tienes dos opciones para el manejo adecuado de las formas plurales:
- PluralRules , que le da las reglas para la PluralRules regional dada
- PluralFormat , que utiliza las reglas antes mencionadas para permitir el formateo
¿Cuál usar? Personalmente, prefiero usar PluralRules directamente, para seleccionar el mensaje apropiado de los paquetes de recursos.
ULocale uLocale = ULocale.forLanguageTag("pl-PL");
ResourceBundle resources = ResourceBundle.getBundle( "path.to.messages",
uLocale.toLocale());
PluralRules pluralRules = PluralRules.forLocale(uLocale);
double[] numbers = { 0, 1, 1.5, 2, 2.5, 3, 4, 5, 5.5, 11, 12, 23 };
for (double number : numbers) {
String resourceKey = "some.message.plural_form." + pluralRules.select(number);
String message = "!" + resourceKey + "!";
try {
message = resources.getString(resourceKey);
System.out.println(format(message, uLocale, number));
} catch (MissingResourceException e) { // Log this }
}
Por supuesto, usted (o el traductor) necesitaría agregar los formularios adecuados al archivo de propiedades, en este ejemplo, digamos:
some.message.plural_form.one=Znaleziono {0} plik
some.message.plural_form.few=Znaleziono {0} pliki
some.message.plural_form.many=Znaleziono {0} plików
some.message.plural_form.other=Znaleziono {0} pliku
Para otros idiomas (es decir, árabe), es posible que también necesite usar las palabras clave "cero" y "dos", consulte las reglas en plural de CLDR para más detalles.
Alternativamente, puede utilizar PluralFormat para seleccionar la forma válida. Los ejemplos habituales muestran una instanciación directa, lo que, en mi opinión, no tiene ningún sentido. Es más fácil de usar con MessageFormat de ICU :
String pattern = "Znaleziono {0,plural,one{# plik}" +
"few{# pliki}" +
"many{# plików}" +
"other{# pliku}}";
MessageFormat fmt = new MessageFormat(pattern, ULocale.forLanguageTag("pl-PL"));
StringBuffer result = new StringBuffer();
FieldPosition zero = new FieldPosition(0);
double[] theNumber = { number };
fmt.format(theNumber, result, zero);
Por supuesto, de manera realista no codificarías la cadena del patrón, sino que colocarías algo como esto en el archivo de propiedades:
some.message.pattern=Found {0,plural,one{# file}other{# files}}
El único problema con este enfoque es que el traductor debe conocer el formato del marcador de posición. Otro problema que traté de mostrar en el código anterior es que el método de formato estático () de MessageFormat (el que es fácil de usar) siempre se formatea para la configuración regional predeterminada. Esto podría ser un problema real en las aplicaciones web, donde la configuración regional predeterminada generalmente significa la del servidor. Por lo tanto, tuve que formatear para un Locale específico (números de punto flotante, claro) y el código parece bastante feo ...
Sigo prefiriendo el enfoque de PluralRules, que para mí es mucho más limpio (aunque necesita usar el mismo estilo de formato de mensaje, solo envuelto con un método auxiliar).
Iba a utilizar el sistema i18n estándar de Java con la clase ChoiceFormat para plurales, pero luego me di cuenta de que no maneja las complejas reglas plurales de algunos idiomas (por ejemplo, polaco). Si solo maneja idiomas que se parecen al inglés, entonces parece un poco inútil.
¿Qué opciones existen para lograr formas plurales correctas? ¿Cuáles son los pros y los contras de usarlos?
ChoiceFormat
, como se explica aquí, parece lo suficientemente flexible como para lidiar con cualquier tipo de pluralización que pueda lanzar.
EDITAR: como el Dr.Haribo señaló en su comentario, ChoiceFormat no es suficiente para la pluralización polaca. Pero un seguimiento del mismo blog sugiere ICU4J que maneja reglas de pluralización más complejas.