@@ -622,3 +622,65 @@ describe("canonical tag is first in alternativeTags", () => {
622622 expect ( ojg ?. alternativeTags [ 0 ] . split ( "-" ) [ 0 ] ) . toBe ( "oj" ) ;
623623 } ) ;
624624} ) ;
625+
626+ // langtags.json sometimes keeps a code that ISO has retired in an entry's iso639_3 field even
627+ // though the entry's own tag already uses the surviving code, e.g. tag "enm-Latn-IE" with
628+ // iso639_3 "yol". Such an entry must fold into the surviving code rather than becoming a
629+ // duplicate language of its own. See the comment in scripts/langtagProcessing.ts and BL-15916.
630+ describe ( "entries whose langtags iso639_3 code has been retired by ISO" , ( ) => {
631+ // [retired code, surviving code the tag uses, exonym of the surviving language]
632+ const retiredToSurviving = [
633+ [ "yol" , "enm" , "Middle English (1100-1500)" ] , // Yola; the surviving code is a *different* language
634+ [ "kpp" , "jkp" , "Paku Karen" ] ,
635+ [ "jeg" , "oyb" , "Oy" ] ,
636+ [ "dek" , "sqm" , "Suma" ] ,
637+ [ "tpw" , "tpn" , "Tupinambá" ] ,
638+ ] ;
639+
640+ it ( "should fold into the surviving language instead of becoming a duplicate, and stay findable by the retired code" , ( ) => {
641+ for ( const [ retired , surviving , exonym ] of retiredToSurviving ) {
642+ expect (
643+ getLanguageBySubtag ( retired ) ,
644+ `${ retired } is retired and should not be a language entry of its own`
645+ ) . toBeUndefined ( ) ;
646+
647+ const survivor = getLanguageBySubtag ( surviving ) ;
648+ expect ( survivor , `${ surviving } should be a language entry` ) . toBeDefined ( ) ;
649+ expect ( survivor ?. exonym ) . toBe ( exonym ) ;
650+ expect (
651+ survivor ?. alternativeTags ,
652+ `the retired tag ${ retired } should have folded into ${ surviving } `
653+ ) . toContain ( retired ) ;
654+ // Note this is the raw search. For yol/enm in particular the surviving language is then
655+ // filtered out by defaultSearchResultModifier (enm is on the historic-language exclusion
656+ // list), so a user searching "yol" sees nothing - that is intended, see the next test.
657+ expect (
658+ searchForLanguage ( retired ) . some ( ( result ) =>
659+ codeMatches ( result . iso639_3_code , surviving )
660+ ) ,
661+ `the raw search for retired code ${ retired } should still reach ${ surviving } `
662+ ) . toBe ( true ) ;
663+ }
664+ } ) ;
665+
666+ it ( "should not offer Yola's entry as a selectable Middle English card" , ( ) => {
667+ // Regression guard for the user-visible symptom: langtags' "enm-Latn-IE" entry (iso639_3
668+ // "yol") used to produce a card reading "Middle English (1100-1500) - A language of Ireland"
669+ // carrying the subtag enm. That mislabelled Yola, would have written the tag enm onto a
670+ // collection, and slipped past the deliberate enm exclusion in
671+ // defaultExcludedHistoricLanguages.ts because the entry was keyed "yol".
672+ const searchString = "Middle English" ;
673+ const results = defaultSearchResultModifier (
674+ searchForLanguage ( searchString ) ,
675+ searchString
676+ ) ;
677+ // The yol assertion is the one carrying the regression guard; enm is additionally covered by
678+ // the historic-language exclusion, so assert both to pin the whole user-visible outcome.
679+ for ( const code of [ "yol" , "enm" ] ) {
680+ expect (
681+ results . some ( ( result ) => codeMatches ( result . iso639_3_code , code ) ) ,
682+ `${ code } should not be offered as a language option`
683+ ) . toBe ( false ) ;
684+ }
685+ } ) ;
686+ } ) ;
0 commit comments