如何在Java或Groovy中获取许多语言的数字的序数后缀

时间:2010-01-15 12:06:48

标签: java grails localization groovy

我正在构建一个多语言 grails 网站,我需要获得英语,法语,西班牙语,德语和意大利语等多种语言的序号后缀

我认为这个问题对于多语言网站所有者来说非常普遍。我发现this article提供了一个解决方案,但它只是英文版。

例如:

/**
 *@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 个答案:

答案 0 :(得分:3)

我认为在许多语言中这种方法是不可能的,因为它们根本没有可用由一些字母作为扩展的数字组成的序数概念。对于“1st”,即德语,你只能写“1”。或“erster”/“erste”/“erstes”取决于您编号的属。

答案 1 :(得分:1)

除非您可以对每种语言应用规则,否则通常会尝试回避复杂的语言问题。你不仅要考虑数字及其序数,还要考虑它出现的背景,甚至句子中的位置如何影响翻译。

而不是尝试编写“1st place”,这样的资源更容易翻译:

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

这将需要读取资源的代码执行案例测试以选择要加载的资源。

答案 2 :(得分:0)

我不知道任何库,但最好的算法可能是在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或更高的序数将返回{的序数{1}}(倒计时的第一个下一个匹配)):

4

答案 3 :(得分:0)

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

输出=='第二' 但我正在尝试编写一条规则,确保数字21-> 23,31-> 33等也能正常工作。有人知道如何使用传递给ChoiceFormat的模式吗?