| package org.unicode.cldr.unittest; |
| |
| import com.google.common.collect.ImmutableSet; |
| import com.ibm.icu.dev.test.TestFmwk; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import java.util.stream.Collectors; |
| import org.unicode.cldr.test.ExampleGenerator; |
| import org.unicode.cldr.test.ExampleGenerator.UnitLength; |
| import org.unicode.cldr.util.CLDRConfig; |
| import org.unicode.cldr.util.CLDRFile; |
| import org.unicode.cldr.util.CldrUtility; |
| import org.unicode.cldr.util.Factory; |
| import org.unicode.cldr.util.GrammarInfo; |
| import org.unicode.cldr.util.GrammarInfo.CaseValues; |
| import org.unicode.cldr.util.GrammarInfo.GrammaticalFeature; |
| import org.unicode.cldr.util.GrammarInfo.GrammaticalScope; |
| import org.unicode.cldr.util.GrammarInfo.GrammaticalTarget; |
| import org.unicode.cldr.util.Pair; |
| import org.unicode.cldr.util.PathStarrer; |
| import org.unicode.cldr.util.SupplementalDataInfo; |
| import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo; |
| import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo.Count; |
| import org.unicode.cldr.util.SupplementalDataInfo.PluralType; |
| import org.unicode.cldr.util.UnitPathType; |
| import org.unicode.cldr.util.With; |
| |
| public class TestExampleGenerator extends TestFmwk { |
| |
| boolean showTranslationPaths = |
| CldrUtility.getProperty("TestExampleGenerator:showTranslationPaths", false); |
| |
| private static final SupplementalDataInfo SDI = SupplementalDataInfo.getInstance(); |
| CLDRConfig info = CLDRConfig.getInstance(); |
| |
| public static void main(String[] args) { |
| new TestExampleGenerator().run(args); |
| } |
| |
| public void testCurrency() { |
| String[][] tests = { |
| { |
| "fr", |
| "one", |
| "〖❬1,23 ❭value-one〗〖❬0,00 ❭value-one〗", |
| "〖❬1,23❭_❬dollar des États-Unis❭〗〖❬1,23❭_❬euro❭〗〖❬0,00❭_❬dollar des États-Unis❭〗〖❬0,00❭_❬euro❭〗" |
| }, |
| { |
| "fr", |
| "other", |
| "〖❬2,34 ❭value-other〗〖❬3,45 ❭value-other〗", |
| "〖❬2,34❭_❬dollars des États-Unis❭〗〖❬2,34❭_❬euros❭〗〖❬3,45❭_❬dollars des États-Unis❭〗〖❬3,45❭_❬euros❭〗" |
| }, |
| {"en", "one", "〖❬1 ❭Bermudan dollar〗", "〖❬1❭ ❬US dollar❭〗〖❬1❭ ❬euro❭〗"}, |
| { |
| "en", |
| "other", |
| "〖❬1.23 ❭Bermudan dollars〗〖❬0.00 ❭Bermudan dollars〗", |
| "〖❬1.23❭ ❬US dollars❭〗〖❬1.23❭ ❬euros❭〗〖❬0.00❭ ❬US dollars❭〗〖❬0.00❭ ❬euros❭〗" |
| }, |
| }; |
| String sampleCurrencyPatternPrefix = |
| "//ldml/numbers/currencyFormats[@numberSystem=\"latn\"]/unitPattern[@count=\""; |
| String sampleCurrencyPrefix = |
| "//ldml/numbers/currencies/currency[@type=\"BMD\"]/displayName[@count=\""; |
| String sampleTemplateSuffix = "\"]"; |
| |
| for (String[] row : tests) { |
| ExampleGenerator exampleGenerator = getExampleGenerator(row[0]); |
| String value = "value-" + row[1]; |
| |
| String path = sampleCurrencyPrefix + row[1] + sampleTemplateSuffix; |
| String result = |
| ExampleGenerator.simplify(exampleGenerator.getExampleHtml(path, value), false); |
| assertEquals(row[0] + "-" + row[1] + "-BMD", row[2], result); |
| |
| value = "{0}_{1}"; |
| path = sampleCurrencyPatternPrefix + row[1] + sampleTemplateSuffix; |
| result = ExampleGenerator.simplify(exampleGenerator.getExampleHtml(path, value), false); |
| assertEquals(row[0] + "-" + row[1] + "-pat", row[3], result); |
| } |
| } |
| |
| /** |
| * Only add to this if the example should NEVER appear. <br> |
| * WARNING - do not disable the test by putting in too broad a match. Make sure the paths are |
| * reasonably granular. |
| */ |
| static final Set<String> DELIBERATE_EXCLUDED_EXAMPLES = |
| ImmutableSet.of( |
| "//ldml/layout/orientation/characterOrder", |
| "//ldml/layout/orientation/lineOrder", |
| "//ldml/characters/moreInformation", |
| "//ldml/numbers/symbols[@numberSystem=\"([^\"]*+)\"]/infinity", |
| "//ldml/numbers/symbols[@numberSystem=\"([^\"]*+)\"]/list", |
| "//ldml/numbers/symbols[@numberSystem=\"([^\"]*+)\"]/nan", |
| "//ldml/numbers/currencies/currency[@type=\"([^\"]*+)\"]/displayName", |
| "//ldml/localeDisplayNames/measurementSystemNames/measurementSystemName[@type=\"([^\"]*+)\"]", |
| // old format |
| "//ldml/numbers/symbols/infinity", |
| "//ldml/numbers/symbols/list", |
| "//ldml/numbers/symbols/nan", |
| "//ldml/posix/messages/nostr", |
| "//ldml/posix/messages/yesstr", |
| "//ldml/contextTransforms/contextTransformUsage[@type=\"([^\"]*+)\"]/contextTransform[@type=\"([^\"]*+)\"]", |
| "//ldml/characters/exemplarCharacters", |
| "//ldml/characters/exemplarCharacters[@type=\"([^\"]*+)\"]", |
| "//ldml/characters/parseLenients.*", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/months/monthContext[@type=\"([^\"]*+)\"]/monthWidth[@type=\"([^\"]*+)\"]/month[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/days/dayContext[@type=\"([^\"]*+)\"]/dayWidth[@type=\"([^\"]*+)\"]/day[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/quarters/quarterContext[@type=\"([^\"]*+)\"]/quarterWidth[@type=\"([^\"]*+)\"]/quarter[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/fields/field[@type=\"([^\"]*+)\"]/displayName", |
| "//ldml/dates/fields/field[@type=\"([^\"]*+)\"]/relative[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/fields/field[@type=\"([^\"]*+)\"]/relativeTime[@type=\"([^\"]*+)\"]/relativeTimePattern[@count=\"([^\"]*+)\"]", |
| "//ldml/dates/fields/field[@type=\"([^\"]*+)\"]/relativePeriod", |
| "//ldml/dates/fields/field[@type=\"([^\"]*+)\"]/displayName[@alt=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/cyclicNameSets/cyclicNameSet[@type=\"([^\"]*+)\"]/cyclicNameContext[@type=\"([^\"]*+)\"]/cyclicNameWidth[@type=\"([^\"]*+)\"]/cyclicName[@type=\"([^\"]*+)\"]", |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"([^\"]*+)\"]", |
| "//ldml/numbers/minimalPairs/ordinalMinimalPairs[@ordinal=\"([^\"]*+)\"]", |
| "//ldml/characters/parseLenients[@scope=\"([^\"]*+)\"][@level=\"([^\"]*+)\"]/parseLenient[@sample=\"([^\"]*+)\"]"); |
| // Only add to above if the example should NEVER appear. |
| |
| /** |
| * Add to this if the example SHOULD appear, but we don't have it yet. <br> |
| * TODO Add later |
| */ |
| static final Set<String> TEMPORARY_EXCLUDED_EXAMPLES = |
| ImmutableSet.of( |
| "//ldml/numbers/currencyFormats/currencySpacing/beforeCurrency/currencyMatch", |
| "//ldml/numbers/currencyFormats/currencySpacing/beforeCurrency/surroundingMatch", |
| "//ldml/numbers/currencyFormats/currencySpacing/beforeCurrency/insertBetween", |
| "//ldml/numbers/currencyFormats/currencySpacing/afterCurrency/currencyMatch", |
| "//ldml/numbers/currencyFormats/currencySpacing/afterCurrency/surroundingMatch", |
| "//ldml/numbers/currencyFormats/currencySpacing/afterCurrency/insertBetween", |
| "//ldml/numbers/currencyFormats/currencyPatternAppendISO", // TODO see |
| // CLDR-14831 |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencySpacing/beforeCurrency/currencyMatch", |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencySpacing/beforeCurrency/surroundingMatch", |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencySpacing/beforeCurrency/insertBetween", |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencySpacing/afterCurrency/currencyMatch", |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencySpacing/afterCurrency/surroundingMatch", |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencySpacing/afterCurrency/insertBetween", |
| "//ldml/numbers/currencyFormats[@numberSystem=\"([^\"]*+)\"]/currencyPatternAppendISO", // TODO see CLDR-14831 |
| "//ldml/localeDisplayNames/variants/variant[@type=\"([^\"]*+)\"]", |
| "//ldml/localeDisplayNames/keys/key[@type=\"([^\"]*+)\"]", |
| "//ldml/localeDisplayNames/types/type[@key=\"([^\"]*+)\"][@type=\"([^\"]*+)\"]", |
| "//ldml/localeDisplayNames/types/type[@key=\"([^\"]*+)\"][@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/eras/eraNames/era[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/eras/eraAbbr/era[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/eras/eraNarrow/era[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateFormats/dateFormatLength[@type=\"([^\"]*+)\"]/dateFormat[@type=\"([^\"]*+)\"]/datetimeSkeleton", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/timeFormats/timeFormatLength[@type=\"([^\"]*+)\"]/timeFormat[@type=\"([^\"]*+)\"]/datetimeSkeleton", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateFormats/dateFormatLength[@type=\"([^\"]*+)\"]/datetimeSkeleton", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/timeFormats/timeFormatLength[@type=\"([^\"]*+)\"]/datetimeSkeleton", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateTimeFormats/appendItems/appendItem[@request=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateTimeFormats/intervalFormats/intervalFormatFallback", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateTimeFormats/intervalFormats/intervalFormatItem[@id=\"([^\"]*+)\"]/greatestDifference[@id=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/eras/eraNames/era[@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/eras/eraAbbr/era[@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/eras/eraNarrow/era[@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/months/monthContext[@type=\"([^\"]*+)\"]/monthWidth[@type=\"([^\"]*+)\"]/month[@type=\"([^\"]*+)\"][@yeartype=\"([^\"]*+)\"]", |
| "//ldml/dates/timeZoneNames/gmtZeroFormat", |
| "//ldml/numbers/minimumGroupingDigits", |
| "//ldml/numbers/symbols/timeSeparator", |
| "//ldml/numbers/symbols[@numberSystem=\"([^\"]*+)\"]/timeSeparator", |
| "//ldml/units/unitLength[@type=\"([^\"]*+)\"]/unit[@type=\"([^\"]*+)\"]/displayName", |
| "//ldml/units/unitLength[@type=\"([^\"]*+)\"]/unit[@type=\"([^\"]*+)\"]/perUnitPattern", |
| "//ldml/units/unitLength[@type=\"([^\"]*+)\"]/coordinateUnit/coordinateUnitPattern[@type=\"([^\"]*+)\"]", |
| "//ldml/units/unitLength[@type=\"([^\"]*+)\"]/coordinateUnit/displayName", |
| "//ldml/characterLabels/characterLabelPattern[@type=\"([^\"]*+)\"]", |
| "//ldml/characterLabels/characterLabelPattern[@type=\"([^\"]*+)\"][@count=\"([^\"]*+)\"]", |
| "//ldml/characterLabels/characterLabel[@type=\"([^\"]*+)\"]", |
| "//ldml/typographicNames/axisName[@type=\"([^\"]*+)\"]", |
| "//ldml/typographicNames/styleName[@type=\"([^\"]*+)\"][@subtype=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", |
| "//ldml/typographicNames/styleName[@type=\"([^\"]*+)\"][@subtype=\"([^\"]*+)\"]", |
| "//ldml/typographicNames/featureName[@type=\"([^\"]*+)\"]", |
| "//ldml/localeDisplayNames/subdivisions/subdivision[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/long/standard", // Error: |
| // (TestExampleGenerator.java:245) No background: <Coordinated Universal Time> |
| // 〖Coordinated Universal Time〗 |
| "//ldml/personNames/nameOrderLocales[@order=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/foreignSpaceReplacement[@xml:space=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/foreignSpaceReplacement[@xml:space=\"([^\"]*+)\"]", // TODO |
| "//ldml/personNames/foreignSpaceReplacement[@alt=\"([^\"]*+)\"]", |
| "//ldml/personNames/foreignSpaceReplacement", // TODO CLDR-15384 |
| "//ldml/personNames/nativeSpaceReplacement[@xml:space=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/nativeSpaceReplacement[@xml:space=\"([^\"]*+)\"]", // TODO |
| "//ldml/personNames/nativeSpaceReplacement[@alt=\"([^\"]*+)\"]", |
| "//ldml/personNames/nativeSpaceReplacement", // TODO CLDR-15384 |
| "//ldml/personNames/initialPattern[@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/initialPattern[@type=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/personName[@order=\"([^\"]*+)\"][@length=\"([^\"]*+)\"][@usage=\"([^\"]*+)\"][@formality=\"([^\"]*+)\"]/namePattern[@alt=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/sampleName[@item=\"([^\"]*+)\"]/nameField[@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/sampleName[@item=\"([^\"]*+)\"]/nameField[@type=\"([^\"]*+)\"]", // TODO CLDR-15384 |
| "//ldml/personNames/parameterDefault[@parameter=\"([^\"]*+)\"]" // TODO |
| // CLDR-15384 |
| ); |
| // Add to above if the example SHOULD appear, but we don't have it yet. TODO Add later |
| |
| /** |
| * Only add to this if the background should NEVER appear. <br> |
| * The background is used when the element is used as part of another format. <br> |
| * WARNING - do not disable the test by putting in too broad a match. Make sure the paths are |
| * reasonably granular. |
| */ |
| static final Set<String> DELIBERATE_OK_TO_MISS_BACKGROUND = |
| ImmutableSet.of( |
| "//ldml/numbers/defaultNumberingSystem", |
| "//ldml/numbers/otherNumberingSystems/native", |
| // TODO fix formatting |
| "//ldml/characters/exemplarCharacters", |
| "//ldml/characters/exemplarCharacters[@type=\"([^\"]*+)\"]", |
| // TODO Add background |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/timeFormats/timeFormatLength[@type=\"([^\"]*+)\"]/timeFormat[@type=\"([^\"]*+)\"]/pattern[@type=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", // CLDR-16606 |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateTimeFormats/availableFormats/dateFormatItem[@id=\"([^\"]*+)\"][@alt=\"([^\"]*+)\"]", // CLDR-16606 |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateFormats/dateFormatLength[@type=\"([^\"]*+)\"]/dateFormat[@type=\"([^\"]*+)\"]/pattern[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/timeFormats/timeFormatLength[@type=\"([^\"]*+)\"]/timeFormat[@type=\"([^\"]*+)\"]/pattern[@type=\"([^\"]*+)\"]", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateTimeFormats/availableFormats/dateFormatItem[@id=\"([^\"]*+)\"]", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/exemplarCity", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/exemplarCity[@alt=\"([^\"]*+)\"]", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/long/daylight", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/short/generic", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/short/standard", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/short/daylight", |
| "//ldml/dates/timeZoneNames/metazone[@type=\"([^\"]*+)\"]/long/generic", |
| "//ldml/dates/timeZoneNames/metazone[@type=\"([^\"]*+)\"]/long/standard", |
| "//ldml/dates/timeZoneNames/metazone[@type=\"([^\"]*+)\"]/long/daylight", |
| "//ldml/units/durationUnit[@type=\"([^\"]*+)\"]/durationUnitPattern"); |
| // Only add to above if the background should NEVER appear. |
| |
| /** |
| * Add to this if the background SHOULD appear, but we don't have them yet. <br> |
| * The background is used when the element is used as part of another format. <br> |
| * TODO Add later |
| */ |
| static final Set<String> TEMPORARY_OK_TO_MISS_BACKGROUND = |
| ImmutableSet.of( |
| "//ldml/numbers/defaultNumberingSystem", |
| "//ldml/dates/calendars/calendar[@type=\"([^\"]*+)\"]/dateTimeFormats/availableFormats/dateFormatItem[@id=\"([^\"]*+)\"][@count=\"([^\"]*+)\"]", |
| "//ldml/dates/timeZoneNames/zone[@type=\"([^\"]*+)\"]/long/standard", |
| "//ldml/dates/timeZoneNames/metazone[@type=\"([^\"]*+)\"]/short/generic", |
| "//ldml/dates/timeZoneNames/metazone[@type=\"([^\"]*+)\"]/short/standard", |
| "//ldml/dates/timeZoneNames/metazone[@type=\"([^\"]*+)\"]/short/daylight", |
| "//ldml/personNames/personName[@order=\"([^\"]*+)\"][@length=\"([^\"]*+)\"][@formality=\"([^\"]*+)\"]/namePattern", |
| "//ldml/personNames/personName[@order=\"([^\"]*+)\"][@length=\"([^\"]*+)\"][@usage=\"([^\"]*+)\"][@formality=\"([^\"]*+)\"]/namePattern"); // CLDR-15384 |
| // Add to above if the background SHOULD appear, but we don't have them yet. TODO Add later |
| |
| public void TestAllPaths() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("en"); |
| PathStarrer ps = new PathStarrer(); |
| Set<String> seen = new HashSet<>(); |
| CLDRFile cldrFile = exampleGenerator.getCldrFile(); |
| TreeSet<String> target = new TreeSet<>(cldrFile.getComparator()); |
| cldrFile.fullIterable().forEach(target::add); |
| for (String path : target) { |
| String plainStarred = ps.set(path); |
| String value = cldrFile.getStringValue(path); |
| if (value == null |
| || path.endsWith("/alias") |
| || path.startsWith("//ldml/identity") |
| || DELIBERATE_EXCLUDED_EXAMPLES.contains(plainStarred)) { |
| continue; |
| } |
| if (TEMPORARY_EXCLUDED_EXAMPLES.contains(plainStarred)) { |
| if (logKnownIssue( |
| "Cldrbug:6342", |
| "Need an example for each path used in context: " + plainStarred)) { |
| continue; |
| } |
| continue; |
| } |
| String example = exampleGenerator.getExampleHtml(path, value); |
| String javaEscapedStarred = "\"" + plainStarred.replace("\"", "\\\"") + "\","; |
| if (example == null) { |
| if (!seen.contains(javaEscapedStarred)) { |
| errln("No example:\t<" + value + ">\t" + javaEscapedStarred); |
| } |
| } else { |
| String simplified = ExampleGenerator.simplify(example, false); |
| |
| if (simplified.contains("null")) { |
| if (true || !seen.contains(javaEscapedStarred)) { |
| // debug |
| exampleGenerator.getExampleHtml(path, value); |
| ExampleGenerator.simplify(example, false); |
| |
| errln( |
| "'null' in message:\t<" |
| + value |
| + ">\t" |
| + simplified |
| + "\t" |
| + javaEscapedStarred); |
| // String example2 = |
| // exampleGenerator.getExampleHtml(path, value); // for |
| // debugging |
| } |
| } else if (!simplified.startsWith("〖")) { |
| if (!seen.contains(javaEscapedStarred)) { |
| errln( |
| "Funny HTML:\t<" |
| + value |
| + ">\t" |
| + simplified |
| + "\t" |
| + javaEscapedStarred); |
| } |
| } else if (!simplified.contains("❬") |
| && !DELIBERATE_OK_TO_MISS_BACKGROUND.contains(plainStarred)) { |
| if (!seen.contains(javaEscapedStarred)) { |
| |
| if (TEMPORARY_OK_TO_MISS_BACKGROUND.contains(plainStarred) |
| && logKnownIssue( |
| "Cldrbug:6342", |
| "Make sure that background appears: " |
| + simplified |
| + "; " |
| + plainStarred)) { |
| continue; |
| } |
| |
| errln( |
| "No background:\t<" |
| + value |
| + ">\t" |
| + simplified |
| + "\t" |
| + javaEscapedStarred); |
| } |
| } |
| } |
| seen.add(javaEscapedStarred); |
| } |
| } |
| |
| public void TestUnits() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("en"); |
| String staticMeterExample = |
| "〖1 meter ≡ 1,000 millimeter〗〖1 meter ≈ 1.0936 yard (US/UK)〗〖1 meter ≡ 1/1000 kilometer〗〖1 meter ≈ 621.37×10ˆ-6 mile (US/UK)〗"; |
| String staticMeterExampleJp = |
| "〖1 meter ≡ 1,000 millimeter〗〖1 meter ≡ 3.025 jo-jp (JP)〗〖1 meter ≈ 1.0936 yard (US/UK)〗〖1 meter ≈ 0.0023341 ri-jp (JP)〗〖1 meter ≡ 1/1000 kilometer〗〖1 meter ≈ 621.37×10ˆ-6 mile (US/UK)〗"; |
| String staticMeterExampleRi = |
| "〖1 ri-jp (JP) ≡ 1,296 jo-jp (JP)〗〖1 ri-jp (JP) ≈ 468.54 yard (US/UK)〗〖1 ri-jp (JP) ≈ 428.43 meter〗〖1 ri-jp (JP) ≈ 0.42843 kilometer〗〖1 ri-jp (JP) ≈ 0.26621 mile (US/UK)〗"; |
| |
| checkValue( |
| "Length m", |
| staticMeterExample, |
| exampleGenerator, |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-meter\"]/displayName"); |
| checkValue( |
| "Duration hm", |
| "〖5:37〗", |
| exampleGenerator, |
| "//ldml/units/durationUnit[@type=\"hm\"]/durationUnitPattern"); |
| checkValue( |
| "Length m", |
| "〖❬1❭ meter〗〖〗" + staticMeterExample, |
| exampleGenerator, |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"one\"]"); |
| checkValue( |
| "Length m", |
| "〖❬1.5❭ meters〗〖〗" + staticMeterExample, |
| exampleGenerator, |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"other\"]"); |
| checkValue( |
| "Length m", |
| "〖❬1.5❭ m〗〖〗" + staticMeterExample, |
| exampleGenerator, |
| "//ldml/units/unitLength[@type=\"short\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"other\"]"); |
| checkValue( |
| "Length m", |
| "〖❬1.5❭m〗〖〗" + staticMeterExample, |
| exampleGenerator, |
| "//ldml/units/unitLength[@type=\"narrow\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"other\"]"); |
| |
| // The following are to ensure that we properly generate an example when we have a |
| // non-winning value |
| checkValue( |
| "Length m", |
| "〖❬1.5❭ badmeter〗〖〗" + staticMeterExample, |
| exampleGenerator, |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"other\"]", |
| "{0} badmeter"); |
| |
| ExampleGenerator exampleGeneratorDe = getExampleGenerator("de"); |
| checkValue( |
| "Length m", |
| "〖❬1,5❭ badmeter〗〖❬Anstatt 1,5❭ badmeter❬ …❭〗〖❌ ❬… für 1,5❭ badmeter❬ …❭〗〖〗" |
| + staticMeterExample, |
| exampleGeneratorDe, |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"other\"][@case=\"genitive\"]", |
| "{0} badmeter"); |
| |
| ExampleGenerator exampleGeneratorJa = getExampleGenerator("ja"); |
| checkValue( |
| "Length m", |
| "〖❬1.5❭m〗〖〗" + staticMeterExampleJp, |
| exampleGeneratorJa, |
| "//ldml/units/unitLength[@type=\"narrow\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"other\"]"); |
| checkValue( |
| "Length ri", |
| "〖❬1.5❭ 里〗〖〗" + staticMeterExampleRi, |
| exampleGeneratorJa, |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-ri-jp\"]/unitPattern[@count=\"other\"]"); |
| } |
| |
| /** |
| * Check that the expected exampleGenerator example is produced for the parameters, with the |
| * value coming from the file. |
| */ |
| private void checkValue( |
| String message, String expected, ExampleGenerator exampleGenerator, String path) { |
| checkValue(message, expected, exampleGenerator, path, null); |
| } |
| |
| /** Check that the expected exampleGenerator example is produced for the parameters */ |
| private void checkValue( |
| String message, |
| String expected, |
| ExampleGenerator exampleGenerator, |
| String path, |
| String value) { |
| final CLDRFile cldrFile = exampleGenerator.getCldrFile(); |
| value = value != null ? value : cldrFile.getStringValue(path); |
| String actual = exampleGenerator.getExampleHtml(path, value); |
| assertEquals( |
| cldrFile.getLocaleID() + ": " + message, |
| expected, |
| ExampleGenerator.simplify(actual, false)); |
| } |
| |
| public void TestCompoundUnit() { |
| String[][] tests = { |
| {"per", "LONG", "one", "〖❬1 meter❭ per ❬second❭〗"}, |
| {"per", "SHORT", "one", "〖❬1 m❭/❬sec❭〗"}, |
| {"per", "NARROW", "one", "〖❬1m❭/❬s❭〗"}, |
| {"per", "LONG", "other", "〖❬1.5 meters❭ per ❬second❭〗"}, |
| {"per", "SHORT", "other", "〖❬1.5 m❭/❬sec❭〗"}, |
| {"per", "NARROW", "other", "〖❬1.5m❭/❬s❭〗"}, |
| {"times", "LONG", "one", "〖❬1 newton❭-❬meter❭〗"}, |
| {"times", "SHORT", "one", "〖❬1 N❭⋅❬m❭〗"}, |
| {"times", "NARROW", "one", "〖❬1N❭⋅❬m❭〗"}, |
| {"times", "LONG", "other", "〖❬1.5 newton❭-❬meters❭〗"}, |
| {"times", "SHORT", "other", "〖❬1.5 N❭⋅❬m❭〗"}, |
| {"times", "NARROW", "other", "〖❬1.5N❭⋅❬m❭〗"}, |
| }; |
| checkCompoundUnits("en", tests); |
| // reenable these after Arabic has meter translated |
| // String[][] tests2 = { |
| // {"LONG", "few", "〖❬1 meter❭ per ❬second❭〗"}, |
| // }; |
| // checkCompoundUnits("ar", tests2); |
| } |
| |
| private void checkCompoundUnits(String locale, String[][] tests) { |
| ExampleGenerator exampleGenerator = getExampleGenerator(locale); |
| for (String[] test : tests) { |
| String actual = |
| exampleGenerator.handleCompoundUnit( |
| UnitLength.valueOf(test[1]), test[0], Count.valueOf(test[2])); |
| assertEquals("CompoundUnit", test[3], ExampleGenerator.simplify(actual, true)); |
| } |
| } |
| |
| public void TestTranslationPaths() { |
| for (String locale : Arrays.asList("en", "el", "ru")) { |
| CLDRFile cldrFile = CLDRConfig.getInstance().getCldrFactory().make(locale, true); |
| ExampleGenerator exampleGenerator = getExampleGenerator(locale); |
| |
| for (UnitPathType pathType : UnitPathType.values()) { |
| for (String width : Arrays.asList("long", "short", "narrow")) { |
| if (pathType == UnitPathType.gender && !width.equals("long")) { |
| continue; |
| } |
| for (String unit : pathType.sampleShortUnitType) { |
| String path = |
| pathType.getTranslationPath( |
| cldrFile, width, unit, "one", "nominative", null); |
| String value = cldrFile.getStringValue(path); |
| if (value != null) { |
| String example = exampleGenerator.getExampleHtml(path, value); |
| if (assertNotNull(locale + "/" + path, example)) { |
| String simplified = ExampleGenerator.simplify(example, false); |
| if (showTranslationPaths) { |
| warnln( |
| locale |
| + ", " |
| + width |
| + ", " |
| + pathType.toString() |
| + " ==>" |
| + simplified); |
| } |
| } else { |
| // for debugging |
| example = exampleGenerator.getExampleHtml(path, value); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| public void TestCompoundUnit2() { |
| String[][] tests = { |
| {"de", "LONG", "other", "Quadrat{0}", "〖❬1,5 ❭Quadrat❬meter❭〗"}, |
| {"en", "SHORT", "one", "z{0}", "〖❬1 ❭z❬m❭〗"}, |
| {"en", "LONG", "other", "zetta{0}", "〖❬1.5 ❭zetta❬meters❭〗"}, |
| {"en", "SHORT", "one", "{0}²", "〖❬1 m❭²〗"}, |
| {"en", "LONG", "other", "square {0}", "〖❬1.5 ❭square ❬meters❭〗"}, |
| {"de", "SHORT", "one", "z{0}", "〖❬1 ❭z❬m❭〗"}, |
| {"de", "LONG", "other", "Zetta{0}", "〖❬1,5 ❭Zetta❬meter❭〗"}, |
| {"de", "SHORT", "one", "{0}²", "〖❬1 m❭²〗"}, |
| {"de", "LONG", "other", "Quadrat{0}", "〖❬1,5 ❭Quadrat❬meter❭〗"}, |
| }; |
| for (String[] test : tests) { |
| |
| ExampleGenerator exampleGenerator = getExampleGenerator(test[0]); |
| |
| String actual = |
| exampleGenerator.handleCompoundUnit1( |
| UnitLength.valueOf(test[1]), Count.valueOf(test[2]), test[3]); |
| assertEquals("CompoundUnit", test[4], ExampleGenerator.simplify(actual, true)); |
| } |
| } |
| |
| public void TestCompoundUnit3() { |
| final Factory cldrFactory = CLDRConfig.getInstance().getCldrFactory(); |
| String[][] tests = { |
| // locale, path, value, expected-example |
| { |
| "en", |
| "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1", |
| "LOCALE", |
| "〖square ❬meters❭〗" |
| }, // |
| { |
| "en", |
| "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"one\"]", |
| "LOCALE", |
| "〖❬1 ❭square ❬meter❭〗" |
| }, // |
| { |
| "en", |
| "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"other\"]", |
| "LOCALE", |
| "〖❬1.5 ❭square ❬meters❭〗" |
| }, // |
| { |
| "en", |
| "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1", |
| "LOCALE", |
| "〖❬m❭²〗" |
| }, |
| { |
| "en", |
| "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"one\"]", |
| "LOCALE", |
| "〖❬1m❭²〗" |
| }, |
| { |
| "en", |
| "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"other\"]", |
| "LOCALE", |
| "〖❬1.5m❭²〗" |
| }, |
| |
| // warning, french patterns has U+00A0 in them |
| { |
| "fr", |
| "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1", |
| "Square {0}", |
| "〖Square ❬mètres❭〗" |
| }, |
| { |
| "fr", |
| "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"one\"]", |
| "square {0}", |
| "〖❬1,5 ❭square ❬mètre❭〗" |
| }, |
| { |
| "fr", |
| "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"other\"]", |
| "squares {0}", |
| "〖❬3,5 ❭squares ❬mètres❭〗" |
| }, |
| { |
| "fr", |
| "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1", |
| "LOCALE", |
| "〖❬m❭²〗" |
| }, |
| { |
| "fr", |
| "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"one\"]", |
| "LOCALE", |
| "〖❬1,5m❭²〗" |
| }, |
| { |
| "fr", |
| "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"power2\"]/compoundUnitPattern1[@count=\"other\"]", |
| "LOCALE", |
| "〖❬3,5m❭²〗" |
| }, |
| }; |
| |
| int lineCount = 0; |
| for (String[] test : tests) { |
| |
| final String localeID = test[0]; |
| final String xpath = test[1]; |
| String value = test[2]; |
| String expected = test[3]; |
| |
| ExampleGenerator exampleGenerator = getExampleGenerator(localeID); |
| |
| if (value.equals("LOCALE")) { |
| value = cldrFactory.make(localeID, true).getStringValue(xpath); |
| } |
| String actual = exampleGenerator.getExampleHtml(xpath, value); |
| assertEquals( |
| ++lineCount + ") " + localeID + ", CompoundUnit3", |
| expected, |
| ExampleGenerator.simplify(actual, false)); |
| } |
| } |
| |
| HashMap<String, ExampleGenerator> ExampleGeneratorCache = new HashMap<>(); |
| |
| private ExampleGenerator getExampleGenerator(String locale) { |
| ExampleGenerator result = ExampleGeneratorCache.get(locale); |
| if (result == null) { |
| final CLDRFile nativeCldrFile = info.getCLDRFile(locale, true); |
| result = new ExampleGenerator(nativeCldrFile, info.getEnglish()); |
| ExampleGeneratorCache.put(locale, result); |
| } |
| return result; |
| } |
| |
| public void TestEllipsis() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("it"); |
| String[][] tests = { |
| {"initial", "〖…❬iappone❭〗"}, |
| {"medial", "〖❬Svizzer❭…❬iappone❭〗"}, |
| {"final", "〖❬Svizzer❭…〗"}, |
| {"word-initial", "〖… ❬Giappone❭〗"}, |
| {"word-medial", "〖❬Svizzera❭ … ❬Giappone❭〗"}, |
| {"word-final", "〖❬Svizzera❭ …〗"}, |
| }; |
| for (String[] pair : tests) { |
| checkValue( |
| exampleGenerator, |
| "//ldml/characters/ellipsis[@type=\"" + pair[0] + "\"]", |
| pair[1]); |
| } |
| } |
| |
| private void checkValue(ExampleGenerator exampleGenerator, String path, String expected) { |
| String value = exampleGenerator.getCldrFile().getStringValue(path); |
| String result = |
| ExampleGenerator.simplify(exampleGenerator.getExampleHtml(path, value), false); |
| assertEquals("Ellipsis", expected, result); |
| } |
| |
| public static String simplify(String exampleHtml) { |
| return ExampleGenerator.simplify(exampleHtml, false); |
| } |
| |
| public void TestClip() { |
| assertEquals("Clipping", "bc", ExampleGenerator.clip("abc", 1, 0)); |
| assertEquals("Clipping", "ab", ExampleGenerator.clip("abc", 0, 1)); |
| assertEquals( |
| "Clipping", "b\u0308c\u0308", ExampleGenerator.clip("a\u0308b\u0308c\u0308", 1, 0)); |
| assertEquals( |
| "Clipping", "a\u0308b\u0308", ExampleGenerator.clip("a\u0308b\u0308c\u0308", 0, 1)); |
| } |
| |
| public void TestPaths() { |
| showCldrFile(info.getEnglish()); |
| showCldrFile(info.getCLDRFile("fr", true)); |
| } |
| |
| public void TestMiscPatterns() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("it"); |
| checkValue( |
| "At least", |
| "〖≥❬99❭〗", |
| exampleGenerator, |
| "//ldml/numbers/miscPatterns[@numberSystem=\"latn\"]/pattern[@type=\"atLeast\"]"); |
| checkValue( |
| "Range", |
| "〖❬99❭-❬144❭〗", |
| exampleGenerator, |
| "//ldml/numbers/miscPatterns[@numberSystem=\"latn\"]/pattern[@type=\"range\"]"); |
| // String actual = exampleGenerator.getExampleHtml( |
| // "//ldml/numbers/miscPatterns[@type=\"arab\"]/pattern[@type=\"atLeast\"]", |
| // "at least {0}", Zoomed.IN); |
| // assertEquals("Invalid format", |
| // "<div class='cldr_example'>at least 99</div>", actual); |
| } |
| |
| public void TestPluralSamples() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("sv"); |
| String[][] tests = { |
| { |
| "//ldml/units/unitLength[@type=\"short\"]/unit[@type=\"length-centimeter\"]/unitPattern[@count=\"one\"]", |
| "Number should be one", |
| "〖❬1❭ cm〗〖❬Jag tror att 1❭ cm❬ är tillräckligt.❭〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/ordinalMinimalPairs[@ordinal=\"one\"]", |
| "Ordinal one", |
| "〖Ta ❬1❭:a svängen till höger〗〖❌ Ta ❬3❭:a svängen till höger〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/ordinalMinimalPairs[@ordinal=\"other\"]", |
| "Ordinal other", |
| "〖Ta ❬3❭:e svängen till höger〗〖❌ Ta ❬1❭:e svängen till höger〗" |
| }, |
| }; |
| for (String[] row : tests) { |
| String path = row[0]; |
| String message = row[1]; |
| String expected = row[2]; |
| checkValue(message, expected, exampleGenerator, path); |
| } |
| } |
| |
| public void TestLocaleDisplayPatterns() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("it"); |
| String actual = |
| exampleGenerator.getExampleHtml( |
| "//ldml/localeDisplayNames/localeDisplayPattern/localePattern", |
| "{0} [{1}]"); |
| assertEquals( |
| "localePattern example faulty", |
| "<div class='cldr_example'><span class='cldr_substituted'>uzbeco</span> [<span class='cldr_substituted'>Afghanistan</span>]</div>" |
| + "<div class='cldr_example'><span class='cldr_substituted'>uzbeco</span> [<span class='cldr_substituted'>arabo, Afghanistan</span>]</div>" |
| + "<div class='cldr_example'><span class='cldr_substituted'>uzbeco</span> [<span class='cldr_substituted'>arabo, Afghanistan, Cifre indo-arabe, Fuso orario: Ora Etiopia</span>]</div>", |
| actual); |
| actual = |
| exampleGenerator.getExampleHtml( |
| "//ldml/localeDisplayNames/localeDisplayPattern/localeSeparator", |
| "{0}. {1}"); |
| assertEquals( |
| "localeSeparator example faulty", |
| "<div class='cldr_example'><span class='cldr_substituted'>uzbeco (arabo</span>. <span class='cldr_substituted'>Afghanistan)</span></div>" |
| + "<div class='cldr_example'><span class='cldr_substituted'>uzbeco (arabo</span>. <span class='cldr_substituted'>Afghanistan</span>. <span class='cldr_substituted'>Cifre indo-arabe</span>. <span class='cldr_substituted'>Fuso orario: Ora Etiopia)</span></div>", |
| actual); |
| } |
| |
| public void TestCurrencyFormats() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("it"); |
| String actual = |
| simplify( |
| exampleGenerator.getExampleHtml( |
| "//ldml/numbers/currencyFormats[@numberSystem=\"latn\"]/currencyFormatLength/currencyFormat[@type=\"standard\"]/pattern[@type=\"standard\"]", |
| "¤ #0.00")); |
| assertEquals("Currency format example faulty", "〖€ ❬1295,00❭〗〖-€ ❬1295,00❭〗", actual); |
| } |
| |
| public void TestCurrencyFormatsWithContext() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("he"); |
| String actual = |
| simplify( |
| exampleGenerator.getExampleHtml( |
| "//ldml/numbers/currencyFormats[@numberSystem=\"latn\"]/currencyFormatLength/currencyFormat[@type=\"standard\"]/pattern[@type=\"standard\"]", |
| "#,##0.00 ¤;-#,##0.00 ¤")); |
| assertEquals( |
| "Currency format example faulty", |
| "【❬1,295❭.❬00❭ ₪〗【⃪❬1,295❭.❬00❭ ₪〗【-❬1,295❭.❬00❭ ₪〗【⃪-❬1,295❭.❬00❭ ₪〗【❬1,295❭.❬00❭ ILS〗【⃪❬1,295❭.❬00❭ ILS〗【-❬1,295❭.❬00❭ ILS〗【⃪-❬1,295❭.❬00❭ ILS〗", |
| actual); |
| } |
| |
| public void TestDateFormatsWithContext() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("ar"); |
| String actual = |
| simplify( |
| exampleGenerator.getExampleHtml( |
| "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateFormats/dateFormatLength[@type=\"short\"]/dateFormat[@type=\"standard\"]/pattern[@type=\"standard\"]", |
| "d/M/y")); |
| assertEquals("Currency format example faulty", "【٥/٩/١٩٩٩〗【⃪٥/٩/١٩٩٩〗", actual); |
| } |
| |
| public void TestDateTimeComboFormats() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("en"); |
| checkValue( |
| "DateTimeCombo long std", |
| "〖❬September 5, 1999❭, ❬1:25:59 PM Eastern Standard Time❭〗〖❬September 5, 1999❭, ❬1:25 PM❭〗〖❬September 5, 1999❭, ❬7:00 AM – 1:25 PM❭〗〖❬today❭, ❬7:00 AM – 1:25 PM❭〗", |
| exampleGenerator, |
| "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/dateTimeFormatLength[@type=\"long\"]/dateTimeFormat[@type=\"standard\"]/pattern[@type=\"standard\"]"); |
| checkValue( |
| "DateTimeCombo short std", |
| "〖❬9/5/99❭, ❬1:25:59 PM Eastern Standard Time❭〗〖❬9/5/99❭, ❬1:25 PM❭〗〖❬9/5/99❭, ❬7:00 AM – 1:25 PM❭〗〖❬today❭, ❬7:00 AM – 1:25 PM❭〗", |
| exampleGenerator, |
| "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/dateTimeFormatLength[@type=\"short\"]/dateTimeFormat[@type=\"standard\"]/pattern[@type=\"standard\"]"); |
| checkValue( |
| "DateTimeCombo long std", |
| "〖❬September 5, 1999❭ at ❬1:25:59 PM Eastern Standard Time❭〗〖❬September 5, 1999❭ at ❬1:25 PM❭〗〖❬today❭ at ❬1:25 PM❭〗", |
| exampleGenerator, |
| "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/dateTimeFormatLength[@type=\"long\"]/dateTimeFormat[@type=\"atTime\"]/pattern[@type=\"standard\"]"); |
| } |
| |
| public void TestSymbols() { |
| CLDRFile english = info.getEnglish(); |
| ExampleGenerator exampleGenerator = new ExampleGenerator(english, english); |
| String actual = |
| exampleGenerator.getExampleHtml( |
| "//ldml/numbers/symbols[@numberSystem=\"latn\"]/superscriptingExponent", |
| "x"); |
| |
| assertEquals( |
| "superscriptingExponent faulty", |
| "<div class='cldr_example'><span class='cldr_substituted'>1.23456789</span>x10<span class='cldr_substituted'><sup>5</sup></span></div>", |
| actual); |
| } |
| |
| public void TestFallbackFormat() { |
| ExampleGenerator exampleGenerator = |
| new ExampleGenerator(info.getEnglish(), info.getEnglish()); |
| String actual = |
| exampleGenerator.getExampleHtml( |
| "//ldml/dates/timeZoneNames/fallbackFormat", "{1} [{0}]"); |
| assertEquals( |
| "fallbackFormat faulty", |
| "〖❬Central Time❭ [❬Cancún❭]〗", |
| ExampleGenerator.simplify(actual, false)); |
| } |
| |
| public void Test4897() { |
| ExampleGenerator exampleGenerator = getExampleGenerator("it"); |
| final CLDRFile cldrFile = exampleGenerator.getCldrFile(); |
| for (String xpath : |
| With.in( |
| cldrFile.iterator( |
| "//ldml/dates/timeZoneNames", cldrFile.getComparator()))) { |
| String value = cldrFile.getStringValue(xpath); |
| String actual = exampleGenerator.getExampleHtml(xpath, value); |
| if (actual == null) { |
| if (!xpath.contains("singleCountries") && !xpath.contains("gmtZeroFormat")) { |
| errln("Null value for " + value + "\t" + xpath); |
| // for debugging |
| exampleGenerator.getExampleHtml(xpath, value); |
| } |
| } else { |
| logln(actual + "\t" + value + "\t" + xpath); |
| } |
| } |
| } |
| |
| public void Test4528() { |
| String[][] testPairs = { |
| { |
| "//ldml/numbers/currencies/currency[@type=\"BMD\"]/displayName[@count=\"other\"]", |
| "〖❬1,23 ❭dollari delle Bermuda〗〖❬0,00 ❭dollari delle Bermuda〗" |
| }, |
| { |
| "//ldml/numbers/currencyFormats[@numberSystem=\"latn\"]/unitPattern[@count=\"other\"]", |
| "〖❬1,23❭ ❬dollari statunitensi❭〗〖❬1,23❭ ❬euro❭〗〖❬0,00❭ ❬dollari statunitensi❭〗〖❬0,00❭ ❬euro❭〗" |
| }, |
| {"//ldml/numbers/currencies/currency[@type=\"BMD\"]/symbol", "〖❬123.456,79 ❭BMD〗"}, |
| }; |
| |
| ExampleGenerator exampleGenerator = getExampleGenerator("it"); |
| for (String[] testPair : testPairs) { |
| String xpath = testPair[0]; |
| String expected = testPair[1]; |
| String value = exampleGenerator.getCldrFile().getStringValue(xpath); |
| String actual = simplify(exampleGenerator.getExampleHtml(xpath, value)); |
| assertEquals("specifics", expected, actual); |
| } |
| } |
| |
| public void Test4607() { |
| String[][] testPairs = { |
| { |
| "//ldml/numbers/decimalFormats[@numberSystem=\"latn\"]/decimalFormatLength[@type=\"long\"]/decimalFormat[@type=\"standard\"]/pattern[@type=\"1000\"][@count=\"one\"]", |
| "<div class='cldr_example'><span class='cldr_substituted'>1</span> thousand</div>" |
| }, |
| { |
| "//ldml/numbers/percentFormats[@numberSystem=\"latn\"]/percentFormatLength/percentFormat[@type=\"standard\"]/pattern[@type=\"standard\"]", |
| "<div class='cldr_example'><span class='cldr_substituted'>5</span>%</div>" |
| + "<div class='cldr_example'><span class='cldr_substituted'>12,345</span>,<span class='cldr_substituted'>679</span>%</div>" |
| + "<div class='cldr_example'>-<span class='cldr_substituted'>12,345</span>,<span class='cldr_substituted'>679</span>%</div>" |
| } |
| }; |
| final CLDRFile nativeCldrFile = info.getEnglish(); |
| ExampleGenerator exampleGenerator = |
| new ExampleGenerator(info.getEnglish(), info.getEnglish()); |
| for (String[] testPair : testPairs) { |
| String xpath = testPair[0]; |
| String expected = testPair[1]; |
| String value = nativeCldrFile.getStringValue(xpath); |
| String actual = exampleGenerator.getExampleHtml(xpath, value); |
| assertEquals("specifics", expected, actual); |
| } |
| } |
| |
| private void showCldrFile(final CLDRFile cldrFile) { |
| ExampleGenerator exampleGenerator = new ExampleGenerator(cldrFile, info.getEnglish()); |
| checkPathValue( |
| exampleGenerator, |
| "//ldml/dates/calendars/calendar[@type=\"chinese\"]/dateFormats/dateFormatLength[@type=\"full\"]/dateFormat[@type=\"standard\"]/pattern[@type=\"standard\"][@draft=\"unconfirmed\"]", |
| "EEEE d MMMMl y'x'G", |
| null); |
| |
| for (String xpath : cldrFile.fullIterable()) { |
| if (xpath.endsWith("/alias")) { |
| continue; |
| } |
| String value = cldrFile.getStringValue(xpath); |
| checkPathValue(exampleGenerator, xpath, value, null); |
| } |
| } |
| |
| private void checkPathValue( |
| ExampleGenerator exampleGenerator, String xpath, String value, String expected) { |
| Set<String> alreadySeen = new HashSet<>(); |
| try { |
| String text = exampleGenerator.getExampleHtml(xpath, value); |
| if (text == null) { |
| // skip |
| } else if (text.contains("Exception")) { |
| errln("getExampleHtml\t" + text); |
| } else if (!alreadySeen.contains(text)) { |
| if (text.contains("n/a")) { |
| if (text.contains("<")) { |
| errln("Text not quoted correctly:" + "\t" + text + "\t" + xpath); |
| } |
| } |
| boolean skipLog = false; |
| if (expected != null) { |
| String simplified = ExampleGenerator.simplify(text, false); |
| // redo for debugging |
| text = exampleGenerator.getExampleHtml(xpath, value); |
| skipLog = |
| !assertEquals("Example text for «" + value + "»", expected, simplified); |
| } |
| if (!skipLog) { |
| logln("getExampleHtml\t" + text + "\t" + xpath); |
| } |
| alreadySeen.add(text); |
| } |
| } catch (Exception e) { |
| errln("getExampleHtml\t" + e.getMessage()); |
| } |
| |
| try { |
| String text = exampleGenerator.getHelpHtml(xpath, value); |
| if (text == null) { |
| // skip |
| } else if (text.contains("Exception")) { |
| errln("getHelpHtml\t" + text); |
| } else { |
| logln("getExampleHtml(help)\t" + "\t" + text + "\t" + xpath); |
| } |
| } catch (Exception e) { |
| if (false) { |
| e.printStackTrace(); |
| } |
| errln("getHelpHtml\t" + e.getMessage()); |
| } |
| } |
| |
| public void TestCompactPlurals() { |
| checkCompactExampleFor("de", Count.one, "〖❬1❭ Mio. €〗", "short", "currency", "000000"); |
| checkCompactExampleFor("de", Count.other, "〖❬2❭ Mio. €〗", "short", "currency", "000000"); |
| checkCompactExampleFor("de", Count.one, "〖❬12❭ Mio. €〗", "short", "currency", "0000000"); |
| checkCompactExampleFor("de", Count.other, "〖❬10❭ Mio. €〗", "short", "currency", "0000000"); |
| |
| checkCompactExampleFor("cs", Count.many, "〖❬1,1❭ milionu〗", "long", "decimal", "000000"); |
| checkCompactExampleFor("pl", Count.other, "〖❬1,1❭ miliona〗", "long", "decimal", "000000"); |
| } |
| |
| private void checkCompactExampleFor( |
| String localeID, |
| Count many, |
| String expected, |
| String longVsShort, |
| String decimalVsCurrency, |
| String zeros) { |
| CLDRFile cldrFile = info.getCLDRFile(localeID, true); |
| ExampleGenerator exampleGenerator = new ExampleGenerator(cldrFile, info.getEnglish()); |
| String path = |
| "//ldml/numbers/" |
| + decimalVsCurrency |
| + "Formats[@numberSystem=\"latn\"]" |
| + "/" |
| + decimalVsCurrency |
| + "FormatLength[@type=\"" |
| + longVsShort |
| + "\"]" |
| + "/" |
| + decimalVsCurrency |
| + "Format[@type=\"standard\"]" |
| + "/pattern[@type=\"1" |
| + zeros |
| + "\"][@count=\"" |
| + many |
| + "\"]"; |
| checkPathValue(exampleGenerator, path, cldrFile.getStringValue(path), expected); |
| } |
| |
| // ldml/numbers/currencyFormats[@numberSystem="latn"]/currencyFormatLength[@type="short"]/currencyFormat[@type="standard"]/pattern[@type="1000"][@count="one"] |
| |
| public void TestDayPeriods() { |
| // checkDayPeriod("da", "format", "morning1", "〖05:00 – 10:00〗〖❬7:30❭ morgens〗"); |
| checkDayPeriod("zh", "format", "morning1", "〖05:00 – 08:00⁻〗〖清晨❬6:30❭〗"); |
| |
| checkDayPeriod("de", "format", "morning1", "〖05:00 – 10:00⁻〗〖❬7:30 ❭morgens〗"); |
| checkDayPeriod("de", "stand-alone", "morning1", "〖05:00 – 10:00⁻〗"); |
| checkDayPeriod("de", "format", "morning2", "〖10:00 – 12:00⁻〗〖❬11:00 ❭vormittags〗"); |
| checkDayPeriod("de", "stand-alone", "morning2", "〖10:00 – 12:00⁻〗"); |
| checkDayPeriod("pl", "format", "morning1", "〖06:00 – 10:00⁻〗〖❬8:00 ❭rano〗"); |
| checkDayPeriod("pl", "stand-alone", "morning1", "〖06:00 – 10:00⁻〗"); |
| |
| checkDayPeriod( |
| "en", "format", "night1", "〖00:00 – 06:00⁻; 21:00 – 24:00⁻〗〖❬3:00 ❭at night〗"); |
| checkDayPeriod("en", "stand-alone", "night1", "〖00:00 – 06:00⁻; 21:00 – 24:00⁻〗"); |
| |
| checkDayPeriod("en", "format", "noon", "〖12:00〗〖❬12:00 ❭noon〗"); |
| checkDayPeriod("en", "format", "midnight", "〖00:00〗〖❬12:00 ❭midnight〗"); |
| checkDayPeriod("en", "format", "am", "〖00:00 – 12:00⁻〗〖❬6:00 ❭AM〗"); |
| checkDayPeriod("en", "format", "pm", "〖12:00 – 24:00⁻〗〖❬6:00 ❭PM〗"); |
| } |
| |
| private void checkDayPeriod( |
| String localeId, String type, String dayPeriodCode, String expected) { |
| CLDRFile cldrFile = info.getCLDRFile(localeId, true); |
| ExampleGenerator exampleGenerator = new ExampleGenerator(cldrFile, info.getEnglish()); |
| String prefix = |
| "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/dayPeriodContext[@type=\""; |
| String suffix = |
| "\"]/dayPeriodWidth[@type=\"wide\"]/dayPeriod[@type=\"" + dayPeriodCode + "\"]"; |
| String path = prefix + type + suffix; |
| checkPathValue(exampleGenerator, path, cldrFile.getStringValue(path), expected); |
| } |
| |
| /** |
| * Test that getExampleHtml returns same output for same input regardless of order in which it |
| * is called with different inputs. |
| * |
| * <p>Calling getExampleHtml with a particular path and value presumably should NOT depend on |
| * the history of paths and/or values it has been called with previously. |
| * |
| * <p>We formerly got different examples for SPECIAL_PATH depending on whether an example was |
| * first gotten for USE_EVIL_PATH. |
| * |
| * <p>Without EVIL_PATH, got right value for SPECIAL_PATH: <div class='cldr_example'><span |
| * class='cldr_substituted'>123 456,79 </span>€</div> |
| * |
| * <p>With EVIL_PATH, got wrong value for SPECIAL_PATH: <div class='cldr_example'><span |
| * class='cldr_substituted'>123457 k </span>€</div> |
| * |
| * <p>This was fixed by doing clone() before returning a DecimalFormat in ICUServiceBuilder. |
| * Reference: https://unicode-org.atlassian.net/browse/CLDR-13375. |
| * |
| * <p>Subsequently, DAIP changed to normalize NNBSP to NBSP for some paths, so this test was |
| * revised not to depend on that distinction, only to expect an example containing "456,79" as a |
| * substring (DAIP has its own unit tests). Ideally this test might be improved so as not to |
| * depend on actual values at all, but would call getExampleHtml repeatedly for the same set of |
| * paths but in different orders and confirm the example is the same regardless of the order; |
| * that would require disabling the cache. |
| * |
| * @throws IOException |
| */ |
| public void TestExampleGeneratorConsistency() throws IOException { |
| final String EVIL_PATH = |
| "//ldml/numbers/currencyFormats/currencyFormatLength[@type=\"short\"]/currencyFormat[@type=\"standard\"]/pattern[@type=\"10000\"][@count=\"one\"]"; |
| final String SPECIAL_PATH = "//ldml/numbers/currencies/currency[@type=\"EUR\"]/symbol"; |
| final String EXPECTED_TO_CONTAIN = "456,79"; |
| |
| final CLDRFile cldrFile = info.getCLDRFile("fr", true); |
| final ExampleGenerator eg = new ExampleGenerator(cldrFile, info.getEnglish()); |
| |
| final String evilValue = cldrFile.getStringValue(EVIL_PATH); |
| final String specialValue = cldrFile.getStringValue(SPECIAL_PATH); |
| |
| eg.getExampleHtml(EVIL_PATH, evilValue); |
| final String specialExample = eg.getExampleHtml(SPECIAL_PATH, specialValue); |
| if (!specialExample.contains(EXPECTED_TO_CONTAIN)) { |
| errln("Expected example to contain " + EXPECTED_TO_CONTAIN + "; got " + specialExample); |
| } |
| } |
| |
| public void TestInflectedUnitExamples() { |
| String[][] deTests = { |
| { |
| "one", |
| "accusative", |
| "〖❬1❭ Tag〗〖❬… für 1❭ Tag❬ …❭〗〖❌ ❬Anstatt 1❭ Tag❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "one", |
| "dative", |
| "〖❬1❭ Tag〗〖❬… mit 1❭ Tag❬ …❭〗〖❌ ❬Anstatt 1❭ Tag❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "one", |
| "genitive", |
| "〖❬1❭ Tages〗〖❬Anstatt 1❭ Tages❬ …❭〗〖❌ ❬… für 1❭ Tages❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "one", |
| "nominative", |
| "〖❬1❭ Tag〗〖❬1❭ Tag❬ kostet (kosten) € 3,50.❭〗〖❌ ❬Anstatt 1❭ Tag❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "accusative", |
| "〖❬1,5❭ Tage〗〖❬… für 1,5❭ Tage❬ …❭〗〖❌ ❬… mit 1,5❭ Tage❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "dative", |
| "〖❬1,5❭ Tagen〗〖❬… mit 1,5❭ Tagen❬ …❭〗〖❌ ❬… für 1,5❭ Tagen❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "genitive", |
| "〖❬1,5❭ Tage〗〖❬Anstatt 1,5❭ Tage❬ …❭〗〖❌ ❬… mit 1,5❭ Tage❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "nominative", |
| "〖❬1,5❭ Tage〗〖❬1,5❭ Tage❬ kostet (kosten) € 3,50.❭〗〖❌ ❬… mit 1,5❭ Tage❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| }; |
| checkInflectedUnitExamples("de", deTests); |
| String[][] elTests = { |
| { |
| "one", |
| "accusative", |
| "〖❬1❭ ημέρα〗〖❬… ανά 1❭ ημέρα❬ …❭〗〖❌ ❬… αξίας 1❭ ημέρα❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "one", |
| "genitive", |
| "〖❬1❭ ημέρας〗〖❬… αξίας 1❭ ημέρας❬ …❭〗〖❌ ❬… ανά 1❭ ημέρας❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "one", |
| "nominative", |
| "〖❬1❭ ημέρα〗〖❬Η απόσταση είναι 1❭ ημέρα❬ …❭〗〖❌ ❬… αξίας 1❭ ημέρα❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "accusative", |
| "〖❬0,9❭ ημέρες〗〖❬… ανά 0,9❭ ημέρες❬ …❭〗〖❌ ❬… αξίας 0,9❭ ημέρες❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "genitive", |
| "〖❬0,9❭ ημερών〗〖❬… αξίας 0,9❭ ημερών❬ …❭〗〖❌ ❬… ανά 0,9❭ ημερών❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| { |
| "other", |
| "nominative", |
| "〖❬0,9❭ ημέρες〗〖❬Η απόσταση είναι 0,9❭ ημέρες❬ …❭〗〖❌ ❬… αξίας 0,9❭ ημέρες❬ …❭〗〖〗〖1 day ≡ 24 hour〗〖1 day ≡ 1/7 week〗" |
| }, |
| }; |
| checkInflectedUnitExamples("el", elTests); |
| } |
| |
| private void checkInflectedUnitExamples(final String locale, String[][] tests) { |
| final CLDRFile cldrFile = info.getCLDRFile(locale, true); |
| ExampleGenerator exampleGenerator = getExampleGenerator(locale); |
| String pattern = |
| "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"duration-day\"]/unitPattern[@count=\"COUNT\"][@case=\"CASE\"]"; |
| boolean showWorkingExamples = false; |
| for (String[] row : tests) { |
| String path = pattern.replace("COUNT", row[0]).replace("CASE", row[1]); |
| String expected = row[2]; |
| String value = cldrFile.getStringValue(path); |
| String actualRaw = exampleGenerator.getExampleHtml(path, value); |
| String actual = ExampleGenerator.simplify(actualRaw, false); |
| showWorkingExamples |= !assertEquals(row[0] + ", " + row[1], expected, actual); |
| } |
| |
| // If a test fails, verbose will regenerate what the code thinks they should be. |
| // Review for correctness, and then replace the test cases |
| |
| if (showWorkingExamples) { |
| System.out.println( |
| "## The following would satisfy the test, but check to make sure the expected values are all correct!"); |
| PluralInfo pluralInfo = SDI.getPlurals(PluralType.cardinal, locale); |
| GrammarInfo grammarInfo = SDI.getGrammarInfo(locale); |
| final Collection<String> grammaticalValues2 = |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalCase, |
| GrammaticalScope.units); |
| |
| for (Count plural : pluralInfo.getCounts()) { |
| for (String grammaticalCase : grammaticalValues2) { |
| String path = |
| pattern.replace("COUNT", plural.toString()) |
| .replace("CASE", grammaticalCase); |
| String value = cldrFile.getStringValue(path); |
| String actualRaw = exampleGenerator.getExampleHtml(path, value); |
| String actual = ExampleGenerator.simplify(actualRaw, false); |
| System.out.println( |
| "{\"" |
| + plural |
| + "\", " |
| + "\"" |
| + grammaticalCase |
| + "\", " |
| + "\"" |
| + actual |
| + "\"},"); |
| } |
| } |
| } |
| } |
| |
| public void TestMinimalPairExamples() { |
| String[][] tests = { |
| { |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"one\"]", |
| "〖❬1❭ Tag〗〖❌ ❬2❭ Tag〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"other\"]", |
| "〖❬2❭ Tage〗〖❌ ❬1❭ Tage〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"accusative\"]", |
| "〖… für ❬1 metrische Pint❭ …〗〖❌ … für ❬1 metrischen Pint❭ …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"dative\"]", |
| "〖… mit ❬1 metrischen Pint❭ …〗〖❌ … mit ❬1 metrische Pint❭ …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"genitive\"]", |
| "〖Anstatt ❬1 metrischen Pints❭ …〗〖❌ Anstatt ❬1 metrische Pint❭ …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"nominative\"]", |
| "〖❬2 metrische Pints❭ kostet (kosten) € 3,50.〗〖❌ ❬1 metrische Pint❭ kostet (kosten) € 3,50.〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"feminine\"]", |
| "〖Die ❬Stunde❭ ist …〗〖❌ Die ❬Tag❭ ist …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"masculine\"]", |
| "〖Der ❬Tag❭ ist …〗〖❌ Der ❬Stunde❭ ist …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"neuter\"]", |
| "〖Das ❬Jahr❭ ist …〗〖❌ Das ❬Stunde❭ ist …〗" |
| }, |
| }; |
| checkMinimalPairExamples("de", tests); |
| |
| String[][] elTests = { |
| { |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"one\"]", |
| "〖❬1❭ ημέρα〗〖❌ ❬2❭ ημέρα〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"other\"]", |
| "〖❬2❭ ημέρες〗〖❌ ❬1❭ ημέρες〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"accusative\"]", |
| "〖… ανά ❬1 τόνο❭ …〗〖❌ … ανά ❬1 τόνου❭ …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"genitive\"]", |
| "〖… αξίας ❬1 τόνου❭ …〗〖❌ … αξίας ❬1 τόνο❭ …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"nominative\"]", |
| "〖Η απόσταση είναι ❬2 τόνοι❭ …〗〖❌ Η απόσταση είναι ❬1 τόνο❭ …〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"feminine\"]", |
| "〖Η ❬ημέρα❭ είναι〗〖❌ Η ❬μήνας❭ είναι〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"masculine\"]", |
| "〖Ο ❬μήνας❭ θα είναι〗〖❌ Ο ❬ημέρα❭ θα είναι〗" |
| }, |
| { |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"neuter\"]", |
| "〖Το ❬λεπτό❭ ήταν〗〖❌ Το ❬ημέρα❭ ήταν〗" |
| }, |
| }; |
| checkMinimalPairExamples("el", elTests); |
| } |
| |
| private void checkMinimalPairExamples(final String locale, String[][] tests) { |
| final CLDRFile cldrFile = info.getCLDRFile(locale, true); |
| ExampleGenerator exampleGenerator = getExampleGenerator(locale); |
| boolean showWorkingExamples = false; |
| for (String[] row : tests) { |
| String path = row[0]; |
| String expected = row[1]; |
| String value = cldrFile.getStringValue(path); |
| String actualRaw = exampleGenerator.getExampleHtml(path, value); |
| String actual = ExampleGenerator.simplify(actualRaw, false); |
| showWorkingExamples |= !assertEquals(row[0] + ", " + row[1], expected, actual); |
| } |
| |
| // If a test fails, verbose will regenerate what the code thinks they should be. |
| // Review for correctness, and then replace the test cases |
| |
| if (showWorkingExamples) { |
| System.out.println( |
| "## The following would satisfy the test, but check to make sure the expected values are all correct!"); |
| PluralInfo pluralInfo = SDI.getPlurals(PluralType.cardinal, locale); |
| ArrayList<String> paths = new ArrayList<>(); |
| |
| for (Count plural : pluralInfo.getCounts()) { |
| paths.add( |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"" |
| + plural |
| + "\"]"); |
| } |
| GrammarInfo grammarInfo = SDI.getGrammarInfo(locale); |
| for (String grammaticalValues : |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalCase, |
| GrammaticalScope.units)) { |
| paths.add( |
| "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"" |
| + grammaticalValues |
| + "\"]"); |
| } |
| for (String grammaticalValues : |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalGender, |
| GrammaticalScope.units)) { |
| paths.add( |
| "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"" |
| + grammaticalValues |
| + "\"]"); |
| } |
| for (String path : paths) { |
| String value = cldrFile.getStringValue(path); |
| String actualRaw = exampleGenerator.getExampleHtml(path, value); |
| String actual = ExampleGenerator.simplify(actualRaw, false); |
| System.out.println("{\"" + path.replace("\"", "\\\"") + "\", \"" + actual + "\"},"); |
| } |
| } |
| } |
| |
| /** |
| * Test the production of minimal pair examples, to make sure we get no exceptions. If -v, then |
| * generates lines for spreadsheet survey |
| */ |
| public void TestListMinimalPairExamples() { |
| Set<String> localesWithGrammar = SDI.hasGrammarInfo(); |
| if (isVerbose()) { |
| System.out.println( |
| "\nLC\tLocale\tType\tCode\tCurrent Pattern\tVerify this is correct!\tVerify this is wrong!"); |
| } |
| final String unused = "∅"; |
| List<String> pluralSheet = new ArrayList(); |
| for (String locale : localesWithGrammar) { |
| final CLDRFile cldrFile = info.getCLDRFile(locale, true); |
| ExampleGenerator exampleGenerator = getExampleGenerator(locale); |
| |
| PluralInfo pluralInfo = SDI.getPlurals(PluralType.cardinal, cldrFile.getLocaleID()); |
| Map<String, Pair<String, String>> paths = new LinkedHashMap<>(); |
| |
| Set<Count> counts = pluralInfo.getCounts(); |
| if (counts.size() > 1) { |
| for (Count plural : counts) { |
| paths.put( |
| "//ldml/numbers/minimalPairs/pluralMinimalPairs[@count=\"" |
| + plural |
| + "\"]", |
| Pair.of("plural", plural.toString())); |
| } |
| } |
| GrammarInfo grammarInfo = SDI.getGrammarInfo(locale); |
| Collection<String> unitCases = |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalCase, |
| GrammaticalScope.units); |
| Collection<String> generalCasesRaw = |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalCase, |
| GrammaticalScope.general); |
| Collection<CaseValues> generalCases = |
| generalCasesRaw.stream() |
| .map(x -> CaseValues.valueOf(x)) |
| .collect(Collectors.toCollection(TreeSet::new)); |
| for (CaseValues unitCase0 : generalCases) { |
| String unitCase = unitCase0.toString(); |
| paths.put( |
| (unitCases.contains(unitCase) ? "" : unused) |
| + "//ldml/numbers/minimalPairs/caseMinimalPairs[@case=\"" |
| + unitCase |
| + "\"]", |
| Pair.of("case", unitCase)); |
| } |
| Collection<String> unitGenders = |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalGender, |
| GrammaticalScope.units); |
| Collection<String> generalGenders = |
| grammarInfo.get( |
| GrammaticalTarget.nominal, |
| GrammaticalFeature.grammaticalGender, |
| GrammaticalScope.general); |
| for (String unitGender : generalGenders) { |
| paths.put( |
| (unitGenders.contains(unitGender) ? "" : unused) |
| + "//ldml/numbers/minimalPairs/genderMinimalPairs[@gender=\"" |
| + unitGender |
| + "\"]", |
| Pair.of("gender", unitGender)); |
| } |
| String localeName = CLDRConfig.getInstance().getEnglish().getName(locale); |
| boolean pluralOnly = true; |
| if (paths.isEmpty()) { |
| pluralSheet.add( |
| locale + "\t" + localeName + "\t" + "N/A" + "\t" + "N/A" + "\t" + "N/A"); |
| } else { |
| for (Entry<String, Pair<String, String>> pathAndLabel : paths.entrySet()) { |
| String path = pathAndLabel.getKey(); |
| String label = pathAndLabel.getValue().getFirst(); |
| String code = pathAndLabel.getValue().getSecond(); |
| if (!label.equals("plural")) { |
| pluralOnly = false; |
| } |
| } |
| String lastLabel = ""; |
| for (Entry<String, Pair<String, String>> pathAndLabel : paths.entrySet()) { |
| String path = pathAndLabel.getKey(); |
| String label = pathAndLabel.getValue().getFirst(); |
| String code = pathAndLabel.getValue().getSecond(); |
| String pattern = ""; |
| String examples = ""; |
| if (!label.equals(lastLabel)) { |
| lastLabel = label; |
| if (!pluralOnly) { |
| if (isVerbose()) { |
| System.out.println(); |
| } |
| } |
| } |
| if (path.startsWith(unused)) { |
| pattern = "🚫 Not used with formatted units"; |
| } else { |
| pattern = cldrFile.getStringValue(path); |
| if (pattern == null) { |
| warnln( |
| "Missing ExampleGenerator html example for " |
| + locale |
| + "(" |
| + localeName |
| + "): " |
| + path); |
| continue; |
| } |
| String actualRaw = exampleGenerator.getExampleHtml(path, pattern); |
| String actualSimplified = ExampleGenerator.simplify(actualRaw, false); |
| examples = |
| actualSimplified |
| .replace("〗〖", "\t") |
| .replace("〗", "") |
| .replace("〖", ""); |
| List<String> exampleList = |
| com.google.common.base.Splitter.on('\t') |
| .trimResults() |
| .splitToList(examples); |
| final int exampleListSize = exampleList.size(); |
| switch (exampleListSize) { |
| case 2: // ok |
| break; |
| case 1: |
| warnln( |
| "Expecting exactly 2 examples: " |
| + exampleList |
| + ", but got " |
| + exampleListSize); |
| break; |
| default: |
| errln( |
| "Expecting exactly 2 examples: " |
| + exampleList |
| + ", but got " |
| + exampleListSize); |
| break; |
| } |
| StringBuilder exampleBuffer = new StringBuilder(); |
| for (String exampleItem : exampleList) { |
| if (exampleItem.contains("❬null❭") || exampleItem.contains("❬n/a❭")) { |
| boolean bad = (exampleItem.contains("❌")); |
| exampleItem = "🆖 No unit available"; |
| if (bad) { |
| exampleItem = "❌ " + exampleItem; |
| } |
| } |
| if (exampleBuffer.length() != 0) { |
| exampleBuffer.append('\t'); |
| } |
| exampleBuffer.append(exampleItem); |
| } |
| examples = exampleBuffer.toString(); |
| } |
| String line = |
| (locale |
| + "\t" |
| + localeName |
| + "\t" |
| + label |
| + "\t" |
| + code |
| + "\t" |
| + pattern |
| + "\t" |
| + examples); |
| if (pluralOnly) { |
| pluralSheet.add(line); |
| } else { |
| if (isVerbose()) { |
| System.out.println(line); |
| } |
| } |
| } |
| } |
| if (pluralOnly) { |
| pluralSheet.add(""); |
| } else if (isVerbose()) { |
| System.out.println(); |
| } |
| } |
| if (isVerbose()) { |
| System.out.println("#################### Plural Only ###################"); |
| for (String line : pluralSheet) { |
| System.out.println(line); |
| } |
| } |
| } |
| |
| public void TestUnicodeSetExamples() { |
| String[][] tests = { |
| { |
| "hi", |
| "//ldml/characters/exemplarCharacters[@type=\"auxiliary\"]", |
| "[ॄ]", |
| "〖🗝️ ॑ ॒ ॠ ॡ ॻ ॼ ॾ ॿ ऱ ॢ ॣ〗〖❰ZWNJ❱ ≡ cursive non-joiner〗〖❰ZWJ❱ ≡ cursive joiner〗〖❬internal: ❭[ॄ]〗" |
| }, |
| { |
| "hu", |
| "//ldml/characters/exemplarCharacters[@type=\"auxiliary\"]", |
| "[qw-yàâ-èê-ìîïñòôøùûÿāăēĕīĭōŏœūŭ]", |
| "〖🗝️ · ắ ằ ẵ ẳ ấ ầ ẫ ẩ ǎ a̧ ą ą́ a᷆ a᷇ ả ạ ặ ậ a̱ aː áː àː ɓ ć ĉ č ċ ď ḑ đ ḍ ḓ ð ɖ ɗ ế ề ễ ể ě ẽ ė ę ę́ e᷆ e᷇ ẻ ẹ ẹ́ ẹ̀ ệ e̱ eː éː èː ǝ ǝ́ ǝ̀ ǝ̂ ǝ̌ ǝ̄ ə ə́ ə̀ ə̂ ə̌ ə̄ ɛ ɛ́ ɛ̀ ɛ̂ ɛ̌ ɛ̈ ɛ̃ ɛ̧ ɛ̄ ɛ᷆ ɛ᷇ ɛ̱ ɛ̱̈ ƒ ğ ĝ ǧ g̃ ġ ģ g̱ gʷ ǥ ɣ ĥ ȟ ħ ḥ ʻ ǐ ĩ İ i̧ į į́ i᷆ i᷇ ỉ ị i̱ iː íː ìː íj́ ı ɨ ɨ́ ɨ̀ ɨ̂ ɨ̌ ɨ̄ ɩ ɩ́ ɩ̀ ɩ̂ ĵ ǩ ķ ḵ kʷ ƙ ĺ ľ ļ ł ḷ ḽ ḻ ḿ m̀ m̄ ń ǹ ň ṅ ņ n̄ ṇ ṋ ṉ ɲ ŋ ŋ́ ŋ̀ ŋ̄ ố ồ ỗ ổ ǒ õ ǫ ǫ́ o᷆ o᷇ ỏ ơ ớ ờ ỡ ở ợ ọ ọ́ ọ̀ ộ o̱ oː óː òː ɔ ɔ́ ɔ̀ ɔ̂ ɔ̌ ɔ̈ ɔ̃ ɔ̧ ɔ̄ ɔ᷆ ɔ᷇ ɔ̱ ŕ ř ŗ ṛ ś ŝ š ş ṣ ș ß ť ṭ ț ṱ ṯ ŧ ǔ ů ũ u̧ ų u᷆ u᷇ ủ ư ứ ừ ữ ử ự ụ uː úː ùː ʉ ʉ́ ʉ̀ ʉ̂ ʉ̌ ʉ̈ ʉ̄ ʊ ʊ́ ʊ̀ ʊ̂ ṽ ʋ ẃ ẁ ŵ ẅ ý ỳ ŷ ỹ ỷ ỵ y̱ ƴ ź ž ż ẓ ʒ ǯ þ ʔ ˀ ʼ ꞌ ǀ ǁ ǂ ǃ〗〖❬internal: ❭[qw-yàâ-èê-ìîïñòôøùûÿāăēĕīĭōŏœūŭ]〗" |
| }, |
| { |
| "de", |
| "//ldml/characters/parseLenients[@scope=\"date\"][@level=\"lenient\"]/parseLenient[@sample=\"-\"]", |
| "[\\u200B \\- . ๎ ็]", |
| "〖➕ ❰WNJ❱ ๎ ็〗〖➖ ‑ /〗〖❰WNJ❱ ≡ allow line wrap after, aka ZWSP〗〖❬internal: ❭[\\-.็๎]〗" |
| }, |
| { |
| "de", |
| "//ldml/characters/exemplarCharacters", |
| "[\\u200B a-z ๎ ็]", |
| "〖➕ ❰WNJ❱ ๎ ็〗〖➖ ä ö ß ü〗〖❰WNJ❱ ≡ allow line wrap after, aka ZWSP〗〖❬internal: ❭[a-z็๎]〗" |
| }, |
| {"de", "//ldml/characters/exemplarCharacters", "a-z ❰ZWSP❱", null}, |
| }; |
| |
| for (String[] test : tests) { |
| final String locale = test[0]; |
| final String path = test[1]; |
| final String value = test[2]; |
| final String expected = test[3]; |
| ExampleGenerator exampleGenerator = getExampleGenerator(locale); |
| String actual = |
| ExampleGenerator.simplify( // |
| exampleGenerator.getExampleHtml(path, value)); |
| assertEquals(locale + path + "=" + value, expected, actual); |
| } |
| } |
| } |