Как получить порядковый суффикс числа для многих языков в Java или Groovy - PullRequest
5 голосов
/ 15 января 2010

Я создаю веб-сайт на нескольких языках grails , и мне нужно получить порядковый суффикс числа для нескольких языков , таких как английский, французский, испанский, немецкий и итальянский.

Я считаю, что эта проблема довольно распространена среди владельцев многоязычных веб-сайтов. Я нашел эту статью , которая предлагает решение, но только на английском языке.

Например:

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

даст следующие результаты:

 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"

Знаете ли вы библиотеку (на Java или Groovy), которая может помочь в этом? Или вы знаете алгоритм, который его реализует?

Ответы [ 4 ]

3 голосов
/ 15 января 2010

Я думаю, что во многих языках такой подход невозможен, поскольку в них просто нет понятия ординалов, которые могут состоять из числа с некоторыми буквами в качестве расширения. Для «1-го», то есть на немецком языке, вы можете написать «1». или "erster" / "erste" / "erstes" в зависимости от рода того, что вы нумеруете.

1 голос
/ 15 января 2010

Если вы не можете применить правило ко всем языкам, часто пытаются обойти сложные языковые проблемы. Вы должны учитывать не только число и его порядковый номер, но и контекст, в котором оно появляется, и даже то, как позиция в предложении может повлиять на перевод.

Вместо того, чтобы пытаться написать "1-е место" , такой ресурс гораздо проще перевести:

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

В зависимости от того, что вы пытаетесь сделать, вы можете пойти на компромисс с таким решением:

#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}

Для этого потребуется код, считывающий ресурс, чтобы выполнить кейс-тест для выбора ресурса для загрузки.

0 голосов
/ 29 сентября 2011
int index = 2;
ChoiceFormat choiceFormat = new ChoiceFormat("1#st | 2#nd | 3#rd | 20<th");
String output = index + choiceFormat.format(index);

output == '2nd' Но я пытаюсь написать правило, которое гарантирует, что числа 21-> 23, 31-> 33 и т. Д. Также работают нормально Кто-нибудь знает, как это сделать, используя шаблон, переданный ChoiceFormat?

0 голосов
/ 15 января 2010

Я не знаю ни одной библиотеки, но лучшим алгоритмом может быть получение всех возможных чисел / локалей / порядковых чисел в 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);
}

В таком случае getOrdinalFor() может в основном выглядеть (за исключением очевидной обработки ошибок во время выполнения):

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

Для других чисел, которые не включены в карту, вы можете рассмотреть возможность обратного отсчета числа до тех пор, пока на карте не будет найдено совпадение (чтобы запрос порядкового номера, например, 5 или выше, возвращал бы порядковый номер для 4 (первое следующее совпадение при обратном отсчете)):

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? 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...