1function detectScriptType(text) { 2 if (!text) return null; 3 if (/[ê°-í£\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7AF\uD7B0-\uD7FF]/.test(text)) return "ko"; 4 if (/[ã-ãã¡-ã¶ã¼\u3040-\u309F\u30A0-\u30FF\u31F0-\u31FF\uFF65-\uFF9F]/.test(text)) return "ja"; 5 if (/[à¤-ॿ\u0900-\u097F]/.test(text)) return "hi"; 6 if (/[Ø-Û¿\u0600-\u06FF\u0750-\u077F]/.test(text)) return "ar"; 7 if (/[Ð-Ó¿\u0400-\u04FF]/.test(text)) return "ru"; 8 if (/[à¸-à¹\u0E00-\u0E7F]/.test(text)) return "th"; 9 if (/[Ͱ-Ï¿\u0370-\u03FF]/.test(text)) return "el"; 10 if (/[Ö-׿\u0590-\u05FF]/.test(text)) return "he"; 11 if (/[ä¸-é¾¥\u4E00-\u9FFF\u3400-\u4DBF]/.test(text)) return "zh"; 12 if (/[a-zA-Z]/.test(text)) return "latin"; 13 return null; 14} 15function getScriptBadge(scriptType) { 16 switch (scriptType) { 17 case "ko": 18 return "KR"; 19 case "ja": 20 return "JP"; 21 case "zh": 22 return "CN"; 23 case "hi": 24 return "IN"; 25 case "ru": 26 return "RU"; 27 case "ar": 28 return "AR"; 29 case "th": 30 return "TH"; 31 case "el": 32 return "GR"; 33 case "he": 34 return "IL"; 35 default: 36 return null; 37 } 38} 39function parseMultilingualData(rawStr) { 40 if (!rawStr) return null; 41 if (typeof rawStr === "object") return rawStr; 42 if (typeof rawStr === "string" && (rawStr.startsWith("{") || rawStr.startsWith("["))) { 43 try { 44 return JSON.parse(rawStr); 45 } catch { 46 return null; 47 } 48 } 49 return null; 50} 51function extractBilingualPairFromText(text) { 52 if (!text) return { title: text, native: null, romanized: null }; 53 const parenMatch = text.match(/^(.+?)\s*\(([^)]+)\)\s*$/); 54 if (parenMatch) { 55 const part1 = parenMatch[1].trim(); 56 const part2 = parenMatch[2].trim(); 57 const isYear = /^\d{4}(?:[-ââ/]\d{2,4})?$/.test(part2); 58 if (!isYear) { 59 const script1 = detectScriptType(part1); 60 const script2 = detectScriptType(part2); 61 if (script1 && script1 !== "latin" && script2 === "latin") { 62 return { title: part1, native: part1, romanized: part2 }; 63 } else if (script1 === "latin" && script2 && script2 !== "latin") { 64 return { title: part1, native: part2, romanized: part1 }; 65 } 66 } 67 } 68 const slashMatch = text.match(/^(.+?)\s*[/|â¢]\s*(.+)$/); 69 if (slashMatch) { 70 const part1 = slashMatch[1].trim(); 71 const part2 = slashMatch[2].trim(); 72 const script1 = detectScriptType(part1); 73 const script2 = detectScriptType(part2); 74 if (script1 && script1 !== "latin" && script2 === "latin") { 75 return { title: part2, native: part1, romanized: part2 }; 76 } else if (script1 === "latin" && script2 && script2 !== "latin") { 77 return { title: part1, native: part2, romanized: part1 }; 78 } 79 } 80 const script = detectScriptType(text); 81 if (script && script !== "latin") { 82 return { title: text, native: text, romanized: null }; 83 } 84 return { title: text, native: null, romanized: text }; 85} 86function getBilingualData(primaryTitle, rawSubtitleOrDetails, currentLang = "en") { 87 const lang = (currentLang || "en").toLowerCase(); 88 const langPrefix = lang.split("-")[0]; 89 const parsed = parseMultilingualData(rawSubtitleOrDetails); 90 const textPair = extractBilingualPairFromText(primaryTitle || ""); 91 let titleDict = null; 92 let extraSubtitle = null; 93 if (parsed && typeof parsed === "object") { 94 if (parsed.title && typeof parsed.title === "object") { 95 titleDict = parsed.title; 96 } else if (parsed.translations && typeof parsed.translations === "object") { 97 titleDict = parsed.translations; 98 } else if (parsed.ja || parsed.ko || parsed.en || parsed["zh-CN"] || parsed.zh || parsed.hi || parsed.ru || parsed.fr || parsed.es || parsed.it || parsed.de) { 99 const pScript = detectScriptType(primaryTitle); 100 const isNonLatin = pScript && pScript !== "latin"; 101 const normPrimary = (primaryTitle || "").toLowerCase().trim(); 102 const matchesPrimary = Object.values(parsed).some((v) => typeof v === "string" && v.toLowerCase().trim() === normPrimary); 103 if (isNonLatin || matchesPrimary) { 104 titleDict = parsed; 105 } else { 106 extraSubtitle = parsed[lang] || parsed[langPrefix] || parsed.en || parsed.ja || null; 107 } 108 } 109 if (parsed.subtitle) { 110 if (typeof parsed.subtitle === "string") { 111 extraSubtitle = parsed.subtitle; 112 } else if (typeof parsed.subtitle === "object") { 113 extraSubtitle = parsed.subtitle[lang] || parsed.subtitle[langPrefix] || parsed.subtitle.en || null; 114 } 115 } 116 } 117 let nativeTitle = null; 118 let romanizedTitle = textPair.romanized; 119 let nativeScript = null; 120 const primaryScript = detectScriptType(primaryTitle); 121 if (primaryScript && primaryScript !== "latin") { 122 nativeScript = primaryScript; 123 nativeTitle = primaryTitle; 124 } 125 if (!nativeTitle && textPair.native) { 126 nativeTitle = textPair.native; 127 nativeScript = detectScriptType(textPair.native); 128 } 129 if (!nativeTitle && titleDict) { 130 const lowerTitle = (primaryTitle || "").toLowerCase(); 131 const isKoreanOrigin = lowerTitle.includes("k-pop") || lowerTitle.includes("korean"); 132 const isJapaneseOrigin = lowerTitle.includes("ghibli") || lowerTitle.includes("anime") || lowerTitle.includes("j-pop") || lowerTitle.includes("japanese") || lowerTitle.includes("vocaloid") || lowerTitle.includes("touhou"); 133 const isChineseOrigin = lowerTitle.includes("c-pop") || lowerTitle.includes("mandopop") || lowerTitle.includes("cantopop") || lowerTitle.includes("chinese"); 134 const isRussianOrigin = lowerTitle.includes("russian"); 135 const isArabicOrigin = lowerTitle.includes("arabic"); 136 if (isKoreanOrigin && titleDict.ko && detectScriptType(titleDict.ko) === "ko") { 137 nativeTitle = titleDict.ko; 138 nativeScript = "ko"; 139 } else if (isJapaneseOrigin && titleDict.ja && detectScriptType(titleDict.ja) === "ja") { 140 nativeTitle = titleDict.ja; 141 nativeScript = "ja"; 142 } else if (isChineseOrigin && (titleDict["zh-CN"] || titleDict["zh-TW"] || titleDict.zh)) { 143 nativeTitle = titleDict["zh-CN"] || titleDict["zh-TW"] || titleDict.zh || null; 144 nativeScript = "zh"; 145 } else if (isRussianOrigin && titleDict.ru && detectScriptType(titleDict.ru) === "ru") { 146 nativeTitle = titleDict.ru; 147 nativeScript = "ru"; 148 } else if (isArabicOrigin && titleDict.ar && detectScriptType(titleDict.ar) === "ar") { 149 nativeTitle = titleDict.ar; 150 nativeScript = "ar"; 151 } 152 } 153 if (titleDict && titleDict.en) { 154 romanizedTitle = titleDict.en; 155 } 156 if (!romanizedTitle) { 157 if (textPair.romanized) romanizedTitle = textPair.romanized; 158 else if (detectScriptType(primaryTitle) === "latin") romanizedTitle = primaryTitle; 159 } 160 let mainTitle = primaryTitle || ""; 161 let subTitle = null; 162 if (titleDict && (titleDict[lang] || titleDict[langPrefix])) { 163 mainTitle = titleDict[lang] || titleDict[langPrefix] || primaryTitle; 164 if (nativeTitle && mainTitle !== nativeTitle) { 165 subTitle = nativeTitle; 166 } else if (romanizedTitle && mainTitle !== romanizedTitle) { 167 subTitle = romanizedTitle; 168 } else if (extraSubtitle) { 169 subTitle = extraSubtitle; 170 } 171 } else if (nativeScript && (lang === nativeScript || langPrefix === nativeScript)) { 172 mainTitle = nativeTitle || primaryTitle; 173 subTitle = romanizedTitle && romanizedTitle !== mainTitle ? romanizedTitle : extraSubtitle; 174 } else { 175 mainTitle = romanizedTitle || primaryTitle; 176 if (nativeTitle && nativeTitle !== mainTitle) { 177 subTitle = nativeTitle; 178 } else if (extraSubtitle) { 179 subTitle = extraSubtitle; 180 } else if (typeof rawSubtitleOrDetails === "string" && !rawSubtitleOrDetails.trim().startsWith("{") && !rawSubtitleOrDetails.trim().startsWith("[")) { 181 subTitle = rawSubtitleOrDetails; 182 } 183 } 184 if (subTitle && typeof subTitle === "string" && (subTitle.trim().startsWith("{") || subTitle.trim().startsWith("["))) { 185 subTitle = null; 186 } 187 let hoverTooltip = mainTitle; 188 if (nativeTitle && nativeTitle !== mainTitle) { 189 hoverTooltip = `${nativeTitle} (${mainTitle})`; 190 } else if (romanizedTitle && romanizedTitle !== mainTitle) { 191 hoverTooltip = `${romanizedTitle} (${mainTitle})`; 192 } 193 let altText = mainTitle; 194 if (nativeTitle && nativeTitle !== mainTitle) { 195 altText = `${mainTitle} (${nativeTitle})`; 196 } 197 const nativeBadge = getScriptBadge(nativeScript); 198 return { 199 mainTitle, 200 subTitle, 201 nativeTitle, 202 romanizedTitle, 203 hoverTooltip, 204 altText, 205 nativeScriptType: nativeScript, 206 nativeBadge 207 }; 208} 209function getBilingualTitle(primaryTitle, rawSubtitleOrDetails, currentLang = "en") { 210 return getBilingualData(primaryTitle, rawSubtitleOrDetails, currentLang); 211} 212export { 213 getBilingualTitle as g, 214 parseMultilingualData as p 215};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.