@@ -68,8 +68,8 @@ public LanguageLookup(bool ensureDefaultTags = false)
6868
6969 foreach ( AllTagEntry entry in rootObject )
7070 {
71- // tags starting with x- have undefined structure so ignoring them as well as deprecated tags
72- // tags starting with _ may provide some sort of undefined variant information, but we ignore them as well
71+ // Tags starting with x- have undefined structure, so ignoring them as well as deprecated tags.
72+ // Tags starting with _ may provide some sort of undefined variant information, but we ignore them as well.
7373 if ( ! entry . deprecated && ! entry . tag . StartsWith ( "x-" , StringComparison . Ordinal ) && ! entry . tag . StartsWith ( "_" , StringComparison . Ordinal ) )
7474 {
7575 AddLanguage ( entry . tag , entry . iso639_3 , entry . full , entry . name , entry . localname , entry . region , entry . names , entry . regions , entry . tags , entry . iana , entry . regionName ) ;
@@ -82,10 +82,10 @@ public LanguageLookup(bool ensureDefaultTags = false)
8282
8383 /// <summary>
8484 /// Some languages in langtags.json have not been normalized to have a default tag without a script marker
85- /// in one of its entries. For some uses of the data, we really want to see only the default tags but we
86- /// also don't want to not see any languages. So scan through the data for cases where every tag associated
85+ /// in one of its entries. For some uses of the data, we really want to see only the default tags, but we
86+ /// also don't want to not see any languages. So scan through the data for cases where every tag associated
8787 /// with a language contains a script marker and choose one as the default to receive a minimal tag that is
88- /// equal to the language code alone. (The one found in the most countries is chosen by default.)
88+ /// equal to the language code alone. (The one found in the most countries is chosen by default.)
8989 /// </summary>
9090 private void EnsureDefaultTags ( )
9191 {
@@ -99,11 +99,7 @@ private void EnsureDefaultTags()
9999 for ( var i = 0 ; i < tagList . Count ; ++ i )
100100 {
101101 var tag = tagList [ i ] ;
102- string language ;
103- string script ;
104- string region ;
105- string variant ;
106- if ( ! TryGetParts ( tag , out language , out script , out region , out variant ) )
102+ if ( ! TryGetParts ( tag , out var language , out var script , out _ , out _ ) )
107103 {
108104 prevLang = tag ; // shouldn't happen, but if it does...
109105 continue ;
@@ -149,41 +145,34 @@ private void EnsureDefaultTags()
149145 private bool AddLanguage ( string code , string threelettercode , string full = null ,
150146 string name = null , string localName = null , string region = null , List < string > names = null , List < string > regions = null , List < string > tags = null , List < string > ianaNames = null , string regionName = null )
151147 {
152- string primarycountry ;
148+ string primaryCountry ;
153149 if ( region == null )
154150 {
155- primarycountry = "" ;
151+ primaryCountry = "" ;
156152 }
157153 else if ( StandardSubtags . IsValidIso3166RegionCode ( region ) )
158154 {
159155 if ( StandardSubtags . IsPrivateUseRegionCode ( region ) )
160156 {
161- if ( region == "XK" )
162- {
163- primarycountry = "Kosovo" ;
164- }
165- else
166- {
167- primarycountry = "Unknown private use" ;
168- }
157+ primaryCountry = region == "XK" ? "Kosovo" : "Unknown private use" ;
169158 }
170159 else
171160 {
172- primarycountry = StandardSubtags . RegisteredRegions [ region ] . Name ; // convert to full region name
161+ primaryCountry = StandardSubtags . RegisteredRegions [ region ] . Name ; // convert to full region name
173162 }
174163 }
175164 else
176165 {
177- primarycountry = "Invalid region" ;
166+ primaryCountry = "Invalid region" ;
178167 }
179168 LanguageInfo language = new LanguageInfo
180169 {
181170 LanguageTag = code ,
182171 ThreeLetterTag = threelettercode ,
183172 // DesiredName defaults to Names[0], which is set below.
184- PrimaryCountry = primarycountry
173+ PrimaryCountry = primaryCountry
185174 } ;
186- language . Countries . Add ( primarycountry ) ;
175+ language . Countries . Add ( primaryCountry ) ;
187176
188177 if ( regions != null )
189178 {
@@ -221,15 +210,15 @@ private bool AddLanguage(string code, string threelettercode, string full = null
221210 // add each name that is not already in language.Names
222211 language . Names . AddRange ( names . Select ( n => n . Trim ( ) ) . Where ( n => ! language . Names . Contains ( n ) ) ) ;
223212 }
224- // If we end up needing to add the language code, that reflects a deficiency in the data. But
225- // having a bogus name value probably hurts less that not having any name at all. The sort
213+ // If we end up needing to add the language code, that reflects a deficiency in the data. But
214+ // having a bogus name value probably hurts less that not having any name at all. The sort
226215 // process mentioned above using the language tag as well as the first two items in the Names list.
227216 Debug . Assert ( language . Names . Count > 0 ) ;
228217 if ( language . Names . Count == 0 )
229218 language . Names . Add ( code ) ;
230219
231220 // add language to _codeToLanguageIndex and _nameToLanguageIndex
232- // if 2 letter code then add both 2 and 3 letter codes to _codeToLanguageIndex
221+ // if 2- letter code, then add both 2 and 3- letter codes to _codeToLanguageIndex
233222
234223 _codeToLanguageIndex [ code ] = language ;
235224 if ( full != null && ! string . Equals ( full , code ) )
@@ -244,26 +233,25 @@ private bool AddLanguage(string code, string threelettercode, string full = null
244233
245234 if ( tags != null )
246235 {
247- foreach ( string langtag in tags )
236+ foreach ( string langTag in tags )
248237 {
249- _codeToLanguageIndex [ langtag ] = language ;
238+ _codeToLanguageIndex [ langTag ] = language ;
250239 }
251240 }
252241
253- foreach ( string langname in language . Names )
254- GetOrCreateListFromName ( langname ) . Add ( language ) ;
242+ foreach ( string langName in language . Names )
243+ GetOrCreateListFromName ( langName ) . Add ( language ) ;
255244 // add to _countryToLanguageIndex
256245 foreach ( var country in language . Countries )
257246 {
258247 if ( ! string . IsNullOrEmpty ( country ) )
259248 {
260- List < LanguageInfo > list ;
261- if ( ! _countryToLanguageIndex . TryGetValue ( country , out list ) )
249+ if ( ! _countryToLanguageIndex . TryGetValue ( country , out var list ) )
262250 {
263251 list = new List < LanguageInfo > ( ) ;
264252 _countryToLanguageIndex [ country ] = list ;
265253 }
266- list . Add ( language ) ;
254+ list . Add ( language ) ;
267255 }
268256 }
269257
@@ -289,8 +277,7 @@ internal List<LanguageInfo> LanguagesWithoutRegions()
289277
290278 private List < LanguageInfo > GetOrCreateListFromName ( string name )
291279 {
292- List < LanguageInfo > languages ;
293- if ( ! _nameToLanguageIndex . TryGetValue ( name , out languages ) )
280+ if ( ! _nameToLanguageIndex . TryGetValue ( name , out var languages ) )
294281 {
295282 languages = new List < LanguageInfo > ( ) ;
296283 _nameToLanguageIndex . Add ( name , languages ) ;
@@ -305,13 +292,12 @@ private List<LanguageInfo> GetOrCreateListFromName(string name)
305292 public LanguageInfo GetLanguageFromCode ( string isoCode )
306293 {
307294 Guard . AgainstNullOrEmptyString ( isoCode , "Parameter to GetLanguageFromCode must not be null or empty." ) ;
308- LanguageInfo languageInfo = null ;
309- _codeToLanguageIndex . TryGetValue ( isoCode , out languageInfo ) ;
295+ _codeToLanguageIndex . TryGetValue ( isoCode , out var languageInfo ) ;
310296 return languageInfo ;
311297 }
312298
313299 /// <summary>
314- /// Get an list of languages that match the given string in some way (code, name, country)
300+ /// Get a list of languages that match the given string in some way (code, name, country)
315301 /// </summary>
316302 public IEnumerable < LanguageInfo > SuggestLanguages ( string searchString )
317303 {
@@ -322,13 +308,13 @@ public IEnumerable<LanguageInfo> SuggestLanguages(string searchString)
322308
323309 if ( searchString == "*" )
324310 {
325- // there will be duplicate LanguageInfo entries for 2 and 3 letter codes and equivalent tags
311+ // There will be duplicate LanguageInfo entries for 2 and 3- letter codes and equivalent tags.
326312 var all_languages = new HashSet < LanguageInfo > ( _codeToLanguageIndex . Select ( l => l . Value ) ) ;
327313 foreach ( LanguageInfo languageInfo in all_languages . OrderBy ( l => l , new ResultComparer ( searchString ) ) )
328314 yield return languageInfo ;
329315 }
330- // if the search string exactly matches a hard-coded way to say "sign", show all the sign languages
331- // there will be duplicate LanguageInfo entries for equivalent tags
316+ // If the search string exactly matches a hard-coded way to say "sign", show all the sign languages.
317+ // There will be duplicate LanguageInfo entries for equivalent tags
332318 else if ( new [ ] { "sign" , "sign language" , "signes" , "langage des signes" , "señas" , "lenguaje de señas" } . Contains ( searchString . ToLowerInvariant ( ) ) )
333319 {
334320 var parallelSearch = new HashSet < LanguageInfo > ( _codeToLanguageIndex . AsParallel ( ) . Select ( li => li . Value ) . Where ( l =>
@@ -342,10 +328,10 @@ public IEnumerable<LanguageInfo> SuggestLanguages(string searchString)
342328 {
343329 IEnumerable < LanguageInfo > matchOnCode = from x in _codeToLanguageIndex where x . Key . StartsWith ( searchString , StringComparison . InvariantCultureIgnoreCase ) select x . Value ;
344330 List < LanguageInfo > [ ] matchOnName = ( from x in _nameToLanguageIndex where x . Key . StartsWith ( searchString , StringComparison . InvariantCultureIgnoreCase ) select x . Value ) . ToArray ( ) ;
345- // Apostrophes can cause trouble in lookup. Unicode TR-29 inexplicably says to use
331+ // Apostrophes can cause trouble in lookup. Unicode TR-29 inexplicably says to use
346332 // u2019 (RIGHT SINGLE QUOTATION MARK) for the English apostrophe when it also defines
347- // u02BC (MODIFIER LETTER APOSTROPHE) as a Letter character. Users are quite likely to
348- // type the ASCII apostrophe (u0027) which is defined as Punctuation. The current
333+ // u02BC (MODIFIER LETTER APOSTROPHE) as a Letter character. Users are quite likely to
334+ // type the ASCII apostrophe (u0027) which is defined as Punctuation. The current
349335 // data appears to use u2019 in several language names, which means that users might
350336 // end up thinking the language isn't in our database.
351337 // See https://silbloom.myjetbrains.com/youtrack/issue/BL-6339.
@@ -393,9 +379,9 @@ public ResultComparer(string searchString)
393379 /// <summary>
394380 /// Sorting the languages for display is tricky: we want the most relevant languages at the
395381 /// top of the list, so we can't simply sort alphabetically by language name or by language tag,
396- /// but need to take both items into account together with the current search string. Ordering
382+ /// but need to take both items into account together with the current search string. Ordering
397383 /// by relevance is clearly impossible since we'd have to read the user's mind and apply that
398- /// knowledge to the data. But the heuristics we use here may be better than nothing...
384+ /// knowledge to the data. But the heuristics we use here may be better than nothing...
399385 /// </summary>
400386 public int Compare ( LanguageInfo x , LanguageInfo y )
401387 {
@@ -404,7 +390,7 @@ public int Compare(LanguageInfo x, LanguageInfo y)
404390
405391 // Favor ones where some language name matches the search string to solve BL-1141
406392 // We restrict this to the top 2 names of each language, and to cases where the
407- // corresponding names of the two languages are different. (If both language names
393+ // corresponding names of the two languages are different. (If both language names
408394 // match the search string, there's no good reason to favor one over the other!)
409395 if ( ! x . Names [ 0 ] . Equals ( y . Names [ 0 ] , StringComparison . InvariantCultureIgnoreCase ) )
410396 {
@@ -415,39 +401,34 @@ public int Compare(LanguageInfo x, LanguageInfo y)
415401 }
416402 else if ( x . Names . Count == 1 || y . Names . Count == 1 || ! x . Names [ 1 ] . Equals ( y . Names [ 1 ] , StringComparison . InvariantCultureIgnoreCase ) )
417403 {
418- // If we get here, x.Names[0] == y.Names[0]. If both equal the search string, then neither x.Names[1]
404+ // If we get here, x.Names[0] == y.Names[0]. If both equal the search string, then neither x.Names[1]
419405 // nor y.Names[1] should equal the search string since the code adding to Names checks for redundancy.
420- // Also it's possible that neither x.Names[1] nor y.Names[1] exists at this point in the code, or that
406+ // Also, it's possible that neither x.Names[1] nor y.Names[1] exists at this point in the code, or that
421407 // only one of them exists, or that both of them exist (in which case they are not equal).
422408 if ( x . Names . Count > 1 && x . Names [ 1 ] . Equals ( _searchString , StringComparison . InvariantCultureIgnoreCase ) )
423409 return - 1 ;
424410 if ( y . Names . Count > 1 && y . Names [ 1 ] . Equals ( _searchString , StringComparison . InvariantCultureIgnoreCase ) )
425411 return 1 ;
426412 }
427413
428- // Favor a language whose tag matches the search string exactly. (equal tags are handled above)
414+ // Favor a language whose tag matches the search string exactly. (equal tags are handled above)
429415 if ( x . LanguageTag . Equals ( _searchString , StringComparison . InvariantCultureIgnoreCase ) )
430416 return - 1 ;
431417 if ( y . LanguageTag . Equals ( _searchString , StringComparison . InvariantCultureIgnoreCase ) )
432418 return 1 ;
433419
434420 // written this way to avoid having to catch predictable exceptions as the user is typing
435- string xlanguage ;
436- string ylanguage ;
437- string script ;
438- string region ;
439- string variant ;
440- var xtagParses = TryGetParts ( x . LanguageTag , out xlanguage , out script , out region , out variant ) ;
441- var ytagParses = TryGetParts ( y . LanguageTag , out ylanguage , out script , out region , out variant ) ;
442- var bothTagLanguagesMatchSearch = xtagParses && ytagParses && xlanguage == ylanguage &&
443- _searchString . Equals ( xlanguage , StringComparison . InvariantCultureIgnoreCase ) ;
421+ var xTagParses = TryGetParts ( x . LanguageTag , out var xLanguage , out _ , out _ , out _ ) ;
422+ var yTagParses = TryGetParts ( y . LanguageTag , out var yLanguage , out _ , out _ , out _ ) ;
423+ var bothTagLanguagesMatchSearch = xTagParses && yTagParses && xLanguage == yLanguage &&
424+ _searchString . Equals ( xLanguage , StringComparison . InvariantCultureIgnoreCase ) ;
444425 if ( ! bothTagLanguagesMatchSearch )
445426 {
446- // One of the tag language pieces may match the search string even though not both match. In that case,
427+ // One of the tag language pieces may match the search string even though not both match. In that case,
447428 // sort the matching language earlier in the list.
448- if ( xtagParses && _searchString . Equals ( xlanguage , StringComparison . InvariantCultureIgnoreCase ) )
429+ if ( xTagParses && _searchString . Equals ( xLanguage , StringComparison . InvariantCultureIgnoreCase ) )
449430 return - 1 ; // x.Tag's language part matches search string exactly, so sort it earlier in the list.
450- if ( ytagParses && _searchString . Equals ( ylanguage , StringComparison . InvariantCultureIgnoreCase ) )
431+ if ( yTagParses && _searchString . Equals ( yLanguage , StringComparison . InvariantCultureIgnoreCase ) )
451432 return 1 ; // y.Tag's language part matches search string exactly, so sort it earlier in the list.
452433 }
453434
@@ -481,7 +462,7 @@ public int Compare(LanguageInfo x, LanguageInfo y)
481462 }
482463
483464 // Editing distance to a language name is not useful when we've detected that the user appears to be
484- // typing a language tag in that both language tags match what the user has typed. (For example,
465+ // typing a language tag in that both language tags match what the user has typed. (For example,
485466 // it gives a strange and unwanted order to the variants of zh.) In such a case we just order the
486467 // matching codes by length (already done) and then alphabetically by code, skipping the sort by
487468 // editing distance to the language names.
@@ -504,7 +485,8 @@ public int Compare(LanguageInfo x, LanguageInfo y)
504485 return res ;
505486 }
506487
507- // Alphabetize by Language tag if 3 characters or less or if there is a hyphen after the first 2 or 3 chars
488+ // Alphabetize by Language tag if 3 characters or fewer, or if there is a hyphen
489+ // after the first 2 or 3 chars.
508490 if ( _lowerSearch . Length <= 3 || _lowerSearch . IndexOf ( '-' ) == 3 || _lowerSearch . IndexOf ( '-' ) == 4 )
509491 {
510492 return string . Compare ( x . LanguageTag , y . LanguageTag , StringComparison . InvariantCultureIgnoreCase ) ;
0 commit comments