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