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

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

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

Например:

/**
 *@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), который может помочь этому? Или Вы знаете алгоритм, который реализует его?

5
задан fabien7474 15 January 2010 в 12:06
поделиться

3 ответа

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

3
ответ дан 15 December 2019 в 01:02
поделиться

Не знаю ни одной библиотеки, но лучшим алгоритмом может быть получение всех возможных чисел/локалей/ординалов в Карте>.

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);
}

Для других номеров, которые не покрыты картой, вы можете рассмотреть возможность обратного отсчета номера до тех пор, пока в карте не будет найдено совпадение (так что запрос ординала для e. g. 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? 
}
0
ответ дан 15 December 2019 в 01:02
поделиться

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

Вместо того, чтобы пытаться написать "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}

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

1
ответ дан 15 December 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: