Add initial implementation of CLDR number rules.

This commit is contained in:
Michael Vehrs 2010-11-20 12:42:59 +00:00
parent 1e59e946fe
commit 55b1b4a0fb
13 changed files with 946 additions and 12 deletions

95
data/strings/plurals.xml Normal file
View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- <!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd"> -->
<supplementalData>
<version number="$Revision$"/>
<generation date="$Date$"/>
<plurals>
<!-- if locale is known to have no plurals, there are no rules -->
<pluralRules locales="az bm fa ig hu ja kde kea ko my ses sg to tr vi wo yo zh bo dz id jv ka km kn ms th"/>
<!-- 2nd line from Tamplin's data -->
<pluralRules locales="ar">
<pluralRule count="zero">n is 0</pluralRule>
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="two">n is 2</pluralRule>
<pluralRule count="few">n mod 100 in 3..10</pluralRule>
<pluralRule count="many">n mod 100 in 11..99</pluralRule>
</pluralRules>
<pluralRules locales="bem brx da de el en eo es et fi fo gl he iw it nb nl nn no pt_PT sv af bg bn ca eu fur fy gu ha is ku lb ml mr nah ne om or pa pap ps so sq sw ta te tk ur zu mn gsw chr rm pt"> <!-- 2nd two lines from Tamplin's data, deleting az fa -->
<pluralRule count="one">n is 1</pluralRule>
</pluralRules>
<pluralRules locales="ak am bh fil tl guw hi ln mg nso ti wa"> <!-- last line from Tamplin's data -->
<pluralRule count="one">n in 0..1</pluralRule>
</pluralRules>
<pluralRules locales="ff fr kab">
<pluralRule count="one">n within 0..2 and n is not 2</pluralRule>
</pluralRules>
<pluralRules locales="lv">
<pluralRule count="zero">n is 0</pluralRule>
<pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule>
</pluralRules>
<pluralRules locales="ga se sma smi smj smn sms">
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="two">n is 2</pluralRule>
</pluralRules>
<pluralRules locales="ro mo">
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="few">n is 0 OR n is not 1 AND n mod 100 in 1..19</pluralRule>
</pluralRules>
<pluralRules locales="lt">
<pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11..19</pluralRule>
<pluralRule count="few">n mod 10 in 2..9 and n mod 100 not in 11..19</pluralRule>
</pluralRules>
<pluralRules locales="hr ru sr uk be bs sh">
<pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule>
<pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule>
<pluralRule count="many">n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14</pluralRule>
<!-- others are fractions -->
</pluralRules>
<pluralRules locales="cs sk">
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="few">n in 2..4</pluralRule>
</pluralRules>
<pluralRules locales="pl">
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule>
<pluralRule count="many">n is not 1 and n mod 10 in 0..1 or n mod 10 in 5..9 or n mod 100 in 12..14</pluralRule>
<!-- others are fractions -->
<!-- and n mod 100 not in 22..24 from Tamplin -->
</pluralRules>
<pluralRules locales="sl">
<pluralRule count="one">n mod 100 is 1</pluralRule>
<pluralRule count="two">n mod 100 is 2</pluralRule>
<pluralRule count="few">n mod 100 in 3..4</pluralRule>
</pluralRules>
<pluralRules locales="mt"> <!-- from Tamplin's data -->
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="few">n is 0 or n mod 100 in 2..10</pluralRule>
<pluralRule count="many">n mod 100 in 11..19</pluralRule>
</pluralRules>
<pluralRules locales="mk"> <!-- from Tamplin's data -->
<pluralRule count="one">n mod 10 is 1 and n is not 11</pluralRule>
</pluralRules>
<pluralRules locales="cy"> <!-- from http://www.saltcymru.org/wordpress/?p=99&lang=en -->
<pluralRule count="zero">n is 0</pluralRule>
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="two">n is 2</pluralRule>
<pluralRule count="few">n is 3</pluralRule>
<pluralRule count="many">n is 6</pluralRule>
</pluralRules>
<pluralRules locales="lag">
<pluralRule count="zero">n is 0</pluralRule>
<pluralRule count="one">n within 0..2 and n is not 0 and n is not 2</pluralRule>
</pluralRules>
<pluralRules locales="shi">
<pluralRule count="one">n within 0..1</pluralRule>
<pluralRule count="few">n in 2..10</pluralRule>
</pluralRules>
<pluralRules locales="br"> <!-- from http://unicode.org/cldr/trac/ticket/2886 -->
<pluralRule count="zero">n is 0</pluralRule>
<pluralRule count="one">n is 1</pluralRule>
<pluralRule count="two">n is 2</pluralRule>
<pluralRule count="few">n is 3</pluralRule>
<pluralRule count="many">n is 6</pluralRule>
</pluralRules>
</plurals>
</supplementalData>

