2010-01-15 34 views
5
許多語言

我建立一個多國語言的Grails網站,我需要得到一個數的序後綴幾種語言如英語,法語,西班牙語,德語和意大利語。如何得到一個數字的序數後綴,在Java或Groovy

我認爲這個問題對於多語言網站所有者來說是相當普遍的。我發現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),可以幫助呢?或者你知道一個實現它的算法嗎?

回答

3

我覺得在很多語言中這種方法是不可能的,因爲他們根本沒有序數的概念,可以用一些數字組成的字母作爲擴展。對於「第一」即德文,您只能寫「1」。或「erster」/「erste」/「erstes」,具體取決於您所編號的屬性。

+0

或「ersten」取決於句子結構 – Thilo 2010-01-15 12:51:58

+0

我同意這很複雜。也許所有語言都不可能。但對於英語,西班牙語,法語和德語等西方語言,我相信這是可能的(並且不難實現)。令人驚訝的是,沒有庫AFAIK能部分解決這種常見情況...... – fabien7474 2010-01-15 14:15:14

+1

是的,如果可以的話,嘗試避開這個要求。無論如何,你需要這些後綴?一旦你超越了第一,第二和第三,你真的需要額外的嗎? – 2010-01-16 06:02:13

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或更高版本將返回4序(上倒計時firstnext匹配)):

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

鑑於您的解決方案,您如何處理以下數字:2900932? – fabien7474 2010-01-15 12:48:47

+0

它只會返回'th'。 OP當然也可以從數字中選擇最新的數字來獲得序數。 – BalusC 2010-01-15 12:51:00

+0

散列表中所有可能的數字?那將是一張大地圖! 「您可能會考慮倒計時值,直到在地圖中找到匹配項」 - >這將無法正常工作。例如:你會添加23.如果你想要24的正確的,你也必須添加24,但如果你想正確的爲33,你將不得不再次添加它。相同的34,43,44,... – Fortega 2010-01-15 12:51:10

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
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的模式來做到這一點?

相關問題