2010-01-15 12 views
5

Estoy construyendo un multi-idiomas griales sitio web y que necesita para obtener el sufijo ordinal de un número para varios idiomas como Inglés, Francés , Español, alemán e italiano¿Cómo obtener el sufijo ordinal de un número para muchos idiomas en Java o Groovy

Creo que este problema es bastante común para los propietarios de sitios web de varios idiomas. He encontrado this article que proporciona una solución, pero solo en inglés.

Por ejemplo:

/** 
*@value number 
*@locale Current locale 
*@returns ordinal suffix for the given number 
**/ 
public static String getOrdinalFor(int value, Locale locale) 

dará los siguientes resultados:

assert getOrdinalFor(1, Locale.ENGLISH) == "st" 
assert getOrdinalFor(1, Locale.FRENCH) == "er" 
assert getOrdinalFor(2, Locale.ENGLISH) == "nd" 
assert getOrdinalFor(3, Locale.ENGLISH) == "rd" 
assert getOrdinalFor(4, Locale.ENGLISH) == "th" 
assert getOrdinalFor(4, Locale.FRENCH) == "ème" 

sabe usted una biblioteca (en Java o Groovy) que pueden ayudar a esto? ¿O conoces un algoritmo que lo implementa?

Respuesta

3

Creo que en muchos idiomas este enfoque es imposible ya que simplemente no tienen ningún concepto de ordinales que pueden estar compuestos de un número con algunas letras como extensión. Para "1er", es decir, en alemán, solo puede escribir "1". o "erster"/"erste"/"erstes" dependiendo del género de lo que está numerando.

+0

o "ersten" según la estructura de la oración – Thilo

+0

Acepto que es complejo.Tal vez imposible para todos los idiomas. Pero para los idiomas occidentales como inglés, español, francés y alemán, estoy seguro de que es posible (y no tan difícil de implementar). Lo que es sorprendente es que no hay bibliotecas, AFAIK, que resuelvan en parte esta situación común ... – fabien7474

+1

Sí, intenta eludir este requisito si puedes. De todos modos, para qué necesitas estos sufijos? una vez que superas el 1. °, 2. ° y 3. ° grado, ¿realmente necesitas otros? –

0

No conozco ninguna biblioteca, pero el mejor algoritmo puede ser conseguir todos los posibles números/locales/ordinales en un Map<Integer, Map<Locale, String>>.

private static Map<Integer, Map<Locale, String>> ordinals = new HashMap<Integer, Map<Locale, String>>(); 
static { 
    Map<Locale, String> ordinal1 = new HashMap<Locale, String>(); 
    ordinal1.put(Locale.ENGLISH, "st"); 
    ordinal1.put(Locale.FRENCH, "er"); 
    ordinals.put(1, ordinal1); 
    Map<Locale, String> ordinal2 = new HashMap<Locale, String>(); 
    ordinal2.put(Locale.ENGLISH, "nd"); 
    ordinals.put(2, ordinal2); 
    Map<Locale, String> ordinal3 = new HashMap<Locale, String>(); 
    ordinal3.put(Locale.ENGLISH, "rd"); 
    ordinals.put(3, ordinal3); 
    Map<Locale, String> ordinal4 = new HashMap<Locale, String>(); 
    ordinal4.put(Locale.ENGLISH, "th"); 
    ordinal4.put(Locale.FRENCH, "ème"); 
    ordinals.put(4, ordinal4); 
} 

El getOrdinalFor() podría entonces básicamente se parezca a (manejo de error de ejecución obvia a un lado):

public static String getOrdinalFor(int value, Locale locale) { 
    return ordinals.get(value).get(locale); 
} 

Para otros números que no están cubiertas por el mapa, se puede considerar la cuenta atrás del número hasta que un partido se encuentra en el mapa (por lo que solicita el ordinal para, por ejemplo 5 o superior devolvería el ordinal 4 (el partido firstnext en cuenta regresiva)):

public static String getOrdinalFor(int value, Locale locale) { 
    Map<Locale, String> ordinal = null; 
    for (int i = value; i > 0 && (ordinal == null || !ordinal.containsKey(locale)); i--) { 
     ordinal = ordinals.get(i); 
    } 
    return ordinal != null ? ordinal.get(locale) : null; // Or other default? 
} 
+0

Dada tu solución, ¿cómo lidias con el siguiente número: 2900932? – fabien7474

+0

Simplemente devolvería 'th'. El OP también puede elegir el último dígito del número para obtener el ordinal. – BalusC

+0

¿Todos los números posibles en un hashmap? ¡Eso sería un gran mapa! "puede considerar realizar una cuenta atrás del valor hasta que se encuentre una coincidencia en el mapa" -> esto no funcionará correctamente. Por ejemplo: habría agregado 23. Si quiere la correcta para 24, también debe agregar 24, pero si quiere la correcta para 33, deberá agregarla nuevamente. Lo mismo para 34, 43, 44, ... – Fortega

1

A menos que pueda aplicar una regla en todos los idiomas, es común tratar de eludir problemas lingüísticos complejos. Debe considerar no solo el número y su ordinal, sino el contexto en el que aparece e incluso cómo la posición dentro de una oración puede afectar la traducción.

En lugar de tratar de escribir "1er lugar", un recurso de este tipo es mucho más fácil de traducir:

#easyToTranslate_en.properties 
label.position=Position: {0,number,integer} 

Dependiendo de lo que estamos tratando de hacer, usted puede ser capaz de comprometerse con una solución como esta:

#compromise_en.properties 
label.position.first=1st place 
label.position.second=2nd place 
label.position.third=3rd place 
label.position.default=Position: {0,number,integer} 

esto requeriría el código de leer el recurso para realizar una prueba caso de elegir qué recurso a la carga.

1
int index = 2; 
ChoiceFormat choiceFormat = new ChoiceFormat("1#st | 2#nd | 3#rd | 20<th"); 
String output = index + choiceFormat.format(index); 

salida == 'segundo' pero estoy tratando de escribir una regla que se asegurará de que los números 21-> 23, 31-> 33, etc también funcionan bien. ¿Alguien sabe cómo hacer esto usando el patrón pasado a ChoiceFormat?

Cuestiones relacionadas