Skip to content

Conversation

@ranhengzhang
Copy link
Contributor

改动

  • 删除 sortTTMLTranslations 方法
  • 使用 cleanTTMLTranslations 方法进行替代

效果

  • 提升处理速度:经测试,目前 ttml-db 中最大的多语言翻译文件处理时间只有 3ms
  • 提高可扩展性:如果后续需要扩展「多语言翻译」相关功能,直接修改 cleanTTMLTranslations 方法及其中的 lang_filter 函数即可

未来

如果后续扩展了 i18n 相关功能,需要根据用户界面更换翻译时,同样需要修改 cleanTTMLTranslations 方法及其中的 lang_filter 函数,重点为 lang_filter 中的优选算法,需要使用短横线分隔语言代码向下选择,例如:文件中有 en-GB en-CA en,界面语言为 enen-US 的用户应该匹配到 en,而文件中没有 en 时匹配到 en-GBen-CA,下面是一个实例函数(应该能直接用)

/**
 * 根据 major_lang 在 context_lang 中查找最匹配的语言。
 * * 逻辑:
 * 1. 精确匹配 context_lang 是否包含 major_lang。
 * 2. 前缀匹配 context_lang 中是否有以 major_lang 开头的项。
 * 3. 都没有,则去掉 major_lang 最后一个 "-" 及其内容,重复上述步骤。
 * 4. 如果循环结束仍无匹配,返回 context_lang 的第一个项。
 */
function findBestMatchLanguage(context_lang: string[], major_lang: string): string {
  // 防御性编程:如果列表为空,返回空字符串或根据需求抛出错误
  if (!context_lang || context_lang.length === 0) {
    return "";
  }

  let currentLang = major_lang;

  // 循环直到无法再拆分(即不包含 '-')
  while (true) {
    // 1. 优先查找是否有完全匹配
    if (context_lang.includes(currentLang)) {
      return currentLang;
    }

    // 2. 查找 major_lang 开头的项 (Prefix match)
    // 例如:currentLang="en", context有一项 "en-US",则匹配
    const prefixMatch = context_lang.find(lang => lang.startsWith(currentLang));
    if (prefixMatch) {
      return prefixMatch;
    }

    // 3. 拆掉最后一个 "-" 及其后面的内容
    const lastHyphenIndex = currentLang.lastIndexOf('-');
    
    if (lastHyphenIndex !== -1) {
      currentLang = currentLang.substring(0, lastHyphenIndex);
    } else {
      // 没有 "-" 符号了,跳出循环
      break;
    }
  }

  // 4. 依然没有找到,直接返回第一个项
  return context_lang[0];
}

Replaced sorting of TTML translations with cleaning logic. Added a new method to clean unnecessary translations from TTML content.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ranhengzhang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求重构了 TTML 歌词翻译的处理机制,将原有的基于排序的逻辑替换为更高效和可扩展的清洗逻辑。核心变更是删除了 sortTTMLTranslations 方法,并引入了 cleanTTMLTranslations 方法。这一改变不仅显著提升了处理大型多语言 TTML 文件的性能,还通过优先选择中文翻译(如 zh-Hans, zh-CN, zh-Hant)来优化用户体验,并为未来更精细的国际化支持提供了灵活的框架。

Highlights

  • 移除旧方法: 删除了 sortTTMLTranslations 方法。
  • 引入新方法: 引入了 cleanTTMLTranslations 方法作为 sortTTMLTranslations 的替代。
  • 性能提升: 新方法显著提升了 TTML 翻译处理速度,对于大型多语言文件,处理时间可缩短至约 3ms。
  • 可扩展性增强: 提高了多语言翻译功能的可扩展性,为未来更复杂的国际化 (i18n) 需求奠定基础。
  • 中文翻译优先: cleanTTMLTranslations 方法内置了优先选择中文翻译(如 zh-Hans, zh-CN, zh-Hant)的逻辑。
  • 内部实现细节: cleanTTMLTranslations 方法通过 lang_counter 提取语言、lang_filter 筛选主要语言和 ttml_cleaner 清洗不相关翻译来实现其功能。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次拉取请求将 sortTTMLTranslations 方法替换为 cleanTTMLTranslations,旨在提高 TTML 翻译处理的速度和可扩展性。新的 cleanTTMLTranslations 方法通过正则表达式识别语言标签并根据预设的中文优先级进行清洗。整体改动方向良好,但有几处细节可以进一步优化,以提高代码的健壮性和未来的可维护性。

Comment on lines 559 to 569
const lang_filter = (langs: string[]) : (string | null) => {
if (langs.length <= 1) return null;

// 重新排列翻译元素
translationElements.forEach((translationElement) => {
element.appendChild(translationElement); // 移动到末尾以实现排序
});
});
if (langs.includes('zh-Hans')) return 'zh-Hans';
if (langs.includes('zh-CN')) return 'zh-CN';
if (langs.includes('zh-Hant')) return 'zh-Hant';

const major = langs.find(key => key.startsWith('zh'));
if (major) return major;

