1 package org.unicode.cldr.util; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.EnumSet; 6 import java.util.HashMap; 7 import java.util.List; 8 import java.util.Map; 9 import java.util.Map.Entry; 10 import java.util.Set; 11 import java.util.TreeSet; 12 import java.util.logging.Logger; 13 import java.util.regex.Matcher; 14 import java.util.regex.Pattern; 15 16 import org.unicode.cldr.util.PatternPlaceholders.PlaceholderInfo; 17 18 import com.ibm.icu.text.MessageFormat; 19 import com.ibm.icu.util.Output; 20 21 public class PathDescription { 22 /** 23 * Remember to quote any [ character! 24 */ 25 final private static String pathDescriptionString = "" 26 /* 27 * ROOT descriptions (using special placeholders). Must occur first. 28 */ 29 + "^//ldml/localeDisplayNames/territories/territory\\[@type=\"(CD|DG|CG|003|021|ZA|018|FK|MK|MM|TW|HK|MO)\"]" 30 + RegexLookup.SEPARATOR 31 + "ROOT territory; Warning - the region {0} requires special attention! Note: before translating, be sure to read " 32 + CLDRURLS.COUNTRY_NAMES + ".\n" 33 34 + "^//ldml/localeDisplayNames/scripts/script\\[@type=\"(Z[^\"]*)\"]" 35 + RegexLookup.SEPARATOR 36 + "ROOT script; The name of the script (writing system) with Unicode script code = {0}. Note: before translating, be sure to read " 37 + CLDRURLS.SCRIPT_NAMES + ".\n" 38 39 + "^//ldml/dates/timeZoneNames/zone\\[@type=\"([^\"]*)\"]/exemplarCity" 40 + RegexLookup.SEPARATOR 41 + "ROOT timezone" 42 + RegexLookup.SEPARATOR 43 + "The name of {0}. For more information, see " 44 + CLDRURLS.TZ_CITY_NAMES + ".\n" 45 46 + "^//ldml/localeDisplayNames/languages/language\\[@type=\"([^\"]*)\"]" 47 + RegexLookup.SEPARATOR 48 + "ROOT language; The name of the language with Unicode language code = {0}. For more information, see " 49 + CLDRURLS.LANGUAGE_NAMES + ".\n" 50 + "^//ldml/localeDisplayNames/scripts/script\\[@type=\"([^\"]*)\"]" 51 + RegexLookup.SEPARATOR 52 + "ROOT script; The name of the script (writing system) with Unicode script code = {0}. For more information, see " 53 + CLDRURLS.SCRIPT_NAMES + ".\n" 54 + "^//ldml/localeDisplayNames/territories/territory\\[@type=\"([^\"]*)\"]" 55 + RegexLookup.SEPARATOR 56 + "ROOT territory; The name of the country or region with Unicode region code = {0}. For more information, see " 57 + CLDRURLS.COUNTRY_NAMES + ".\n" 58 + "^//ldml/localeDisplayNames/subdivisions/subdivision\\[@type=\"([^\"]*)\"]" 59 + RegexLookup.SEPARATOR 60 + "ROOT territory; The name of the country subdivision with Unicode subdivision code = {0}. For more information, see " 61 + CLDRURLS.COUNTRY_NAMES + ".\n" 62 + "^//ldml/numbers/currencies/currency\\[@type=\"([^\"]*)\"]/symbol$" 63 + RegexLookup.SEPARATOR 64 + "ROOT currency; The symbol for the currency with the ISO currency code = {0}. For more information, see " 65 + CLDRURLS.CURRENCY_NAMES + ".\n" 66 + "^//ldml/numbers/currencies/currency\\[@type=\"([^\"]*)\"]/symbol\\[@alt=\"narrow\"]" 67 + RegexLookup.SEPARATOR 68 + "ROOT currency; The NARROW form of the symbol used for the currency with the ISO currency code = {0}, when the known context is already enough to distinguish the symbol from other currencies that may use the same symbol. Normally, this does not need to be changed from the inherited value. For more information, see " 69 + CLDRURLS.CURRENCY_NAMES + ".\n" 70 + "^//ldml/numbers/currencies/currency\\[@type=\"([^\"]*)\"]/symbol\\[@alt=\"([^\"]++)\"]" 71 + RegexLookup.SEPARATOR 72 + "ROOT currency; An alternative form of the symbol used for the currency with the ISO currency code = {0}. Usually occurs shortly after a new currency symbol is introduced. For more information, see " 73 + CLDRURLS.CURRENCY_NAMES + ".\n" 74 + "^//ldml/numbers/currencies/currency\\[@type=\"([^\"]*)\"]/displayName" 75 + RegexLookup.SEPARATOR 76 + "ROOT currency; The name of the currency with the ISO currency code = {0}. For more information, see " 77 + CLDRURLS.CURRENCY_NAMES + ".\n" 78 79 /* 80 * Note: we change the metazones dynamically in code 81 */ 82 + "^//ldml/dates/timeZoneNames/metazone\\[@type=\"([^\"]*)\"](.*)/(.*)" 83 + RegexLookup.SEPARATOR 84 + "ROOT metazone; The name of the timezone for “{0}”. Note: before translating, be sure to read " 85 + CLDRURLS.TZ_CITY_NAMES + ".\n" 86 87 /* 88 * OTHER Descriptions 89 */ 90 + "^//ldml/localeDisplayNames/types/type\\[@key=\"collation\"]\\[@type=\"([^\"]*)\"]" 91 + RegexLookup.SEPARATOR 92 + "The name of “{1} collation” (sorting order). For more information, please see " 93 + CLDRURLS.KEY_NAMES + ".\n" 94 + "^//ldml/localeDisplayNames/types/type\\[@key=\"numbers\"]\\[@type=\"([^\"]*)\"]" 95 + RegexLookup.SEPARATOR 96 + "The name of “{1} number system”. For more information, please see " 97 + CLDRURLS.KEY_NAMES + ".\n" 98 + "^//ldml/localeDisplayNames/types/type\\[@key=\"calendar\"]\\[@type=\"roc\"]" 99 + RegexLookup.SEPARATOR 100 + "The name of “roc calendar” (common names include “Minguo Calendar”, “Republic of China Calendar”, and “Republican Calendar”). For more information, please see " 101 + CLDRURLS.KEY_NAMES + ".\n" 102 + "^//ldml/localeDisplayNames/types/type\\[@key=\"calendar\"]\\[@type=\"([^\"]*)\"]" 103 + RegexLookup.SEPARATOR 104 + "The name of “{1} calendar”. For more information, please see " 105 + CLDRURLS.KEY_NAMES + ".\n" 106 + "^//ldml/localeDisplayNames/types/type\\[@key=\"em\"]\\[@type=\"([^\"]*)\"]" 107 + RegexLookup.SEPARATOR 108 + "The name of “emoji presentation style {1}”. For more information, please see " 109 + CLDRURLS.KEY_NAMES + ".\n" 110 + "^//ldml/localeDisplayNames/types/type\\[@key=\"fw\"]\\[@type=\"([^\"]*)\"]" 111 + RegexLookup.SEPARATOR 112 + "The name of “first day of the week is {1}”. For more information, please see " 113 + CLDRURLS.KEY_NAMES + ".\n" 114 + "^//ldml/localeDisplayNames/types/type\\[@key=\"lb\"]\\[@type=\"([^\"]*)\"]" 115 + RegexLookup.SEPARATOR 116 + "The name of “{1} line break style”. For more information, please see " 117 + CLDRURLS.KEY_NAMES + ".\n" 118 + "^//ldml/localeDisplayNames/types/type\\[@key=\"([^\"]*)\"]\\[@type=\"([^\"]*)\"]" 119 + RegexLookup.SEPARATOR 120 + "The name of the “{2} {1}”. For more information, please see " 121 + CLDRURLS.KEY_NAMES + ".\n" 122 + "^//ldml/localeDisplayNames/keys/key\\[@type=\"([^\"]*)\"]" 123 + RegexLookup.SEPARATOR 124 + "The name of the system for “{1}”. For more information, please see " 125 + CLDRURLS.KEY_NAMES + ".\n" 126 + "^//ldml/localeDisplayNames/variants/variant[@type=\"([^\"]*)\"]" 127 + RegexLookup.SEPARATOR 128 + "The name of the language variant with code {1}”. For more information, please see " 129 + CLDRURLS.LANGUAGE_NAMES + ".\n" 130 131 + "^//ldml/characters/exemplarCharacters$" 132 + RegexLookup.SEPARATOR 133 + "Defines the set of characters used in your language. You may not edit or vote on this item at this time. Before filing any tickets to request changes, be sure to read " 134 + CLDRURLS.EXEMPLAR_CHARACTERS + ".\n" 135 + "^//ldml/characters/exemplarCharacters\\[@type=\"([^\"]*)\"]" 136 + RegexLookup.SEPARATOR 137 + "Defines the set of characters used in your language for the “{1}” category. You may not edit or vote on this item at this time. Before filing any tickets to request changes, be sure to read " 138 + CLDRURLS.EXEMPLAR_CHARACTERS + ".\n" 139 140 + "^//ldml/characters/parseLenients" 141 + RegexLookup.SEPARATOR 142 + "Defines sets of characters that are treated as equivalent in parsing. You may not edit or vote on this item at this time. Before filing any tickets to request changes, be sure to read " 143 + CLDRURLS.PARSE_LENIENT + ".\n" 144 145 + "^//ldml/characters/ellipsis\\[@type=\"([^\"]*)\"]" 146 + RegexLookup.SEPARATOR 147 + "Supply the ellipsis pattern for when the {1} part of a string is omitted. Note: before translating, be sure to read " 148 + CLDRURLS.CHARACTERS_HELP + ".\n" 149 + "^//ldml/characters/moreInformation" 150 + RegexLookup.SEPARATOR 151 + "The character or short string used to indicate that more information is available. Note: before translating, be sure to read " 152 + CLDRURLS.CHARACTERS_HELP + ".\n" 153 154 + "^//ldml/delimiters/alternateQuotationEnd" 155 + RegexLookup.SEPARATOR 156 + "Supply the (alternate) ending quotation mark (the right mark except in BIDI languages). Note: before translating, be sure to read " 157 + CLDRURLS.CHARACTERS_HELP + ".\n" 158 + "^//ldml/delimiters/alternateQuotationStart" 159 + RegexLookup.SEPARATOR 160 + "Supply the (alternate) starting quotation mark (the left mark except in BIDI languages). Note: before translating, be sure to read " 161 + CLDRURLS.CHARACTERS_HELP + ".\n" 162 + "^//ldml/delimiters/quotationEnd" 163 + RegexLookup.SEPARATOR 164 + "Supply the ending quotation mark (the right mark except in BIDI languages). Note: before translating, be sure to read " 165 + CLDRURLS.CHARACTERS_HELP + ".\n" 166 + "^//ldml/delimiters/quotationStart" 167 + RegexLookup.SEPARATOR 168 + "Supply the starting quotation mark (the left mark except in BIDI languages). Note: before translating, be sure to read " 169 + CLDRURLS.CHARACTERS_HELP + ".\n" 170 171 + "^//ldml/localeDisplayNames/localeDisplayPattern/localePattern" 172 + RegexLookup.SEPARATOR 173 + "The pattern used to compose locale (language) names. Note: before translating, be sure to read " 174 + CLDRURLS.LOCALE_PATTERN + ".\n" 175 + "^//ldml/localeDisplayNames/localeDisplayPattern/localeSeparator" 176 + RegexLookup.SEPARATOR 177 + "The separator used to compose modifiers in locale (language) names. Note: before translating, be sure to read " 178 + CLDRURLS.LOCALE_PATTERN + ".\n" 179 + "^//ldml/localeDisplayNames/localeDisplayPattern/localeKeyTypePattern" 180 + RegexLookup.SEPARATOR 181 + "The pattern used to compose key-type values in locale (language) names. Note: before translating, be sure to read " 182 + CLDRURLS.LOCALE_PATTERN + ".\n" 183 184 + "^//ldml/layout/orientation/characterOrder" 185 + RegexLookup.SEPARATOR 186 + "Specifies the horizontal direction of text in the language. Valid values are \"left-to-right\" or \"right-to-left\". For more information, see " 187 + CLDRURLS.UNITS_MISC_HELP + ".\n" 188 + "^//ldml/layout/orientation/lineOrder" 189 + RegexLookup.SEPARATOR 190 + "Specifies the vertical direction of text in the language. Valid values are \"top-to-bottom\" or \"bottom-to-top\". For more information, see " 191 + CLDRURLS.UNITS_MISC_HELP + ".\n" 192 193 + "^//ldml/numbers/symbols/(\\w++)" 194 + RegexLookup.SEPARATOR 195 + "The {1} symbol used in the localized form of numbers. Note: before translating, be sure to read " 196 + CLDRURLS.NUMBERS_HELP + ".\n" 197 + "^//ldml/numbers/symbols\\[@numberSystem=\"([a-z]*)\"]/(\\w++)" 198 + RegexLookup.SEPARATOR 199 + "The {2} symbol used in the {1} numbering system. NOTE: especially for the decimal and grouping symbol, before translating, be sure to read " 200 + CLDRURLS.NUMBERS_HELP + ".\n" 201 + "^//ldml/numbers/defaultNumberingSystem" 202 + RegexLookup.SEPARATOR 203 + "The default numbering system used in this locale. For more information, please see " 204 + CLDRURLS.NUMBERING_SYSTEMS + ".\n" 205 + "^//ldml/numbers/minimumGroupingDigits" 206 + RegexLookup.SEPARATOR 207 + "The default minimum number of digits before a grouping separator used in this locale. For more information, please see " 208 + CLDRURLS.NUMBERING_SYSTEMS + ".\n" 209 + "^//ldml/numbers/otherNumberingSystems/(\\w++)" 210 + RegexLookup.SEPARATOR 211 + "The {1} numbering system used in this locale. For more information, please see " 212 + CLDRURLS.NUMBERING_SYSTEMS + ".\n" 213 214 + "^//ldml/dates/timeZoneNames/regionFormat\\[@type=\"standard\"]" 215 + RegexLookup.SEPARATOR 216 + "The pattern used to compose standard (winter) fallback time zone names, such as 'Germany Winter Time'. Note: before translating, be sure to read " 217 + CLDRURLS.TZ_CITY_NAMES + ".\n" 218 + "^//ldml/dates/timeZoneNames/regionFormat\\[@type=\"daylight\"]" 219 + RegexLookup.SEPARATOR 220 + "The pattern used to compose daylight (summer) fallback time zone names, such as 'Germany Summer Time'. Note: before translating, be sure to read " 221 + CLDRURLS.TZ_CITY_NAMES + ".\n" 222 + "^//ldml/dates/timeZoneNames/regionFormat" 223 + RegexLookup.SEPARATOR 224 + "The pattern used to compose generic fallback time zone names, such as 'Germany Time'. Note: before translating, be sure to read " 225 + CLDRURLS.TZ_CITY_NAMES + ".\n" 226 + "^//ldml/dates/timeZoneNames/(fallback|fallbackRegion|gmtZero|gmt|hour|region)Format" 227 + RegexLookup.SEPARATOR 228 + "The {1} pattern used to compose time zone names. Note: before translating, be sure to read " 229 + CLDRURLS.TZ_CITY_NAMES + ".\n" 230 231 /* 232 * Warning: the longer match must come first 233 */ 234 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/compoundUnit\\[@type=\"([^\"]*)\"]/compoundUnitPattern1" 235 + RegexLookup.SEPARATOR 236 + "Special pattern used to compose powers of a unit, such as meters squared. Note: before translating, be sure to read " 237 + CLDRURLS.UNITS_HELP + ".\n" 238 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/compoundUnit\\[@type=\"([^\"]*)\"]/compoundUnitPattern" 239 + RegexLookup.SEPARATOR 240 + "Special pattern used to compose forms of two units, such as meters per second. Note: before translating, be sure to read " 241 + CLDRURLS.UNITS_HELP + ".\n" 242 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/compoundUnit\\[@type=\"([^\"]*)\"]/unitPrefixPattern" 243 + RegexLookup.SEPARATOR 244 + "Special pattern used to compose a metric prefix with a unit, such as kilo{0} with meters to produce kilometers. Note: before translating, be sure to read " 245 + CLDRURLS.UNITS_HELP + ".\n" 246 247 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/coordinateUnit/displayName" 248 + RegexLookup.SEPARATOR 249 + "Display name ({1} form) for the type of direction used in latitude and longitude, such as north or east. Note: before translating, be sure to read " 250 + CLDRURLS.UNITS_HELP + ".\n" 251 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/coordinateUnit/coordinateUnitPattern\\[@type=\"([^\"]*)\"]" 252 + RegexLookup.SEPARATOR 253 + "Special pattern used in latitude and longitude, such as 12°N. Note: before translating, be sure to read " 254 + CLDRURLS.UNITS_HELP + ".\n" 255 256 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"area-acre\"]/displayName" 257 + RegexLookup.SEPARATOR 258 + "Display name ({1} form) for “area-acre”, referring specifically to an English acre. Note: before translating, be sure to read " 259 + CLDRURLS.UNITS_HELP + ".\n" 260 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"duration-day\"]/displayName" 261 + RegexLookup.SEPARATOR 262 + "Display name ({1} form) for “duration-day”, meaning a time duration of 24 hours (not a calendar day). Note: before translating, be sure to read " 263 + CLDRURLS.UNITS_HELP + ".\n" 264 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"energy-calorie\"]/displayName" 265 + RegexLookup.SEPARATOR 266 + "Display name ({1} form) for “energy-calorie”, calories as used in chemistry, not the same as food calorie. Note: before translating, be sure to read " 267 + CLDRURLS.UNITS_HELP + ".\n" 268 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"energy-foodcalorie\"]/displayName" 269 + RegexLookup.SEPARATOR 270 + "Display name ({1} form) for “energy-foodcalorie”, kilocalories for food energy; may have same translation as energy-kilocalorie. Note: before translating, be sure to read " 271 + CLDRURLS.UNITS_HELP + ".\n" 272 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"energy-kilocalorie\"]/displayName" 273 + RegexLookup.SEPARATOR 274 + "Display name ({1} form) for “energy-kilocalorie”, kilocalories for uses not specific to food energy, such as chemistry. Note: before translating, be sure to read " 275 + CLDRURLS.UNITS_HELP + ".\n" 276 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-em\"]/displayName" 277 + RegexLookup.SEPARATOR 278 + "Display name ({1} form) for “graphics-em”, referring to typographic length equal to a font’s point size. Note: before translating, be sure to read " 279 + CLDRURLS.UNITS_HELP + ".\n" 280 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-pixel\"]/displayName" 281 + RegexLookup.SEPARATOR 282 + "Display name ({1} form) for “graphics-pixel”, used for counting the individual elements in bitmap image. Note: before translating, be sure to read " 283 + CLDRURLS.UNITS_HELP + ".\n" 284 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-megapixel\"]/displayName" 285 + RegexLookup.SEPARATOR 286 + "Display name ({1} form) for “graphics-megapixel”, used for counting the individual elements in bitmap image. Note: before translating, be sure to read " 287 + CLDRURLS.UNITS_HELP + ".\n" 288 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-pixel-per-centimeter\"]/displayName" 289 + RegexLookup.SEPARATOR 290 + "Display name ({1} form) for “graphics-pixel-per-centimeter”, typically used for display resolution. Note: before translating, be sure to read " 291 + CLDRURLS.UNITS_HELP + ".\n" 292 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-pixel-per-inch\"]/displayName" 293 + RegexLookup.SEPARATOR 294 + "Display name ({1} form) for “graphics-pixel-per-inch”, typically used for display resolution. Note: before translating, be sure to read " 295 + CLDRURLS.UNITS_HELP + ".\n" 296 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-dot-per-centimeter\"]/displayName" 297 + RegexLookup.SEPARATOR 298 + "Display name ({1} form) for “graphics-dot-per-centimeter”, typically used for printer resolution. Note: before translating, be sure to read " 299 + CLDRURLS.UNITS_HELP + ".\n" 300 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"graphics-dot-per-inch\"]/displayName" 301 + RegexLookup.SEPARATOR 302 + "Display name ({1} form) for “graphics-dot-per-inch”, typically used for printer resolution. Note: before translating, be sure to read " 303 + CLDRURLS.UNITS_HELP + ".\n" 304 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"length-point\"]/displayName" 305 + RegexLookup.SEPARATOR 306 + "Display name ({1} form) for “length-point”, referring to a typographic point, 1/72 inch. Note: before translating, be sure to read " 307 + CLDRURLS.UNITS_HELP + ".\n" 308 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"mass-stone\"]/displayName" 309 + RegexLookup.SEPARATOR 310 + "Display name ({1} form) for “mass-stone”, used in UK/Ireland for body weight, equal to 14 pounds. Note: before translating, be sure to read " 311 + CLDRURLS.UNITS_HELP + ".\n" 312 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"mass-ton\"]/displayName" 313 + RegexLookup.SEPARATOR 314 + "Display name ({1} form) for “mass-ton”, meaning U.S. short ton, not U.K. long ton or metric ton. Note: before translating, be sure to read " 315 + CLDRURLS.UNITS_HELP + ".\n" 316 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"([^\"]*)\"]/displayName" 317 + RegexLookup.SEPARATOR 318 + "Display name ({1} form) for “{2}”. Note: before translating, be sure to read " 319 + CLDRURLS.UNITS_HELP + ".\n" 320 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"([^\"]*)\"]/unitPattern" 321 + RegexLookup.SEPARATOR 322 + "[ICU Syntax] Special pattern used to compose plural for {1} forms of “{2}”. Note: before translating, be sure to read " 323 + CLDRURLS.PLURALS_HELP + ".\n" 324 + "^//ldml/units/unitLength\\[@type=\"([^\"]*)\"]/unit\\[@type=\"([^\"]*)\"]/perUnitPattern" 325 + RegexLookup.SEPARATOR 326 + "Special pattern ({1} form) used to compose values per unit, such as “meters per {2}”. Note: before translating, be sure to read " 327 + CLDRURLS.UNITS_HELP + ".\n" 328 329 + "^//ldml/units/durationUnit\\[@type=\"(hms|hm|ms)\"]" 330 + RegexLookup.SEPARATOR 331 + "[ICU Syntax] Special pattern used to compose duration units. Note: before translating, be sure to read " 332 + CLDRURLS.PLURALS_HELP + ".\n" 333 334 + "^//ldml/numbers/decimalFormats/decimalFormatLength\\[@type=\"([^\"]*)\"]/decimalFormat\\[@type=\"([^\"]*)\"]/pattern\\[@type=\"([^\"]*)\"]" 335 + RegexLookup.SEPARATOR 336 + "Special pattern used for a short version of numbers with the same number of digits as {3}. Note: before translating, be sure to read " 337 + CLDRURLS.NUMBERS_SHORT + ".\n" 338 + "^//ldml/numbers/currencyFormats\\[@numberSystem=\"([^\"]*)\"]/currencyFormatLength\\[@type=\"short\"]/currencyFormat\\[@type=\"standard\"]/pattern\\[@type=\"(\\d+)\"]\\[@count=\"([^\"]+)\"]" 339 + RegexLookup.SEPARATOR 340 + "Special currency pattern used to obtain the abbreviated plural forms of numbers with the same number of digits as {2}. See " 341 + CLDRURLS.NUMBERS_SHORT + " for details.\n" 342 + "^//ldml/numbers/decimalFormats\\[@numberSystem=\"([^\"]*)\"]/decimalFormatLength\\[@type=\"short\"]/decimalFormat\\[@type=\"standard\"]/pattern\\[@type=\"(\\d+)\"]\\[@count=\"([^\"]+)\"]" 343 + RegexLookup.SEPARATOR 344 + "Special decimal pattern used to obtain the abbreviated plural forms of numbers with the same number of digits as {2}. See " 345 + CLDRURLS.NUMBERS_SHORT + " for details.\n" 346 + "^//ldml/numbers/decimalFormats\\[@numberSystem=\"([^\"]*)\"]/decimalFormatLength\\[@type=\"long\"]/decimalFormat\\[@type=\"standard\"]/pattern\\[@type=\"(\\d+)\"]\\[@count=\"([^\"]+)\"]" 347 + RegexLookup.SEPARATOR 348 + "Special decimal pattern used to obtain the long plural forms of numbers with the same number of digits as {2}. See " 349 + CLDRURLS.NUMBERS_PLURAL + " for details.\n" 350 + "^//ldml/numbers/currencyFormats/currencyPatternAppendISO" 351 + RegexLookup.SEPARATOR 352 + "Pattern used to combine a regular currency format with an ISO 4217 code (¤¤). For more information, please see " 353 + CLDRURLS.NUMBER_PATTERNS + ".\n" 354 + "^//ldml/numbers/currencyFormats\\[@numberSystem=\"([^\"]*)\"]/currencyPatternAppendISO" 355 + RegexLookup.SEPARATOR 356 + "Pattern used to combine a regular currency format with an ISO 4217 code (¤¤). For more information, please see " 357 + CLDRURLS.NUMBER_PATTERNS + ".\n" 358 + "^//ldml/numbers/currencyFormats\\[@numberSystem=\"([^\"]*)\"]/unitPattern\\[@count=\"(\\w++)\"]" 359 + RegexLookup.SEPARATOR 360 + "Currency format used for numbers of type {2}. For more information, please see " 361 + CLDRURLS.NUMBER_PATTERNS + ".\n" 362 363 + "^//ldml/numbers/miscPatterns\\[@numberSystem=\"([^\"]*)\"]/pattern\\[@type=\"range\"]" 364 + RegexLookup.SEPARATOR 365 + "Format used to indicate a range of numbers. The '{'0'}' and '{'1'}' in the pattern represent the lowest and highest numbers in the range, respectively. For more information, please see " 366 + CLDRURLS.UNITS_MISC_HELP + ".\n" 367 + "^//ldml/numbers/miscPatterns\\[@numberSystem=\"([^\"]*)\"]/pattern\\[@type=\"atLeast\"]" 368 + RegexLookup.SEPARATOR 369 + "Format used to indicate a number is at least a certain value, often combined with other patterns to produce examples such as “≥12kg”. For more information, please see " 370 + CLDRURLS.UNITS_MISC_HELP + ".\n" 371 + "^//ldml/numbers/miscPatterns\\[@numberSystem=\"([^\"]*)\"]/pattern\\[@type=\"atMost\"]" 372 + RegexLookup.SEPARATOR 373 + "Format used to indicate a number is at most a certain value, often combined with other patterns to produce examples such as “≤12kg”. For more information, please see " 374 + CLDRURLS.UNITS_MISC_HELP + ".\n" 375 + "^//ldml/numbers/miscPatterns\\[@numberSystem=\"([^\"]*)\"]/pattern\\[@type=\"approximately\"]" 376 + RegexLookup.SEPARATOR 377 + "Format used to indicate a number is approximately a given value, often combined with other patterns to produce examples such as “~12kg”. For more information, please see " 378 + CLDRURLS.UNITS_MISC_HELP + ".\n" 379 380 + "^//ldml/numbers/minimalPairs/ordinalMinimalPairs\\[@ordinal=\"([^\"]*)\"]" 381 + RegexLookup.SEPARATOR 382 + "Minimal pairs for ordinals. For more information, please see " 383 + CLDRURLS.PLURALS_HELP_MINIMAL + ".\n" 384 + "^//ldml/numbers/minimalPairs/pluralMinimalPairs\\[@count=\"([^\"]*)\"]" 385 + RegexLookup.SEPARATOR 386 + "Minimal pairs for plurals (cardinals). For more information, please see " 387 + CLDRURLS.PLURALS_HELP_MINIMAL + ".\n" 388 + "^//ldml/numbers/minimalPairs/caseMinimalPairs\\[@case=\"([^\"]*)\"]" 389 + RegexLookup.SEPARATOR 390 + "Minimal pairs for cases used in the language. For more information, please see " 391 + CLDRURLS.GRAMMATICAL_INFLECTION + ".\n" 392 + "^//ldml/numbers/minimalPairs/genderMinimalPairs\\[@gender=\"([^\"]*)\"]" 393 + RegexLookup.SEPARATOR 394 + "Minimal pairs for genders. For more information, please see " 395 + CLDRURLS.GRAMMATICAL_INFLECTION + ".\n" 396 397 + "^//ldml/personNames/nameOrderLocales\\[@order=\"([^\"]*)\"]" 398 + RegexLookup.SEPARATOR 399 + "Person name order for locales. For more information, please see " 400 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 401 + "^//ldml/personNames/foreignSpaceReplacement" 402 + RegexLookup.SEPARATOR 403 + "For foreign personal names displayed in your locale, any special character that replaces a space (defaults to regular space). For more information, please see " 404 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 405 + "^//ldml/personNames/initialPattern\\[@type=\"initial\"]" 406 + RegexLookup.SEPARATOR 407 + "The pattern used for a single initial in person name formats. For more information, please see " 408 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 409 + "^//ldml/personNames/initialPattern\\[@type=\"initialSequence\"]" 410 + RegexLookup.SEPARATOR 411 + "The pattern used to compose sequences of initials in person name formats. For more information, please see " 412 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 413 + "^//ldml/personNames/personName\\[@order=\"([^\"]*)\"]\\[@length=\"([^\"]*)\"]\\[@usage=\"referring\"]\\[@formality=\"([^\"]*)\"]" 414 + RegexLookup.SEPARATOR 415 + "Person name formats for referring to a person (with a particular order, length, formality). For more information, please see " 416 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 417 + "^//ldml/personNames/personName\\[@order=\"([^\"]*)\"]\\[@length=\"([^\"]*)\"]\\[@usage=\"addressing\"]\\[@formality=\"([^\"]*)\"]" 418 + RegexLookup.SEPARATOR 419 + "Person name format for addressing a person (with a particular order, length, formality). For more information, please see " 420 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 421 + "^//ldml/personNames/personName\\[@order=\"([^\"]*)\"]\\[@length=\"([^\"]*)\"]\\[@usage=\"monogram\"]\\[@formality=\"([^\"]*)\"]" 422 + RegexLookup.SEPARATOR 423 + "Person name formats for monograms (with a particular order, length, formality). For more information, please see " 424 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 425 + "^//ldml/personNames/sampleName" 426 + RegexLookup.SEPARATOR 427 + "Sample names for person name format examples (enter ∅∅∅ for unused fields). For more information, please see " 428 + CLDRURLS.PERSON_NAME_FORMATS + ".\n" 429 430 + "^//ldml/numbers/([a-z]*)Formats(\\[@numberSystem=\"([^\"]*)\"])?/\\1FormatLength/\\1Format\\[@type=\"standard\"]/pattern\\[@type=\"standard\"]$" 431 + RegexLookup.SEPARATOR 432 + "Special pattern used to compose {1} numbers. Note: before translating, be sure to read " 433 + CLDRURLS.NUMBER_PATTERNS + ".\n" 434 + "^//ldml/numbers/currencyFormats\\[@numberSystem=\"([^\"]*)\"]/currencyFormatLength/currencyFormat\\[@type=\"standard\"]/pattern\\[@type=\"standard\"]\\[@alt=\"alphaNextToNumber\"]" 435 + RegexLookup.SEPARATOR 436 + "Special pattern used to compose currency values when the currency symbol has a letter adjacent to the number. Note: before translating, be sure to read " 437 + CLDRURLS.NUMBER_PATTERNS + ".\n" 438 + "^//ldml/numbers/currencyFormats\\[@numberSystem=\"([^\"]*)\"]/currencyFormatLength/currencyFormat\\[@type=\"standard\"]/pattern\\[@type=\"standard\"]\\[@alt=\"noCurrency\"]" 439 + RegexLookup.SEPARATOR 440 + "Special pattern used to compose currency values for which no currency symbol should be shown. Note: before translating, be sure to read " 441 + CLDRURLS.NUMBER_PATTERNS + ".\n" 442 + "^//ldml/numbers/currencyFormats\\[@numberSystem=\"([^\"]*)\"]/currencyFormatLength/currencyFormat\\[@type=\"accounting\"]/pattern" 443 + RegexLookup.SEPARATOR 444 + "Special pattern used to compose currency values for accounting purposes. Note: before translating, be sure to read " 445 + CLDRURLS.NUMBER_PATTERNS + ".\n" 446 447 + "^//ldml/numbers/currencyFormats/currencySpacing/([a-zA-Z]*)/([a-zA-Z]*)" 448 + RegexLookup.SEPARATOR 449 + "Special pattern used to compose currency signs ($1/$2) with numbers. Note: before translating, be sure to read " 450 + CLDRURLS.NUMBER_PATTERNS + ".\n" 451 452 + "^//ldml/listPatterns/listPattern/listPatternPart\\[@type=\"2\"]" 453 + RegexLookup.SEPARATOR 454 + "Special pattern used to make an “and” list out of two standard elements. Note: before translating, be sure to read " 455 + CLDRURLS.LISTS_HELP + ".\n" 456 + "^//ldml/listPatterns/listPattern/listPatternPart\\[@type=\"([^\"]*)\"]" 457 + RegexLookup.SEPARATOR 458 + "Special pattern used to make a “and” list out of more than two standard elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 459 + CLDRURLS.LISTS_HELP + ".\n" 460 461 + "^//ldml/listPatterns/listPattern\\[@type=\"standard-short\"]/listPatternPart\\[@type=\"2\"]" 462 + RegexLookup.SEPARATOR 463 + "Special pattern used to make a short-style “and” list out of two standard elements. Note: before translating, be sure to read " 464 + CLDRURLS.LISTS_HELP + ".\n" 465 + "^//ldml/listPatterns/listPattern\\[@type=\"standard-short\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 466 + RegexLookup.SEPARATOR 467 + "Special pattern used to make a short-style “and” list out of more than two standard elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 468 + CLDRURLS.LISTS_HELP + ".\n" 469 470 + "^//ldml/listPatterns/listPattern\\[@type=\"standard-narrow\"]/listPatternPart\\[@type=\"2\"]" 471 + RegexLookup.SEPARATOR 472 + "Special pattern used to make a short-style “and” list out of two standard elements. Note: before translating, be sure to read " 473 + CLDRURLS.LISTS_HELP + ".\n" 474 + "^//ldml/listPatterns/listPattern\\[@type=\"standard-narrow\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 475 + RegexLookup.SEPARATOR 476 + "Special pattern used to make a short-style “and” list out of more than two standard elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 477 + CLDRURLS.LISTS_HELP + ".\n" 478 479 + "^//ldml/listPatterns/listPattern\\[@type=\"or\"]/listPatternPart\\[@type=\"2\"]" 480 + RegexLookup.SEPARATOR 481 + "Special pattern used to make an “or” list out of two standard elements. Note: before translating, be sure to read " 482 + CLDRURLS.LISTS_HELP + ".\n" 483 + "^//ldml/listPatterns/listPattern\\[@type=\"or\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 484 + RegexLookup.SEPARATOR 485 + "Special pattern used to make an “or” list out of more than two standard elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 486 + CLDRURLS.LISTS_HELP + ".\n" 487 488 + "^//ldml/listPatterns/listPattern\\[@type=\"or-short\"]/listPatternPart\\[@type=\"2\"]" 489 + RegexLookup.SEPARATOR 490 + "Special pattern used to make an “or” list out of two standard elements. Note: before translating, be sure to read " 491 + CLDRURLS.LISTS_HELP + ".\n" 492 + "^//ldml/listPatterns/listPattern\\[@type=\"or-short\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 493 + RegexLookup.SEPARATOR 494 + "Special pattern used to make an “or” list out of more than two standard elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 495 + CLDRURLS.LISTS_HELP + ".\n" 496 497 + "^//ldml/listPatterns/listPattern\\[@type=\"or-narrow\"]/listPatternPart\\[@type=\"2\"]" 498 + RegexLookup.SEPARATOR 499 + "Special pattern used to make an “or” list out of two standard elements. Note: before translating, be sure to read " 500 + CLDRURLS.LISTS_HELP + ".\n" 501 + "^//ldml/listPatterns/listPattern\\[@type=\"or-narrow\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 502 + RegexLookup.SEPARATOR 503 + "Special pattern used to make an “or” list out of more than two standard elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 504 + CLDRURLS.LISTS_HELP + ".\n" 505 506 + "^//ldml/listPatterns/listPattern\\[@type=\"unit\"]/listPatternPart\\[@type=\"2\"]" 507 + RegexLookup.SEPARATOR 508 + "Special pattern used to make a list out of two unit elements. Note: before translating, be sure to read " 509 + CLDRURLS.LISTS_HELP + ".\n" 510 + "^//ldml/listPatterns/listPattern\\[@type=\"unit\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 511 + RegexLookup.SEPARATOR 512 + "Special pattern used to make a list out of more than two unit elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 513 + CLDRURLS.LISTS_HELP + ".\n" 514 515 + "^//ldml/listPatterns/listPattern\\[@type=\"unit-short\"]/listPatternPart\\[@type=\"2\"]" 516 + RegexLookup.SEPARATOR 517 + "Special pattern used to make a list out of two abbreviated unit elements. Note: before translating, be sure to read " 518 + CLDRURLS.LISTS_HELP + ".\n" 519 + "^//ldml/listPatterns/listPattern\\[@type=\"unit-short\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 520 + RegexLookup.SEPARATOR 521 + "Special pattern used to make a list out of more than two abbreviated unit elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 522 + CLDRURLS.LISTS_HELP + ".\n" 523 524 + "^//ldml/listPatterns/listPattern\\[@type=\"unit-narrow\"]/listPatternPart\\[@type=\"2\"]" 525 + RegexLookup.SEPARATOR 526 + "Special pattern used to make a list out of two narrow unit elements. Note: before translating, be sure to read " 527 + CLDRURLS.LISTS_HELP + ".\n" 528 + "^//ldml/listPatterns/listPattern\\[@type=\"unit-narrow\"]/listPatternPart\\[@type=\"([^\"]*)\"]" 529 + RegexLookup.SEPARATOR 530 + "Special pattern used to make a list out of more than two narrow unit elements. This is used for the {1} portion of the list. Note: before translating, be sure to read " 531 + CLDRURLS.LISTS_HELP + ".\n" 532 533 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dayPeriods/dayPeriodContext\\[@type=\"(format)\"]/dayPeriodWidth\\[@type=\"([^\"]*)\"]/dayPeriod\\[@type=\"([^\"]*)\"]" 534 + RegexLookup.SEPARATOR 535 + "Provide the {3}, {2} version of the name for the day period code “{4}”. This version must have the right inflection/prepositions/etc. for adding after a number, such as “in the morning” for use in “10:00 in the morning”. To see the time spans for these codes, please see " 536 + CLDRURLS.DATE_TIME_HELP + "\n" 537 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dayPeriods/dayPeriodContext\\[@type=\"([^\"]*)\"]/dayPeriodWidth\\[@type=\"([^\"]*)\"]/dayPeriod\\[@type=\"([^\"]*)\"]" 538 + RegexLookup.SEPARATOR 539 + "Provide the {3}, {2} version of the name for the day period code “{4}”. To see the time spans for these codes, please see " 540 + CLDRURLS.DATE_TIME_HELP + "\n" 541 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/days/dayContext\\[@type=\"([^\"]*)\"]/dayWidth\\[@type=\"([^\"]*)\"]/day\\[@type=\"([^\"]*)\"]" 542 + RegexLookup.SEPARATOR 543 + "Provide the {2} and {3} version of the name for day-of-the-week {4}. For more information, please see " 544 + CLDRURLS.DATE_TIME_NAMES + ".\n" 545 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/eras/eraAbbr/era\\[@type=\"([^\"]*)\"]" 546 + RegexLookup.SEPARATOR 547 + "Provide the format-abbreviated version of the name for era {4}. For more information, please see " 548 + CLDRURLS.DATE_TIME_NAMES + ".\n" 549 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/eras/eraNames/era\\[@type=\"([^\"]*)\"]" 550 + RegexLookup.SEPARATOR 551 + "Provide the format-wide version of the name for era {4}. For more information, please see " 552 + CLDRURLS.DATE_TIME_NAMES + ".\n" 553 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/eras/eraNarrow/era\\[@type=\"([^\"]*)\"]" 554 + RegexLookup.SEPARATOR 555 + "Provide the format-narrow version of the name for era {4}. For more information, please see " 556 + CLDRURLS.DATE_TIME_NAMES + ".\n" 557 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/months/monthContext\\[@type=\"([^\"]*)\"]/monthWidth\\[@type=\"([^\"]*)\"]/month\\[@type=\"([^\"]*)\"]" 558 + RegexLookup.SEPARATOR 559 + "Provide the {2} and {3} version of the name for month {4}. For more information, please see " 560 + CLDRURLS.DATE_TIME_NAMES + ".\n" 561 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/quarters/quarterContext\\[@type=\"([^\"]*)\"]/quarterWidth\\[@type=\"([^\"]*)\"]/quarter\\[@type=\"([^\"]*)\"]" 562 + RegexLookup.SEPARATOR 563 + "Provide the {2} and {3} version of the name for quarter {4}. For more information, please see " 564 + CLDRURLS.DATE_TIME_NAMES + ".\n" 565 566 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/displayName" 567 + RegexLookup.SEPARATOR 568 + "Provide the name (as it would appear in menus) for the field “{1}”. For more information, please see " 569 + CLDRURLS.DATE_TIME_NAMES_FIELD + ".\n" 570 571 + "^//ldml/dates/fields/field\\[@type=\"day\"]/relative\\[@type=\"0\"]" 572 + RegexLookup.SEPARATOR 573 + "Provide the name for today. For more information, please see " 574 + CLDRURLS.DATE_TIME_NAMES_RELATIVE + ".\n" 575 + "^//ldml/dates/fields/field\\[@type=\"day\"]/relative\\[@type=\"-([^\"]*)\"]" 576 + RegexLookup.SEPARATOR 577 + "Provide a name for the day, {1} before today. For more information, please see " 578 + CLDRURLS.DATE_TIME_NAMES_RELATIVE + ".\n" 579 + "^//ldml/dates/fields/field\\[@type=\"day\"]/relative\\[@type=\"([^\"]*)\"]" 580 + RegexLookup.SEPARATOR 581 + "Provide a name for the day, {1} after today. For more information, please see " 582 + CLDRURLS.DATE_TIME_NAMES_RELATIVE + ".\n" 583 584 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/relative\\[@type=\"0\"]" 585 + RegexLookup.SEPARATOR 586 + "Provide the name for “this {2}”. For more information, please see " 587 + CLDRURLS.DATE_TIME_NAMES_RELATIVE + ".\n" 588 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/relative\\[@type=\"-1\"]" 589 + RegexLookup.SEPARATOR 590 + "Provide a name for “last {1}”. For more information, please see " 591 + CLDRURLS.DATE_TIME_NAMES_RELATIVE + ".\n" 592 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/relative\\[@type=\"1\"]" 593 + RegexLookup.SEPARATOR 594 + "Provide a name for “next {1}”. For more information, please see " 595 + CLDRURLS.DATE_TIME_NAMES_RELATIVE + ".\n" 596 597 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/relativeTime\\[@type=\"future\"]/relativeTimePattern\\[@count=\"([^\"]*)\"]" 598 + RegexLookup.SEPARATOR 599 + "Provide a pattern used to display times in the future. For more information, please see " 600 + CLDRURLS.DATE_TIME_NAMES + ".\n" 601 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/relativeTime\\[@type=\"past\"]/relativeTimePattern\\[@count=\"([^\"]*)\"]" 602 + RegexLookup.SEPARATOR 603 + "Provide a pattern used to display times in the past. For more information, please see " 604 + CLDRURLS.DATE_TIME_NAMES + ".\n" 605 606 + "^//ldml/dates/fields/field\\[@type=\"([^\"]*)\"]/relativePeriod" 607 + RegexLookup.SEPARATOR 608 + "Provide a name for “the {1} of SOME_DATE”. For more information, please see " 609 + CLDRURLS.DATE_TIME_NAMES + ".\n" 610 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateTimeFormats/dateTimeFormatLength\\[@type=\"([^\"]*)\"]/dateTimeFormat\\[@type=\"standard\"]/pattern\\[@type=\"([^\"]*)\"]" 611 + RegexLookup.SEPARATOR 612 + "Provide the {2} version of the date-time pattern suitable for most use cases, including combining a date with a time range. Note: before translating, be sure to read " 613 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 614 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateTimeFormats/dateTimeFormatLength\\[@type=\"([^\"]*)\"]/dateTimeFormat\\[@type=\"atTime\"]/pattern\\[@type=\"([^\"]*)\"]" 615 + RegexLookup.SEPARATOR 616 + "Provide the {2} version of the date-time pattern suitable for expressing a date at a specific time. Note: before translating, be sure to read " 617 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 618 619 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateFormats/dateFormatLength\\[@type=\"([^\"]*)\"]/dateFormat\\[@type=\"([^\"]*)\"]/pattern\\[@type=\"([^\"]*)\"]" 620 + RegexLookup.SEPARATOR 621 + "Provide the {2} version of the basic date pattern. Note: before translating, be sure to read " 622 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 623 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/timeFormats/timeFormatLength\\[@type=\"([^\"]*)\"]/timeFormat\\[@type=\"([^\"]*)\"]/pattern\\[@type=\"([^\"]*)\"]" 624 + RegexLookup.SEPARATOR 625 + "Provide the {2} version of the basic time pattern. Note: before translating, be sure to read " 626 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 627 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateTimeFormats/availableFormats/dateFormatItem\\[@id=\"([^\"]*)\"]" 628 + RegexLookup.SEPARATOR 629 + "Provide the pattern used in your language for the skeleton “{2}”. Note: before translating, be sure to read " 630 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 631 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateTimeFormats/appendItems/appendItem\\[@request=\"([^\"]*)\"]" 632 + RegexLookup.SEPARATOR 633 + "Provide the pattern used in your language to append a “{2}” to another format. Note: before translating, be sure to read " 634 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 635 636 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateTimeFormats/intervalFormats/intervalFormatFallback" 637 + RegexLookup.SEPARATOR 638 + "The pattern used for “fallback” with date/time intervals. Note: before translating, be sure to read " 639 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 640 + "^//ldml/dates/calendars/calendar\\[@type=\"([^\"]*)\"]/dateTimeFormats/intervalFormats/intervalFormatItem\\[@id=\"([^\"]*)\"]/greatestDifference\\[@id=\"([^\"]*)\"]" 641 + RegexLookup.SEPARATOR 642 + "The pattern used for the date/time interval skeleton “{2}” when the greatest difference is “{3}”. Note: before translating, be sure to read " 643 + CLDRURLS.DATE_TIME_PATTERNS + ".\n" 644 645 + "^//ldml/dates/calendars/calendar\\[@type=\"[^\"]*\"]/cyclicNameSets/cyclicNameSet\\[@type=\"([^\"]*)\"]/cyclicNameContext\\[@type=\"([^\"]*)\"]/cyclicNameWidth\\[@type=\"([^\"]*)\"]/cyclicName\\[@type=\"([^\"]*)\"]" 646 + RegexLookup.SEPARATOR 647 + "Provide the {2} and {3} version of type {4} in the {1} name cycle. For more information, please see " 648 + CLDRURLS.DATE_TIME_NAMES_CYCLIC + ".\n" 649 + "^//ldml/dates/calendars/calendar\\[@type=\"[^\"]*\"]/monthPatterns/monthPatternContext\\[@type=\"([^\"]*)\"]/monthPatternWidth\\[@type=\"([^\"]*)\"]/monthPattern\\[@type=\"([^\"]*)\"]" 650 + RegexLookup.SEPARATOR 651 + "Provide the {1} and {2} version of the name for {3} month types. For more information, please see " 652 + CLDRURLS.DATE_TIME_NAMES_MONTH + ".\n" 653 654 + "^//ldml/localeDisplayNames/transformNames/transformName\\[@type=\"([^\"]*)\"]" 655 + RegexLookup.SEPARATOR 656 + "The name of the transform “{1}”. For more information, please see " 657 + CLDRURLS.TRANSFORMS_HELP + ".\n" 658 659 + "^//ldml/localeDisplayNames/codePatterns/codePattern[@type=\"([^\"]*)\"]" 660 + RegexLookup.SEPARATOR 661 + "The pattern to be used when displaying a name for a character {1}. For more information, please see " 662 + CLDRURLS.LOCALE_PATTERN + ".\n" 663 664 + "^//ldml/localeDisplayNames/measurementSystemNames/measurementSystemName\\[@type=\"([^\"]*)\"]" 665 + RegexLookup.SEPARATOR 666 + "The name of the measurement system “{1}”. For more information, please see " 667 + CLDRURLS.UNITS_MISC_HELP + ".\n" 668 + "^//ldml/posix/messages/(no|yes)str" 669 + RegexLookup.SEPARATOR 670 + "The word for “{1}”, lowercased, plus any abbreviations separated by a colon. For more information, see " 671 + CLDRURLS.UNITS_MISC_HELP + ".\n" 672 673 + "^//ldml/localeDisplayNames/annotationPatterns/annotationPattern[@type=\"([^\"]*)\"]" 674 + RegexLookup.SEPARATOR 675 + "The pattern to be used when displaying a {1}. For more information, please see " 676 + CLDRURLS.LOCALE_PATTERN + ".\n" 677 678 + "^//ldml/characters/stopwords/stopwordList\\[@type=\"([^\"]*)\"]" 679 + RegexLookup.SEPARATOR 680 + "The words that should be ignored in sorting in your language. For more information, see " 681 + CLDRURLS.UNITS_MISC_HELP + ".\n" 682 + "^//ldml/dates/timeZoneNames/zone\\[@type=\"([^\"]*)\"]/([^/]*)/(.*)" 683 + RegexLookup.SEPARATOR 684 + "Override for the $3-$2 timezone name for $1. For more information, see " 685 + CLDRURLS.TZ_CITY_NAMES + ".\n" 686 687 + "^//ldml/typographicNames/axisName[@type=\"([^\"]*)\"]" 688 + RegexLookup.SEPARATOR 689 + "A label for a typographic design axis, such as “Width” or “Weight”. For more information, see " 690 + CLDRURLS.TYPOGRAPHIC_NAMES + ".\n" 691 + "^//ldml/typographicNames/styleName[@type=\"([^\"]*)\"][@subtype=\"([^\"]*)\"]" 692 + RegexLookup.SEPARATOR 693 + "A label for a typographic style, such as “Narrow” or “Semibold”. For more information, see " 694 + CLDRURLS.TYPOGRAPHIC_NAMES + ".\n" 695 + "^//ldml/typographicNames/featureName[@type=\"([^\"]*)\"]" 696 + RegexLookup.SEPARATOR 697 + "A label for a typographic feature, such as “Small Capitals”. For more information, see " 698 + CLDRURLS.TYPOGRAPHIC_NAMES + ".\n" 699 700 + "^//ldml/characterLabels/characterLabelPattern\\[@type=\"([^\"]*)\"]\\[@count=\"([^\"]*)\"]" 701 + RegexLookup.SEPARATOR 702 + "A label for a set of characters that has a numeric placeholder, such as “1 Stroke”, “2 Strokes”. For more information, see " 703 + CLDRURLS.CHARACTER_LABELS + ".\n" 704 + "^//ldml/characterLabels/characterLabelPattern\\[@type=\"([^\"]*)\"]" 705 + RegexLookup.SEPARATOR 706 + "A modifier composed with a label for a set of characters. For more information, see " 707 + CLDRURLS.CHARACTER_LABELS + ".\n" 708 + "^//ldml/characterLabels/characterLabel\\[@type=\"([^\"]*)\"]" 709 + RegexLookup.SEPARATOR 710 + "A label for a set of characters. For more information, see " 711 + CLDRURLS.CHARACTER_LABELS + ".\n" 712 713 + "^//ldml/annotations/annotation\\[@cp=\"([^\"]*)\"]\\[@type=\"tts\"]" 714 + RegexLookup.SEPARATOR 715 + "A name for a character or sequence. For more information, see " 716 + CLDRURLS.SHORT_CHARACTER_NAMES + ".\n" 717 + "^//ldml/annotations/annotation\\[@cp=\"([^\"]*)\"]" 718 + RegexLookup.SEPARATOR 719 + "A set of keywords for a character or sequence. For more information, see " 720 + CLDRURLS.SHORT_CHARACTER_NAMES + ".\n"; 721 722 private final static Logger logger = Logger.getLogger(PathDescription.class.getName()); 723 724 public enum ErrorHandling { 725 SKIP, CONTINUE 726 } 727 728 public static final Set<String> EXTRA_LANGUAGES = new TreeSet<>( 729 Arrays 730 .asList( 731 "ach|af|ak|ak|am|ar|az|be|bem|bg|bh|bn|br|bs|ca|chr|ckb|co|crs|cs|cy|da|de|de_AT|de_CH|ee|el|en|en_AU|en_CA|en_GB|en_US|eo|es|es_419|es_ES|et|eu|fa|fi|fil|fo|fr|fr_CA|fr_CH|fy|ga|gaa|gd|gl|gn|gsw|gu|ha|haw|he|hi|hr|ht|hu|hy|ia|id|ig|io|is|it|ja|jv|ka|kg|kk|km|kn|ko|kri|ku|ky|la|lg|ln|lo|loz|lt|lua|lv|mfe|mg|mi|mk|ml|mn|mr|ms|mt|my|nb|ne|nl|nl_BE|nn|no|nso|ny|nyn|oc|om|or|pa|pcm|pl|ps|pt|pt_BR|pt_PT|qu|rm|rn|ro|ro|ro_MD|ru|rw|sd|si|sk|sl|sn|so|sq|sr|sr_Latn|sr_ME|st|su|sv|sw|ta|te|tg|th|ti|tk|tlh|tn|to|tr|tt|tum|ug|uk|und|ur|uz|vi|wo|xh|yi|yo|zh|zh_Hans|zh_Hant|zh_HK|zu|zxx" 732 .split("|"))); 733 734 private static final Pattern METAZONE_PATTERN = Pattern 735 .compile("//ldml/dates/timeZoneNames/metazone\\[@type=\"([^\"]*)\"]/(.*)/(.*)"); 736 private static final Pattern STAR_ATTRIBUTE_PATTERN = PatternCache.get("=\"([^\"]*)\""); 737 738 private static final StandardCodes STANDARD_CODES = StandardCodes.make(); 739 private static Map<String, String> ZONE2COUNTRY = STANDARD_CODES.zoneParser.getZoneToCounty(); 740 741 private static RegexLookup<String> pathHandling = new RegexLookup<String>().loadFromString(pathDescriptionString); 742 743 // set in construction 744 745 private final CLDRFile english; 746 private final Map<String, String> extras; 747 private final ErrorHandling errorHandling; 748 private final Map<String, List<Set<String>>> starredPaths; 749 private final Set<String> allMetazones; 750 751 // used on instance 752 753 private Matcher metazoneMatcher = METAZONE_PATTERN.matcher(""); 754 private String starredPathOutput; 755 private Output<String[]> pathArguments = new Output<>(); 756 private EnumSet<Status> status = EnumSet.noneOf(Status.class); 757 758 public static final String MISSING_DESCRIPTION = "Before translating, please see " + CLDRURLS.GENERAL_HELP_URL + "."; 759 PathDescription(SupplementalDataInfo supplementalDataInfo, CLDRFile english, Map<String, String> extras, Map<String, List<Set<String>>> starredPaths, ErrorHandling errorHandling)760 public PathDescription(SupplementalDataInfo supplementalDataInfo, 761 CLDRFile english, 762 Map<String, String> extras, 763 Map<String, List<Set<String>>> starredPaths, 764 ErrorHandling errorHandling) { 765 this.english = english; 766 this.extras = extras == null ? new HashMap<>() : extras; 767 this.starredPaths = starredPaths == null ? new HashMap<>() : starredPaths; 768 allMetazones = supplementalDataInfo.getAllMetazones(); 769 this.errorHandling = errorHandling; 770 } 771 getStarredPathOutput()772 public String getStarredPathOutput() { 773 return starredPathOutput; 774 } 775 getStatus()776 public EnumSet<Status> getStatus() { 777 return status; 778 } 779 780 public enum Status { 781 SKIP, NULL_VALUE, EMPTY_CONTENT, NOT_REQUIRED 782 } 783 getRawDescription(String path, String value, Object context)784 public String getRawDescription(String path, String value, Object context) { 785 status.clear(); 786 return pathHandling.get(path, context, pathArguments); 787 } 788 getDescription(String path, String value, Level level, Object context)789 public String getDescription(String path, String value, Level level, Object context) { 790 status.clear(); 791 792 String description = pathHandling.get(path, context, pathArguments); 793 if (description == null) { 794 description = MISSING_DESCRIPTION; 795 } else if ("SKIP".equals(description)) { 796 status.add(Status.SKIP); 797 if (errorHandling == ErrorHandling.SKIP) { 798 return null; 799 } 800 } 801 if (value == null) { // a count item? 802 String xpath = extras.get(path); 803 if (xpath != null) { 804 value = english.getStringValue(xpath); 805 } else if (path.contains("/metazone")) { 806 if (metazoneMatcher.reset(path).matches()) { 807 String name = metazoneMatcher.group(1); 808 String type = metazoneMatcher.group(3); 809 value = name.replace('_', ' ') 810 + (type.equals("generic") ? "" : type.equals("daylight") ? " Summer" : " Winter") + " Time"; 811 } 812 } 813 if (value == null) { 814 status.add(Status.NULL_VALUE); 815 if (errorHandling == ErrorHandling.SKIP) { 816 return null; 817 } 818 } 819 } 820 if (value != null && value.length() == 0) { 821 status.add(Status.EMPTY_CONTENT); 822 if (errorHandling == ErrorHandling.SKIP) { 823 return null; 824 } 825 } 826 827 List<String> attributes = addStarredInfo(starredPaths, path); 828 829 // In special cases, only use if there is a root value (languageNames, ... 830 if (description.startsWith("ROOT")) { 831 int typeEnd = description.indexOf(';'); 832 String type = description.substring(4, typeEnd).trim(); 833 description = description.substring(typeEnd + 1).trim(); 834 835 boolean isMetazone = type.equals("metazone"); 836 String code = attributes.get(0); 837 boolean isRootCode = isRootCode(code, allMetazones, type, isMetazone); 838 if (!isRootCode) { 839 status.add(Status.NOT_REQUIRED); 840 if (errorHandling == ErrorHandling.SKIP) { 841 return null; 842 } 843 } 844 if (isMetazone) { 845 XPathParts parts = XPathParts.getFrozenInstance(path); 846 String daylightType = parts.getElement(-1); 847 daylightType = daylightType.equals("daylight") ? "summer" 848 : daylightType.equals("standard") ? "winter" 849 : daylightType; 850 String length = parts.getElement(-2); 851 length = length.equals("long") ? "" : "abbreviated "; 852 code = code + ", " + length + daylightType + " form"; 853 } else if (type.equals("timezone")) { 854 String country = ZONE2COUNTRY.get(code); 855 int lastSlash = code.lastIndexOf('/'); 856 String codeName = lastSlash < 0 ? code : code.substring(lastSlash + 1).replace('_', ' '); 857 858 boolean found = false; 859 if ("001".equals(country)) { 860 code = "the timezone “" + codeName + "”"; 861 found = true; 862 } else if (country != null) { 863 String countryName = english.getName("territory", country); 864 if (countryName != null) { 865 if (!codeName.equals(countryName)) { 866 code = "the city “" + codeName + "” (in " + countryName + ")"; 867 } else { 868 code = "the country “" + codeName + "”"; 869 } 870 found = true; 871 } 872 } 873 if (!found) { 874 logger.warning("Missing country for timezone " + code); 875 } 876 } 877 description = MessageFormat.format(MessageFormat.autoQuoteApostrophe(description), new Object[] { code }); 878 } else if (path.contains("exemplarCity")) { 879 String regionCode = ZONE2COUNTRY.get(attributes.get(0)); 880 String englishRegionName = english.getName(CLDRFile.TERRITORY_NAME, regionCode); 881 description = MessageFormat.format(MessageFormat.autoQuoteApostrophe(description), 882 new Object[] { englishRegionName }); 883 } else if (description != MISSING_DESCRIPTION) { 884 description = MessageFormat.format(MessageFormat.autoQuoteApostrophe(description), 885 (Object[]) pathArguments.value); 886 } 887 888 return description; 889 } 890 891 /** 892 * Creates an escaped HTML string of placeholder information. 893 * 894 * @param path 895 * the xpath to specify placeholder information for 896 * @return a HTML string, or an empty string if there was no placeholder information 897 */ 898 public String getPlaceholderDescription(String path) { 899 Map<String, PlaceholderInfo> placeholders = PatternPlaceholders.getInstance().get(path); 900 if (placeholders != null && placeholders.size() > 0) { 901 StringBuffer buffer = new StringBuffer(); 902 buffer.append("<table>"); 903 buffer.append("<tr><th>Placeholder</th><th>Meaning</th><th>Example</th></tr>"); 904 for (Entry<String, PlaceholderInfo> entry : placeholders.entrySet()) { 905 PlaceholderInfo info = entry.getValue(); 906 buffer.append("<tr>"); 907 buffer.append("<td>").append(entry.getKey()).append("</td>"); 908 buffer.append("<td>").append(info.name).append("</td>"); 909 buffer.append("<td>").append(info.example).append("</td>"); 910 buffer.append("</tr>"); 911 } 912 buffer.append("</table>"); 913 return buffer.toString(); 914 } 915 return ""; 916 } 917 isRootCode(String code, Set<String> allMetazones, String type, boolean isMetazone)918 private static boolean isRootCode(String code, Set<String> allMetazones, String type, boolean isMetazone) { 919 Set<String> codes = isMetazone ? allMetazones 920 : type.equals("timezone") ? STANDARD_CODES.zoneParser.getZoneData().keySet() 921 : STANDARD_CODES.getSurveyToolDisplayCodes(type); 922 // end 923 boolean isRootCode = codes.contains(code) || code.contains("_"); 924 if (!isRootCode && type.equals("language") 925 && EXTRA_LANGUAGES.contains(code)) { 926 isRootCode = true; 927 } 928 return isRootCode; 929 } 930 addStarredInfo(Map<String, List<Set<String>>> starredPaths, String path)931 private List<String> addStarredInfo(Map<String, List<Set<String>>> starredPaths, String path) { 932 Matcher starAttributeMatcher = STAR_ATTRIBUTE_PATTERN.matcher(path); 933 StringBuilder starredPath = new StringBuilder(); 934 List<String> attributes = new ArrayList<>(); 935 int lastEnd = 0; 936 while (starAttributeMatcher.find()) { 937 int start = starAttributeMatcher.start(1); 938 int end = starAttributeMatcher.end(1); 939 starredPath.append(path.substring(lastEnd, start)); 940 starredPath.append(".*"); 941 942 attributes.add(path.substring(start, end)); 943 lastEnd = end; 944 } 945 starredPath.append(path.substring(lastEnd)); 946 String starredPathString = starredPath.toString().intern(); 947 starredPathOutput = starredPathString; 948 949 List<Set<String>> attributeList = starredPaths.get(starredPathString); 950 if (attributeList == null) { 951 starredPaths.put(starredPathString, attributeList = new ArrayList<>()); 952 } 953 int i = 0; 954 for (String attribute : attributes) { 955 if (attributeList.size() <= i) { 956 TreeSet<String> subset = new TreeSet<>(); 957 subset.add(attribute); 958 attributeList.add(subset); 959 } else { 960 Set<String> subset = attributeList.get(i); 961 subset.add(attribute); 962 } 963 ++i; 964 } 965 return attributes; 966 } 967 } 968