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