1 package org.unicode.cldr.test; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 import java.util.regex.Matcher; 6 import java.util.regex.Pattern; 7 8 import org.unicode.cldr.util.GrammarInfo; 9 import org.unicode.cldr.util.Organization; 10 import org.unicode.cldr.util.RegexUtilities; 11 import org.unicode.cldr.util.StandardCodes; 12 13 import com.google.common.collect.ImmutableSet; 14 import com.google.common.collect.ImmutableSortedSet; 15 16 public final class SubmissionLocales { 17 18 public static final Set<String> CLDR_LOCALES = StandardCodes.make().getLocaleToLevel(Organization.cldr).keySet(); 19 20 /** 21 * Non-CLDR Locales, but consistently have high level of engagement from volunteers to keep at modern level. 22 * Reevaluate for each release based on meeting 95+% of modern, moderate, and basic coverage 23 */ 24 public static Set<String> HIGH_LEVEL_LOCALES = ImmutableSet.of( 25 "chr", // Cherokee 26 "gd", // Scottish Gaelic, Gaelic 27 "fo", // Faroese 28 "kok", // Konkani 29 "pcm", // Nigerian Pidgin 30 "ha", // Hausa 31 "hsb", // Upper Sorbian 32 "dsb", // Lower Sorbian 33 "yue_Hans", // Cantonese (Simplified) 34 "to" // Tongan 35 ); 36 37 public static final Set<String> CLDR_OR_HIGH_LEVEL_LOCALES = ImmutableSet.<String>builder() 38 .addAll(CLDR_LOCALES) 39 .addAll(HIGH_LEVEL_LOCALES) 40 .build(); 41 42 /** 43 * Update this in each limited release. 44 */ 45 public static final Set<String> LOCALES_FOR_LIMITED; 46 static { 47 Set<String> temp = new HashSet<>(CLDR_OR_HIGH_LEVEL_LOCALES); GrammarInfo.getGrammarLocales()48 temp.retainAll(GrammarInfo.getGrammarLocales()); 49 LOCALES_FOR_LIMITED = ImmutableSortedSet.copyOf(temp); 50 } 51 52 /** 53 * New locales in this release, where we want to allow any paths even if others are restricted 54 */ 55 public static Set<String> ALLOW_ALL_PATHS = ImmutableSet.of( 56 "brx", 57 "ks", 58 "ks_Deva", 59 "rhg" // Rohingya 60 ); 61 62 public static Set<String> LOCALES_ALLOWED_IN_LIMITED = ImmutableSet.<String>builder() 63 .addAll(LOCALES_FOR_LIMITED) 64 .addAll(ALLOW_ALL_PATHS) 65 .build(); 66 67 public static final Pattern PATHS_ALLOWED_IN_LIMITED = Pattern.compile( 68 "//ldml/" 69 // v43: All person names 70 // + "(personNames/.*" 71 // v43: Turkey and its alternate 72 // + "|localeDisplayNames/territories/territory\\[@type=\"TR\"\\].*" 73 + "|units/unitLength\\[@type=\"long\"]" 74 // v43: Exemplar city for America/Ciudad_Juarez 75 + "|dates/timeZoneNames/zone[@type=\"America/Ciudad_Juarez\"]/exemplarCity" 76 + ")"); 77 78 /* Example of special paths 79 * Pattern.compile( 80 "//ldml/" 81 + "(listPatterns/listPattern\\[@type=\"standard" 82 + "|annotations/annotation\\[@cp=\"([©®‼⁉☑✅✔✖✨✳✴❇❌❎❓-❕❗❣ ➕-➗-⭕⭕]|♀|♂)\"" 83 + "|localeDisplayNames/" 84 + "(scripts/script\\[@type=\"(Elym|Hmnp|Nand|Wcho)\"" 85 + "|territories/territory\\[@type=\"(MO|SZ)\"](\\[@alt=\"variant\"])?" 86 + "|types/type\\[@key=\"numbers\"]\\[@type=\"(hmnp|wcho)\"]" 87 + ")" 88 + "|dates/timeZoneNames/(metazone\\[@type=\"Macau\"]" 89 + "|zone\\[@type=\"Asia/Macau\"]" 90 + ")" 91 + ")" 92 ); 93 */ 94 95 //ldml/dates/timeZoneNames/metazone[@type="Macau"]/long/daylight, old: Macau Summer Time, new: Macao Summer Time 96 //ldml/dates/timeZoneNames/metazone[@type="Macau"]/long/standard, old: Macau Standard Time, new: Macao Standard Time 97 //ldml/localeDisplayNames/territories/territory[@type="SZ"][@alt="variant"], old: SZ, new: Swaziland 98 //ldml/dates/timeZoneNames/zone[@type="Asia/Macau"]/exemplarCity, old: Macau, new: Macao 99 //ldml/dates/timeZoneNames/metazone[@type="Macau"]/long/generic, old: Macau Time, new: Macao Time 100 //ldml/localeDisplayNames/territories/territory[@type="SZ"], old: Swaziland, new: Eswatini 101 102 103 /** 104 * Only call this if LIMITED_SUBMISSION 105 * @param localeString 106 * @param path 107 * @param isError 108 * @param isMissing 109 * @return true if submission is allowed, else false 110 */ allowEvenIfLimited(String localeString, String path, boolean isError, boolean isMissing)111 public static boolean allowEvenIfLimited(String localeString, String path, boolean isError, boolean isMissing) { 112 113 // don't limit new locales or errors 114 115 if (SubmissionLocales.ALLOW_ALL_PATHS.contains(localeString) || isError) { 116 return true; 117 } else { 118 int debug = 0; // for debugging 119 } 120 121 // all but specific locales are otherwise locked 122 123 if (!SubmissionLocales.LOCALES_ALLOWED_IN_LIMITED.contains(localeString)) { 124 return false; 125 } else { 126 int debug = 0; // for debugging 127 } 128 129 // in those locales, lock all paths except missing and special 130 131 if (isMissing) { 132 return true; 133 } else { 134 int debug = 0; // for debugging 135 } 136 137 if (pathAllowedInLimitedSubmission(path)) { 138 return true; 139 } else { 140 int debug = 0; // for debugging 141 } 142 143 return false; // skip 144 } 145 146 private static final boolean DEBUG_REGEX = false; 147 148 /** 149 * Only public for testing 150 * @param path 151 * @return 152 */ pathAllowedInLimitedSubmission(String path)153 public static boolean pathAllowedInLimitedSubmission(String path) { 154 if (PATHS_ALLOWED_IN_LIMITED == null) { 155 return false; 156 } 157 final Matcher matcher = SubmissionLocales.PATHS_ALLOWED_IN_LIMITED.matcher(path); 158 boolean result = matcher.lookingAt(); 159 if (DEBUG_REGEX && !result) { 160 System.out.println(RegexUtilities.showMismatch(matcher, path)); 161 } 162 return result; 163 } 164 } 165