@@ -433,7 +433,7 @@ class LyricManager {
433433 }
434434 if ( isStale ( ) ) return ;
435435 if ( ! ttmlContent || typeof ttmlContent !== "string" ) return ;
436- const sorted = this . sortTTMLTranslations ( ttmlContent ) ;
436+ const sorted = this . cleanTTMLTranslations ( ttmlContent ) ;
437437 const parsed = parseTTML ( sorted ) ;
438438 const lines = parsed ?. lines || [ ] ;
439439 if ( ! lines . length ) return ;
@@ -517,7 +517,7 @@ class LyricManager {
517517 if ( ! lyric ) return { lrcData : [ ] , yrcData : [ ] } ;
518518 // TTML 直接返回
519519 if ( format === "ttml" ) {
520- const sorted = this . sortTTMLTranslations ( lyric ) ;
520+ const sorted = this . cleanTTMLTranslations ( lyric ) ;
521521 const ttml = parseTTML ( sorted ) ;
522522 const lines = ttml ?. lines || [ ] ;
523523 statusStore . usingTTMLLyric = true ;
@@ -551,52 +551,74 @@ class LyricManager {
551551 }
552552
553553 /**
554- * 处理 TTML 内容并排序翻译
554+ * 清洗 TTML 中不需要的翻译
555555 * @param ttmlContent 原始 TTML 内容
556- * @param translationOrder 翻译排序顺序
557- * @returns 排序后的 TTML 内容
556+ * @returns 清洗后的 TTML 内容
558557 */
559- // 此函数应该在 AMLL 的 TTML 解析器支持多语言翻译后删除
560- private sortTTMLTranslations (
558+ // 当支持 i18n 之后,需要对其中的部分函数进行修改,使其优选逻辑能够根据用户界面语言变化
559+ private cleanTTMLTranslations (
560+ // 一般没有多种音译,故不对音译部分进行清洗,如果需要请另写处理函数
561561 ttmlContent : string ,
562- translationOrder : string [ ] = [ "zh-CN" , "zh-Hans" , "zh-TW" , "zh-Hant" ] ,
563562 ) : string {
564- // 使用 DOMParser 解析 XML 内容
565- const parser = new DOMParser ( ) ;
566- const xmlDoc = parser . parseFromString ( ttmlContent , "text/xml" ) ;
567-
568- // 查找所有歌词行元素
569- const lyricsElements = xmlDoc . querySelectorAll ( "tt > body > div > p" ) ;
570-
571- lyricsElements . forEach ( ( element : Element ) => {
572- // 获取当前歌词行的所有翻译元素
573- const translationElements = Array . from ( element . children ) . filter (
574- ( child ) =>
575- child . hasAttribute ( "ttm:role" ) && child . getAttribute ( "ttm:role" ) === "x-translation" ,
576- ) ;
563+ const lang_counter = ( ttml_text : string ) => {
564+ // 使用正则匹配所有 xml:lang="xx-XX" 格式的字符串
565+ const langRegex = / (?< = < ( s p a n | t r a n s l a t i o n ) [ ^ < > ] + ) x m l : l a n g = " ( [ ^ " ] + ) " / g;
566+ const matches = ttml_text . matchAll ( langRegex ) ;
577567
578- // 按照指定顺序对翻译进行排序
579- // 按照指定顺序对翻译进行排序
580- translationElements . sort ( ( a , b ) => {
581- const aLang = ( a . getAttribute ( "xml:lang" ) || a . getAttribute ( "lang" ) || "" ) . toLowerCase ( ) ;
582- const bLang = ( b . getAttribute ( "xml:lang" ) || b . getAttribute ( "lang" ) || "" ) . toLowerCase ( ) ;
568+ // 提取匹配结果并去重
569+ const langSet = new Set < string > ( ) ;
570+ for ( const match of matches ) {
571+ if ( match [ 2 ] ) langSet . add ( match [ 2 ] ) ;
572+ }
583573
584- const aIndex = translationOrder . findIndex ( ( lang ) => aLang . startsWith ( lang . toLowerCase ( ) ) ) ;
585- const bIndex = translationOrder . findIndex ( ( lang ) => bLang . startsWith ( lang . toLowerCase ( ) ) ) ;
574+ return Array . from ( langSet ) ;
575+ } ;
586576
587- // 如果找不到指定语言,则放在最后
588- return ( aIndex === - 1 ? Infinity : aIndex ) - ( bIndex === - 1 ? Infinity : bIndex ) ;
589- } ) ;
577+ const lang_filter = ( langs : string [ ] ) : string | null => {
578+ if ( langs . length <= 1 ) return null ;
590579
591- // 重新排列翻译元素
592- translationElements . forEach ( ( translationElement ) => {
593- element . appendChild ( translationElement ) ; // 移动到末尾以实现排序
594- } ) ;
595- } ) ;
580+ const lang_matcher = ( target : string ) => {
581+ return langs . find ( ( lang ) => {
582+ try {
583+ return new Intl . Locale ( lang ) . maximize ( ) . script === target ;
584+ } catch {
585+ return false ;
586+ }
587+ } ) ;
588+ } ;
589+
590+ const hans_matched = lang_matcher ( "Hans" ) ;
591+ if ( hans_matched ) return hans_matched ;
592+
593+ const hant_matched = lang_matcher ( "Hant" ) ;
594+ if ( hant_matched ) return hant_matched ;
595+
596+ const major = langs . find ( ( key ) => key . startsWith ( "zh" ) ) ;
597+ if ( major ) return major ;
598+
599+ return langs [ 0 ] ;
600+ } ;
601+
602+ const ttml_cleaner = ( ttml_text : string , major_lang : string | null ) : string => {
603+ // 如果没有指定主语言,直接返回原文本(或者根据需求返回空)
604+ if ( major_lang === null ) return ttml_text ;
605+
606+ /**
607+ * 替换逻辑回调函数
608+ * @param match 完整匹配到的标签字符串 (例如 <code><span ...>...<\/span></code>)
609+ * @param lang 正则中第一个捕获组匹配到的语言代码 (例如 "ja-JP")
610+ */
611+ const replacer = ( match : string , lang : string ) => ( lang === major_lang ? match : "" ) ;
612+ const translationRegex = / < t r a n s l a t i o n [ ^ > ] + x m l : l a n g = " ( [ ^ " ] + ) " [ ^ > ] * > [ \s \S ] * ?< \/ t r a n s l a t i o n > / g;
613+ const spanRegex = / < s p a n [ ^ > ] + x m l : l a n g = " ( [ ^ " ] + ) " [ ^ > ] * > [ \s \S ] * ?< \/ s p a n > / g;
614+ return ttml_text . replace ( translationRegex , replacer ) . replace ( spanRegex , replacer ) ;
615+ } ;
616+
617+ const context_lang = lang_counter ( ttmlContent ) ;
618+ const major = lang_filter ( context_lang ) ;
619+ const cleaned_ttml = ttml_cleaner ( ttmlContent , major ) ;
596620
597- // 序列化回字符串
598- const serializer = new XMLSerializer ( ) ;
599- return serializer . serializeToString ( xmlDoc ) ;
621+ return cleaned_ttml ;
600622 }
601623
602624 /**
0 commit comments