|
44 | 44 | return "" |
45 | 45 | end function |
46 | 46 |
|
47 | | -' resolveLanguageName: Convert a 3-letter ISO 639-2 language code to its full display name |
48 | | -' Uses getSubtitleLanguages() from languages.bs as the lookup table. |
49 | | -' Falls back to the raw code if not found in the lookup table. |
| 47 | +' resolveLanguageName: Convert a media stream language code to a localized display name. |
50 | 48 | ' |
51 | | -' @param {string} langCode - 3-letter ISO 639-2 language code (e.g., "eng", "spa") |
52 | | -' @returns {string} - Full language name (e.g., "English", "Spanish") or raw code if unknown |
| 49 | +' MediaStream.Language passes through whatever the container metadata holds — |
| 50 | +' ffmpeg/Jellyfin do not normalize, so real-world inputs include ISO 639-2/T |
| 51 | +' ("fra"), 639-2/B ("fre"), 639-1 ("fr"), and BCP-47 tags ("fr-FR", "pt_BR"). |
| 52 | +' |
| 53 | +' Three-tier resolution chain: |
| 54 | +' 1. Lowercase + strip after first "-" or "_" (drop region/script suffix) |
| 55 | +' 2. "und" / "zxx" → "" — caller omits the language label |
| 56 | +' 3. Alias map → normalize 3-letter / deprecated codes to a base form |
| 57 | +' 4. Tier 1: translationKey lookup → translate() — localized to user's UI |
| 58 | +' 5. Tier 2: English-name fallback → covers every other ISO 639-2 code |
| 59 | +' 6. Tier 3: raw code passthrough — last-resort, preserves info |
| 60 | +' |
| 61 | +' "und" (Undefined) and "zxx" (No linguistic content — instrumental music, |
| 62 | +' ambient sound, foley) are both omitted: rendering "No linguistic content |
| 63 | +' EAC3 5.1" as a track label is noisier than just "EAC3 5.1". The other |
| 64 | +' ISO 639-2 special codes ("mul" Multiple, "mis" Uncoded) ARE displayed |
| 65 | +' because they convey real information when they appear. |
| 66 | +' |
| 67 | +' @param {string} langCode - Media stream language code from any common format |
| 68 | +' @returns {string} - Localized name, English fallback, "" for und/zxx, or raw code |
53 | 69 | function resolveLanguageName(langCode as string) as string |
54 | 70 | if langCode = "" then return "" |
55 | 71 |
|
56 | | - lowerCode = LCase(langCode) |
| 72 | + base = LCase(langCode) |
57 | 73 |
|
58 | | - ' "und" (Undefined) is not useful to display — omit it entirely |
59 | | - if lowerCode = "und" then return "" |
| 74 | + hyphenPos = inStr(1, base, "-") |
| 75 | + if hyphenPos > 0 then base = Left(base, hyphenPos - 1) |
| 76 | + underscorePos = inStr(1, base, "_") |
| 77 | + if underscorePos > 0 then base = Left(base, underscorePos - 1) |
60 | 78 |
|
61 | | - languages = getSubtitleLanguages() |
| 79 | + if base = "und" or base = "zxx" then return "" |
62 | 80 |
|
63 | | - if languages.doesExist(lowerCode) |
64 | | - return languages[lowerCode] |
65 | | - end if |
| 81 | + aliases = mediaLanguageAliases() |
| 82 | + if aliases.doesExist(base) then base = aliases[base] |
| 83 | + |
| 84 | + keyMap = languageTranslationKeys() |
| 85 | + if keyMap.doesExist(base) then return translate(keyMap[base]) |
| 86 | + |
| 87 | + fallbacks = languageEnglishFallbacks() |
| 88 | + if fallbacks.doesExist(base) then return fallbacks[base] |
66 | 89 |
|
67 | 90 | return langCode |
68 | 91 | end function |
|
0 commit comments