• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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