View File

@ -0,0 +1,103 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
/**
* This class handles zero or one rule for each number category.
*/
public class DefaultNumberRule implements Number {
Map<Category, Rule> rules = new EnumMap<Category, Rule>(Category.class);
/**
* Add a parsed rule for category.
*
* @param number a <code>Category</code> value
* @param rule a <code>Rule</code> value
*/
public void addRule(Category number, Rule rule) {
rules.put(number, rule);
}
/**
* Add an unparsed rule for category.
*
* @param number a <code>Category</code> value
* @param input a <code>String</code> value
*/
public void addRule(Category number, String input) {
rules.put(number, new Rule(input));
}
/**
* Return the number of rules added.
*
* @return an <code>int</code> value
*/
public int countRules() {
return rules.values().size();
}
/**
* Return the rule for the given category.
*
* @param category a <code>Category</code> value
* @return a <code>Rule</code> value
*/
public Rule getRule(Category category) {
return rules.get(category);
}
public Category getCategory(double input) {
for (Category number : Category.values()) {
Rule r = rules.get(number);
if (r != null && r.matches(input)) {
return number;
}
}
return Category.other;
}
public int getIndex(double input) {
int index = 0;
for (Category number : Category.values()) {
Rule r = rules.get(number);
if (r != null) {
if (r.matches(input)) {
return index;
} else {
index++;
}
}
}
return index;
}
}

View File

