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