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