@ -0,0 +1,48 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
/**
* Number optimized for languages that distinguish the categories one,
* two and other.
*/
public class DualNumberRule implements Number {
public Category getCategory(double input) {
if (input == 1) {
return Category.one;
} else if (input == 2) {
return Category.two;
} else {
return Category.other;
}
}
public int getIndex(double input) {
if (input == 1) {
return 0;
} else if (input == 2) {
return 1;
} else {
return 2;
}
}
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2002-2007 The FreeCol Team
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*

View File

@ -0,0 +1,51 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
/**
* Classes implementing this interface can determine the category and
* the index of a double based on the number rules for a language.
*
* @See http://cldr.unicode.org/index/cldr-spec/plural-rules
*/
public interface Number {
public enum Category { zero, one, two, few, many, other };
/**
* Return the category input belongs to.
*
* @param input a <code>double</code> value
* @return a <code>Category</code> value
*/
public Category getCategory(double input);
/**
* Return the index of the rule this input matches. The index
* differs from the category in the following way: Given a
* language that distinguishes one, two and other, the index for
* the number 1 will be zero and the index for the number 2 will
* be 1 because there is no rule for category zero.
*
* @param input a <code>double</code> value
* @return an <code>int</code> value
*/
public int getIndex(double input);
}

View File

@ -0,0 +1,136 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import net.sf.freecol.client.gui.i18n.Number.Category;
/**
* @See http://cldr.unicode.org/index/cldr-spec/plural-rules
*/
public class NumberRules {
private static final Logger logger = Logger.getLogger(NumberRules.class.getName());
public static Number OTHER_NUMBER_RULE = new OtherNumberRule();
public static Number DUAL_NUMBER_RULE = new DualNumberRule();
public static Number PLURAL_NUMBER_RULE = new PluralNumberRule();
public static Number ZERO_ONE_NUMBER_RULE = new ZeroOneNumberRule();
Map<String, Number> numberMap = new HashMap<String, Number>();
public NumberRules(InputStream in) {
load(in);
}
public Number getNumberForLanguage(String lang) {
return numberMap.get(lang);
}
private void load(InputStream in) {
try {
XMLStreamReader xsr = XMLInputFactory.newInstance().createXMLStreamReader(in);
readFromXML(xsr);
} catch (Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
logger.warning(sw.toString());
throw new RuntimeException("Error parsing number rules.");
}
}
private void readFromXML(XMLStreamReader in) throws XMLStreamException {
while (in.nextTag() != XMLStreamConstants.END_ELEMENT) {
String tag = in.getLocalName();
if ("version".equals(tag)) {
in.nextTag();
} else if ("generation".equals(tag)) {
in.nextTag();
} else if ("plurals".equals(tag)) {
while (in.nextTag() != XMLStreamConstants.END_ELEMENT) {
tag = in.getLocalName();
if ("pluralRules".equals(tag)) {
readChild(in);
}
}
}
}
}
private void readChild(XMLStreamReader in) throws XMLStreamException {
String[] locales = in.getAttributeValue(null, "locales").split(" ");
if (locales != null) {
DefaultNumberRule numberRule = new DefaultNumberRule();
while (in.nextTag() != XMLStreamConstants.END_ELEMENT) {
if ("pluralRule".equals(in.getLocalName())) {
Category category = Category.valueOf(in.getAttributeValue(null, "count"));
Rule rule = new Rule(in.getElementText());
numberRule.addRule(category, rule);
}
}
Number number = null;
switch(numberRule.countRules()) {
case 0:
number = OTHER_NUMBER_RULE;
break;
case 1:
Rule rule = numberRule.getRule(Category.one);
if (rule != null) {
if ("n is 1".equals(rule.toString())) {
number = PLURAL_NUMBER_RULE;
} else if ("n in 0..1".equals(rule.toString())) {
number = ZERO_ONE_NUMBER_RULE;
}
}
break;
case 2:
Rule oneRule = numberRule.getRule(Category.one);
Rule twoRule = numberRule.getRule(Category.two);
if (oneRule != null
&& "n is 1".equals(oneRule.toString())
&& twoRule != null
&& "n is 2".equals(twoRule.toString())) {
number = DUAL_NUMBER_RULE;
}
break;
default:
number = numberRule;
}
for (String locale : locales) {
numberMap.put(locale, number);
}
}
}
}

View File

@ -0,0 +1,35 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
/**
* Number optimized for languages that do not distinguish any number
* categories. The category returned is always other.
*/
public class OtherNumberRule implements Number {
public Category getCategory(double input) {
return Category.other;
}
public int getIndex(double input) {
return 0;
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
/**
* Number optimized for languages that distinguish the categories one
* and other.
*/
public class PluralNumberRule implements Number {
public Category getCategory(double input) {
if (input == 1) {
return Category.one;
} else {
return Category.other;
}
}
public int getIndex(double input) {
if (input == 1) {
return 0;
} else {
return 1;
}
}
}

View File

@ -0,0 +1,142 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
import java.util.List;
public class Relation {
int low, high, mod = 1;
boolean negated = false;
boolean integer = true;
public Relation(List<String> tokens) {
parse(tokens);
}
public Relation(int low, int high) {
this.low = low;
this.high = high;
}
/**
* Sets the divisor for a modulo operation (defaults to 1).
*
* @param mod an <code>int</code> value
*/
public void setMod(int mod) {
this.mod = mod;
}
/**
* Negates the return value of the relation (defaults to false).
*
* @param value a <code>boolean</code> value
*/
public void setNegated(boolean value) {
this.negated = value;
}
/**
* Determines whether this relation only matches integers
* (defaults to true).
*
* @param value a <code>boolean</code> value
*/
public void setInteger(boolean value) {
this.integer = value;
}
/**
* Returns true if the given number matches this relation.
*
* @param number a <code>double</code> value
* @return a <code>boolean</code> value
*/
public boolean matches(double number) {
double value = (mod == 1) ? number : number % mod;
if (integer && value != (int) value) {
return false;
}
return (low <= value && value <= high) != negated;
}
public String toString() {
String result = new String("n ");
if (mod != 1) {
result += "mod " + Integer.toString(mod) + " ";
}
if (low == high) {
result += "is ";
if (negated) {
result += "not ";
}
result += Integer.toString(low);
} else {
if (negated) {
result += "not ";
}
if (!integer) {
result += "with";
}
result += "in " + Integer.toString(low)
+ ".." + Integer.toString(high);
}
return result;
}
/**
* Parses a list of string tokens.
*
* @param input a list of string tokens
*/
private void parse(List<String> input) {
String token = input.remove(0);
if ("n".equals(token)) {
token = input.remove(0);
} else {
throw new IllegalArgumentException("Relation must start with 'n'.");
}
if ("mod".equals(token)) {
mod = Integer.parseInt(input.remove(0));
token = input.remove(0);
}
if ("not".equals(token)) {
negated = true;
token = input.remove(0);
}
if ("is".equals(token)) {
token = input.remove(0);
if ("not".equals(token)) {
negated = true;
token = input.remove(0);
}
low = high = Integer.parseInt(token);
} else {
if ("within".equals(token)) {
integer = false;
}
low = Integer.parseInt(input.remove(0));
high = Integer.parseInt(input.remove(0));
}
}
}

View File

@ -0,0 +1,120 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
/**
* A rule consists of any number of relations combined with "and" and
* "or" operators. The "and" operator binds more strongly, and there
* are no grouping features.
*/
public class Rule {
List<List<Relation>> conditions = new ArrayList<List<Relation>>();
public Rule(String input) {
parse(input);
}
/**
* Adds a list of relations combined with the "and" operator.
*
* @param condition a list of relations combined with the "and" operator
*/
public void add(List<Relation> condition) {
conditions.add(condition);
}
/**
* Returns true if this rule matches the given number.
*
* @param number a <code>double</code> value
* @return a <code>boolean</code> value
*/
public boolean matches(double number) {
outer: for (List<Relation> andCondition : conditions) {
for (Relation relation : andCondition) {
if (!relation.matches(number)) {
continue outer;
}
}
return true;
}
return false;
}
/**
* Parses a string.
*
* @param input a <code>String</code> value
*/
public void parse(String input) {
StringTokenizer st = new StringTokenizer(input.toLowerCase(Locale.US), " .");
List<String> tokens = new ArrayList<String>();
while (st.hasMoreTokens()) {
String token = st.nextToken();
if ("or".equals(token)) {
conditions.add(parseCondition(tokens));
tokens.clear();
} else {
tokens.add(token);
}
}
conditions.add(parseCondition(tokens));
}
private List<Relation> parseCondition(List<String> input) {
List<String> tokens = new ArrayList<String>();
List<Relation> result = new ArrayList<Relation>();
for (String token : input) {
if ("and".equals(token)) {
result.add(new Relation(tokens));
tokens.clear();
} else {
tokens.add(token);
}
}
result.add(new Relation(tokens));
return result;
}
public String toString() {
String result = new String();
for (List<Relation> andCondition : conditions) {
String condition = new String();
for (Relation relation : andCondition) {
condition += " and " + relation.toString();
}
result += " or " + condition.substring(5);
}
return result.substring(4);
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (C) 2002-2010 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
/**
* Number optimized for languages that distinguish place the numbers 0
* and 1 in category one, and all others in category other.
*/
public class ZeroOneNumberRule implements Number {
public Category getCategory(double input) {
if (input == 0 || input == 1) {
return Category.one;
} else {
return Category.other;
}
}
public int getIndex(double input) {
if (input == 0 || input == 1) {
return 0;
} else {
return 1;
}
}
}

View File

@ -0,0 +1,118 @@
/**
* Copyright (C) 2002-2007 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.i18n;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import net.sf.freecol.client.gui.i18n.Number.Category;
import net.sf.freecol.util.test.FreeColTestCase;
public class CLDRTest extends FreeColTestCase {
public void testRuleParsing() {
List<String> tokens = new ArrayList<String>();
Rule rule = new Rule("n mod 10 in 2..4 and n mod 100 not in 12..14");
assertTrue(rule.matches(2));
assertTrue(rule.matches(102));
assertTrue(rule.matches(103));
assertFalse(rule.matches(1));
assertFalse(rule.matches(5));
assertFalse(rule.matches(112));
DefaultNumberRule arabic = new DefaultNumberRule();
arabic.addRule(Category.zero, "n is 0");
arabic.addRule(Category.one, "n is 1");
arabic.addRule(Category.two, "n is 2");
arabic.addRule(Category.few, "N Mod 100 in 3.. 10");
arabic.addRule(Category.many, "n MOD 100 in 11 ..99");
assertEquals(Category.zero, arabic.getCategory(0));
assertEquals(Category.one, arabic.getCategory(1));
assertEquals(Category.two, arabic.getCategory(2));
assertEquals(Category.few, arabic.getCategory(3));
assertEquals(Category.few, arabic.getCategory(7));
assertEquals(Category.few, arabic.getCategory(10));
assertEquals(Category.many, arabic.getCategory(11));
assertEquals(Category.many, arabic.getCategory(99));
assertEquals(Category.many, arabic.getCategory(2345));
}
public void testPlurals() {
FileInputStream in = null;
File inputFile = new File("data/strings/plurals.xml");
assertTrue(inputFile.exists());
try {
in = new FileInputStream(inputFile);
} catch(Exception e) {
fail("Failed to open input stream.");
}
NumberRules numberRules = new NumberRules(in);
try {
in.close();
} catch(Exception e) {
fail("Failed to close input stream.");
}
assertNotNull(numberRules.getNumberForLanguage("az"));
assertTrue(numberRules.getNumberForLanguage("az") instanceof OtherNumberRule);
assertNotNull(numberRules.getNumberForLanguage("ko"));
assertTrue(numberRules.getNumberForLanguage("ko") instanceof OtherNumberRule);
assertNotNull(numberRules.getNumberForLanguage("th"));
assertTrue(numberRules.getNumberForLanguage("th") instanceof OtherNumberRule);
assertNotNull(numberRules.getNumberForLanguage("en"));
assertTrue(numberRules.getNumberForLanguage("en") instanceof PluralNumberRule);
assertNotNull(numberRules.getNumberForLanguage("it"));
assertTrue(numberRules.getNumberForLanguage("it") instanceof PluralNumberRule);
assertNotNull(numberRules.getNumberForLanguage("pt"));
assertTrue(numberRules.getNumberForLanguage("pt") instanceof PluralNumberRule);
assertNotNull(numberRules.getNumberForLanguage("ak"));
assertTrue(numberRules.getNumberForLanguage("ak") instanceof ZeroOneNumberRule);
assertNotNull(numberRules.getNumberForLanguage("hi"));
assertTrue(numberRules.getNumberForLanguage("hi") instanceof ZeroOneNumberRule);
assertNotNull(numberRules.getNumberForLanguage("wa"));
assertTrue(numberRules.getNumberForLanguage("wa") instanceof ZeroOneNumberRule);
assertNotNull(numberRules.getNumberForLanguage("ga"));
assertTrue(numberRules.getNumberForLanguage("ga") instanceof DualNumberRule);
assertNotNull(numberRules.getNumberForLanguage("smi"));
assertTrue(numberRules.getNumberForLanguage("smi") instanceof DualNumberRule);
assertNotNull(numberRules.getNumberForLanguage("sms"));
assertTrue(numberRules.getNumberForLanguage("sms") instanceof DualNumberRule);
}
}

View File

@ -36,11 +36,11 @@ public class MessagesTest extends FreeColTestCase {
public void testMessageString() {
assertEquals("Press enter in order to end the turn.", Messages.message("infoPanel.endTurnPanel.text"));
assertEquals("Press enter in order to end the turn.", Messages.message("infoPanel.endTurnPanel.text"));
assertEquals("Trade Advisor", Messages.message("reportTradeAction.name"));
// With parameters
assertEquals("Score: %score% | Gold: %gold% | Tax: %tax%% | Year: %year%",
assertEquals("Score: %score% | Gold: %gold% | Tax: %tax%% | Year: %year%",
Messages.message("menuBar.statusLine"));
// Long String
@ -53,7 +53,7 @@ public class MessagesTest extends FreeColTestCase {
}
public void testMessageStringVarargs() {
try {
Messages.message(null);
fail("We should never get here");
@ -64,13 +64,13 @@ public class MessagesTest extends FreeColTestCase {
assertEquals("Trade Advisor", Messages.message("reportTradeAction.name"));
// With parameters for "Gold: %gold% | Tax: %tax%% | Year: %year%"
assertEquals("Score: 1050 | Gold: silver | Tax: 13% | Year: %year%",
assertEquals("Score: 1050 | Gold: silver | Tax: 13% | Year: %year%",
Messages.message("menuBar.statusLine", "%score%", "1050", "%gold%", "silver", "%tax%", "13"));
// Long String
assertEquals("Food is necessary to feed your colonists and to breed horses. "
+ "A new colonist is born whenever a colony has 200 units of food or more.", Messages.message(
"model.goods.food.description"));
+ "A new colonist is born whenever a colony has 200 units of food or more.",
Messages.message("model.goods.food.description"));
try {
Messages.message("menuBar.statusLine", "%tax%");
@ -79,11 +79,11 @@ public class MessagesTest extends FreeColTestCase {
// Expected
}
// Message not found
assertEquals(noSuchKey, Messages.message(noSuchKey));
assertEquals(noSuchKey, Messages.message(noSuchKey,
assertEquals(noSuchKey, Messages.message(noSuchKey,
"%gold%", "silver", "%tax%", "13"));
}
@ -96,14 +96,14 @@ public class MessagesTest extends FreeColTestCase {
assertEquals("Handelsberater", Messages.message("reportTradeAction.name"));
}
// Tests if messages with special chars (like $) are well processed
public void testMessageWithSpecialChars(){
String errMsg = "Error setting up test.";
String expected = "You establish the colony of %colony%.";
String message = Messages.message("model.history.FOUND_COLONY");
assertEquals(errMsg, expected, message);
String colNameWithSpecialChars="$specialColName\\";
errMsg = "Wrong message";
expected = "You establish the colony of $specialColName\\.";