return langs[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

当前 lang_filter 函数的语言匹配逻辑相对简单,它直接检查 zh-Hanszh-CNzh-Hant,然后是所有以 zh 开头的语言,最后返回列表中的第一个语言。这与您在 PR 描述的「未来」部分中提到的 findBestMatchLanguage 函数的更复杂、更健壮的匹配逻辑(例如,通过短横线分隔符向下匹配 en-USen)不符。

建议将 lang_filter 的逻辑更新为 findBestMatchLanguage 中描述的算法,以更好地支持未来的国际化需求,并提高语言匹配的准确性。这能确保在 i18n 功能扩展时,无需再次修改此核心逻辑。

    const lang_filter = (context_lang: string[]) : (string | null) => {
      if (!context_lang || context_lang.length === 0) {
        return null;
      }

      let major_lang = 'zh-Hans'; // 默认优先简体中文
      if (context_lang.includes(major_lang)) return major_lang;

      major_lang = 'zh-CN';
      if (context_lang.includes(major_lang)) return major_lang;

      major_lang = 'zh-Hant';
      if (context_lang.includes(major_lang)) return major_lang;

      // 按照 PR 描述中的 findBestMatchLanguage 逻辑进行更通用的匹配
      let currentLang = 'zh'; // 假设默认中文为主要语言,可以根据实际用户设置动态传入
      while (true) {
        if (context_lang.includes(currentLang)) {
          return currentLang;
        }

        const prefixMatch = context_lang.find(lang => lang.startsWith(currentLang));
        if (prefixMatch) {
          return prefixMatch;
        }

        const lastHyphenIndex = currentLang.lastIndexOf('-');
        if (lastHyphenIndex !== -1) {
          currentLang = currentLang.substring(0, lastHyphenIndex);
        } else {
          break;
        }
      }

      // 如果上述匹配都失败,则返回列表中的第一个语言
      return context_lang[0];
    }

Comment on lines 583 to 591
if (ttml_text.indexOf("iTunesMetadata") !== -1) {
const translationRegex = /<translation[^>]+xml:lang="([^"]+)"[^>]*>[\s\S]*?<\/translation>/g;

return ttml_text.replace(translationRegex, replacer);
} else {
const spanRegex = /<span[^>]+xml:lang="([^"]+)"[^>]*>[\s\S]*?<\/span>/g;

return ttml_text.replace(spanRegex, replacer);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

ttml_cleaner 函数中,您使用 ttml_text.indexOf("iTunesMetadata") !== -1 来判断应该使用 translationRegex 还是 spanRegex。这种基于字符串 indexOf 的启发式判断可能不够健壮。

如果 TTML 文件中包含 iTunesMetadata 但没有 translation 标签,或者有 translation 标签但没有 iTunesMetadata,这可能会导致错误的正则表达式被应用,从而影响清洗的准确性。建议考虑更明确的方式来区分这两种情况,例如检查是否存在 translation 标签本身,或者根据 TTML 文件的结构约定来选择。

      if (/<translation[^>]+xml:lang="([^" ]+)"[^>]*>/.test(ttml_text)) { // 检查是否存在 <translation> 标签
        const translationRegex = /<translation[^>]+xml:lang="([^" ]+)"[^>]*>[\s\S]*?<\/translation>/g;

        return ttml_text.replace(translationRegex, replacer);
      } else {
        const spanRegex = /<span[^>]+xml:lang="([^" ]+)"[^>]*>[\s\S]*?<\/span>/g;

        return ttml_text.replace(spanRegex, replacer);
      }

@ranhengzhang
Copy link
Contributor Author

ranhengzhang commented Jan 8, 2026

拒绝 Ai 的建议

  1. 当前项目并没有支持 i18n,并且中文语言代码较为复杂,盲目引进只会增加当前项目的混乱程度
  2. ttml_cleaner 函数中使用 iTunesMetadata 是为了判断 TTML 文件标准,考虑到当前 ttml-db 中为了下游项目的兼容进行的处理,建议去掉 if 判断,同时执行两种修改:
const translationRegex = /<translation[^>]+xml:lang="([^"]+)"[^>]*>[\s\S]*?<\/translation>/g;
const spanRegex = /<span[^>]+xml:lang="([^" ]+)"[^>]*>[\s\S]*?<\/span>/g;
return ttml_text.replace(translationRegex, replacer).replace(spanRegex, replacer);

Consolidate regex replacements for translation and span tags.
@ranhengzhang
Copy link
Contributor Author

ranhengzhang commented Jan 8, 2026

拒绝 Ai 的建议

  1. 当前项目并没有支持 i18n,并且中文语言代码较为复杂,盲目引进只会增加当前项目的混乱程度
  2. ttml_cleaner 函数中使用 iTunesMetadata 是为了判断 TTML 文件标准,考虑到当前 ttml-db 中为了下游项目的兼容进行的处理,建议去掉 if 判断,同时执行两种修改:
const translationRegex = /<translation[^>]+xml:lang="([^"]+)"[^>]*>[\s\S]*?<\/translation>/g;
const spanRegex = /<span[^>]+xml:lang="([^" ]+)"[^>]*>[\s\S]*?<\/span>/g;
return ttml_text.replace(translationRegex, replacer).replace(spanRegex, replacer);

第二点更改已完成:

-  if (ttml_text.indexOf("iTunesMetadata") !== -1) {
  const translationRegex = /<translation[^>]+xml:lang="([^"]+)"[^>]*>[\s\S]*?<\/translation>/g;
-  return ttml_text.replace(translationRegex, replacer);
-  } else {
  const spanRegex = /<span[^>]+xml:lang="([^"]+)"[^>]*>[\s\S]*?<\/span>/g;
-  return ttml_text.replace(spanRegex, replacer);
+  return ttml_text.replace(translationRegex, replacer).replace(spanRegex, replacer);
-  }

开拓者 改写

- [Refactor] Enhance the logic for cleaning unnecessary translations in TTML content.
- [Fix] Adjust parameter handling and improve language matching functionality.
@imsyy imsyy merged commit f862bbe into imsyy:dev Jan 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants