1 package org.unicode.cldr.tool;
2 
3 import java.io.IOException;
4 import java.util.List;
5 
6 import org.unicode.cldr.util.CLDRFile;
7 
8 import com.ibm.icu.dev.util.CollectionUtilities;
9 import com.ibm.icu.impl.Row.R4;
10 
11 public class ChartLanguageMatching extends Chart {
12 
main(String[] args)13     public static void main(String[] args) {
14         new ChartLanguageMatching().writeChart(null);
15     }
16 
17     @Override
getDirectory()18     public String getDirectory() {
19         return FormattedFileWriter.CHART_TARGET_DIR;
20     }
21 
22     @Override
getTitle()23     public String getTitle() {
24         return "Language Matching";
25     }
26 
27     @Override
getExplanation()28     public String getExplanation() {
29         return "<p>Language Matching data is used to match the user’s desired language/locales against an application’s supported languages/locales. "
30             + "For more information, see "
31             + "<a href='http://unicode.org/reports/tr35/#LanguageMatching'>Language Matching</a>. "
32             + "The latest release data for this chart is in "
33             + "<a href='http://unicode.org/cldr/latest/common/supplemental/languageInfo.xml'>languageInfo.xml</a>. "
34             + "The matching process is approximately:<p>"
35             + "<ul>"
36             + "<li>The rules are tested—in order—for matches, with the first one winning.</li>"
37             + "<li>Any exact match between fields has zero distance.</li>"
38             + "<li>The placeholder (*) matches any code (of that type). "
39             + "For the last field in Supported, it must be different than Desired.</li>"
40             + "<li>The <i>Distance</i> indicates how close the match is, where identical fields have distance = 0. </li>"
41             + "<li>A ⬌︎ in the <i>Sym?</i> column indicates that the distance is symmetric, "
42             + "and is thus used for both directions: Supported→Desired and Desired→Supported. "
43             + "A → indicates that the distance is <i>not</i> symmetric: this is usually a <i>fallback</i> match.</li>"
44             + "</ul>";
45     }
46 
47     @Override
writeContents(FormattedFileWriter pw)48     public void writeContents(FormattedFileWriter pw) throws IOException {
49         TablePrinter tablePrinter = new TablePrinter()
50             .addColumn("Desired", "class='source'", null, "class='source'", true)
51             .addColumn("Supported", "class='source'", null, "class='source'", true)
52             .addColumn("D. Code", "class='source'", null, "class='source'", true)
53             .setBreakSpans(true)
54             .addColumn("S. Code", "class='source'", null, "class='source'", true)
55             .setBreakSpans(true)
56             .addColumn("Distance", "class='target'", null, "class='target'", true)
57             .addColumn("Sym?", "class='target'", null, "class='target'", true);
58 
59         for (String type : SDI.getLanguageMatcherKeys()) {
60             pw.write("<h2>Type=" + type + "</h2>");
61             List<R4<String, String, Integer, Boolean>> data = SDI.getLanguageMatcherData(type);
62             for (R4<String, String, Integer, Boolean> row : data) {
63                 // <languageMatch desired="gsw" supported="de" percent="96" oneway="true" /> <!-- All Swiss speakers can read High German -->
64 
65                 tablePrinter.addRow()
66                     //.addCell(ENGLISH.getName(locale))
67                     .addCell(getName(row.get0(), true))
68                     .addCell(getName(row.get1(), false))
69                     .addCell(row.get0())
70                     .addCell(row.get1())
71                     .addCell((100 - row.get2()))
72                     .addCell(row.get3() ? "→" : "⬌")
73                     .finishRow();
74             }
75             pw.write(tablePrinter.toTable());
76             tablePrinter.clearRows();
77         }
78     }
79 
getName(String codeWithStars, boolean user)80     private String getName(String codeWithStars, boolean user) {
81         if (!codeWithStars.contains("*") && !codeWithStars.contains("$")) {
82             return ENGLISH.getName(codeWithStars, true, CLDRFile.SHORT_ALTS);
83         }
84         String[] parts = codeWithStars.split("_");
85         if (parts[0].equals("*")) {
86             parts[0] = "xxx";
87         }
88         if (parts.length > 1 && parts[1].equals("*")) {
89             parts[1] = "Xxxx";
90         }
91         String parts2orig = "XY";
92         if (parts.length > 2) {
93             parts2orig = parts[2];
94             if (parts[2].equals("*")) {
95                 parts[2] = "XX";
96             } else if (parts[2].startsWith("$")) {
97                 parts[2] = "XY";
98             }
99         }
100         String result = ENGLISH.getName(CollectionUtilities.join(parts, "_"), true, CLDRFile.SHORT_ALTS);
101         if (user) {
102             result = result
103                 .replace("Xxxx", "any-script")
104                 .replace("xxx", "any-language")
105                 .replace("XX", "any-region")
106                 .replace("XY", parts2orig);
107         } else {
108             result = replaceStar(result);
109         }
110         return result;
111     }
112 
replaceStar(String result)113     private String replaceStar(String result) {
114         String temp = result.replace("XX", "any-other-region");
115         temp = temp.equals(result) ? temp.replace("Xxxx", "any-other-script") : temp.replace("Xxxx", "any-script");
116         temp = temp.equals(result) ? temp.replace("xxx", "any-other-language") : temp.replace("xxx", "any-language");
117         return temp;
118     }
119 }
120