# 翻译引擎(TranslationEngine)
本文按以下顺序说明翻译引擎能力:
- 普通翻译接口(
TranslationEngine) - 普通翻译接口的分隔线批量翻译(
allowBatchTranslationBySeparator) - 批量翻译接口(
BatchTranslationEngine)
# 一、普通翻译接口(TranslationEngine)
通过实现 TranslationEngine,可以为 MT 管理器的翻译模式和文本输入框增加单文本翻译能力。
# 接口概览
| 方法 | 说明 |
|---|---|
void init(PluginContext context) | 初始化翻译引擎 |
PluginContext getContext() | 获取插件上下文 |
String name() | 获取翻译引擎名称 |
Configuration getConfiguration() | 获取配置信息 |
List<String> loadSourceLanguages() | 加载源语言列表 |
List<String> loadTargetLanguages(String sourceLanguage) | 加载目标语言列表 |
String getLanguageDisplayName(String language) | 将语言代码转换为显示名称 |
void beforeStart() | 翻译开始前回调(UI线程) |
void onStart() | 翻译开始回调(子线程) |
String translate(String text, String sourceLanguage, String targetLanguage) | 执行翻译(子线程) |
void onFinish() | 翻译结束回调(子线程) |
void afterFinish() | 翻译结束后回调(UI线程) |
boolean onError(Exception e) | 错误处理回调(UI线程) |
# BaseTranslationEngine 基类
BaseTranslationEngine 提供了 TranslationEngine 的默认实现:
- 自动管理
PluginContext - 提供可重写的
init()(无参) - 提供可重写的
onBuildConfiguration(...) - 默认使用 MT 内置语言名称实现
getLanguageDisplayName(...) - 生命周期方法提供空实现
- 默认将
autoRepairFormatSpecifiersError设为true(仅无参构造)
构造方式:
BaseTranslationEngine():先调用onBuildConfiguration(builder)再构建配置BaseTranslationEngine(Configuration configuration):直接使用传入配置,不调用onBuildConfiguration(...)
# 生命周期
TranslationEngine 生命周期如下:
init(PluginContext)(每个引擎实例仅一次)beforeStart()(UI线程)onStart()(子线程)translate(...)(子线程,可多次)onFinish()(子线程)afterFinish()(UI线程)
如果 translate(...) 抛出异常,将调用 onError(...),且不会再调用 onFinish()、afterFinish()。
# 关键方法说明
# name
@NonNull
String name()
引擎显示名称。支持 {key} 本地化键,详见 本地化文本。
# translate
@NonNull
String translate(String text, String sourceLanguage, String targetLanguage) throws IOException
执行单文本翻译。
text:待翻译文本。若maxTranslationTextLength > 0,MT 调用该方法前会先按该长度口径拆分文本,传入的text不会超限sourceLanguage:源语言代码targetLanguage:目标语言代码- 返回值:翻译结果(不能为
null) - 异常:网络/IO 错误可抛出
IOException
# 配置项(普通翻译接口)
继承 BaseTranslationEngine 时,通常通过重写 onBuildConfiguration(...) 来设置配置:
public class OnlineTranslationEngine extends BaseTranslationEngine {
@Override
protected void onBuildConfiguration(ConfigurationBuilder builder) {
// 调用父类默认配置:会将 autoRepairFormatSpecifiersError 设为 true。
super.onBuildConfiguration(builder);
builder.setMaxTranslationTextLength(4000);
builder.setTextLengthCalculator(text -> text.getBytes(StandardCharsets.UTF_8).length);
builder.setAcceptTranslated(false);
}
}
| 字段 | 默认值 | 说明 |
|---|---|---|
maxTranslationTextLength | 0 | 单次翻译最大文本长度。<= 0 表示无限制 |
textLengthCalculator | null | 自定义长度计算器;为 null 时按 String.length()(字符数)计算 |
acceptTranslated | false | 是否允许把已翻译文本作为下一次输入 |
forceNotToSkipTranslated | false | 是否强制不跳过已翻译词条 |
targetLanguageMutable | false | 目标语言列表是否随源语言变化 |
autoRepairFormatSpecifiersError | false | 是否自动修复 %s 等格式化占位符误译 |
disableAutoHideLanguage | false | 是否禁用语言自动隐藏 |
注意:以上是
ConfigurationBuilder的默认值。若继承BaseTranslationEngine并使用无参构造,autoRepairFormatSpecifiersError默认会被设为true。
# setMaxTranslationTextLength
ConfigurationBuilder setMaxTranslationTextLength(int maxTranslationTextLength)
设置单次翻译最大长度,超长文本会自动拆分并拼接回填。
# setTextLengthCalculator
ConfigurationBuilder setTextLengthCalculator(TextLengthCalculator textLengthCalculator)
设置自定义文本长度计算器,用于定义 maxTranslationTextLength 的计量方式。
- 默认值:
null(按String.length()计算) - 典型场景:翻译 API 的限制基于 UTF-8 字节数、URL 编码长度等
- 约束:实现应满足可加性,即
calculate(a) + calculate(b) == calculate(a + b),否则文本拆分时可能出现长度计算偏差 - 不建议直接使用分词 Token 计数作为实现(通常不满足可加性)
# setAcceptTranslated
ConfigurationBuilder setAcceptTranslated(boolean acceptTranslated)
为 true 时,二次翻译可能使用“已翻译文本”作为输入;false 时始终用原文。
# setForceNotToSkipTranslated
ConfigurationBuilder setForceNotToSkipTranslated(boolean forceNotToSkipTranslated)
启用后,翻译模式中的“跳过已翻译”选项会被隐藏。
# setTargetLanguageMutable
ConfigurationBuilder setTargetLanguageMutable(boolean targetLanguageMutable)
启用后,源语言切换时会重新调用 loadTargetLanguages(sourceLanguage)。
# setAutoRepairFormatSpecifiersError
ConfigurationBuilder setAutoRepairFormatSpecifiersError(boolean autoRepairFormatSpecifiersError)
自动修复常见格式化占位符误译(例如 %s 被翻译成 %S)。
# setDisableAutoHideLanguage
ConfigurationBuilder setDisableAutoHideLanguage(boolean disableAutoHideLanguage)
设置是否禁用语言自动隐藏功能。
# 示例(普通翻译接口)
public class OnlineTranslationEngine extends BaseTranslationEngine {
private OkHttpClient httpClient;
@Override
protected void init() {
httpClient = new OkHttpClient.Builder().build();
}
@Override
protected void onBuildConfiguration(ConfigurationBuilder builder) {
// 调用父类默认配置:会将 autoRepairFormatSpecifiersError 设为 true。
super.onBuildConfiguration(builder);
builder.setMaxTranslationTextLength(4000);
builder.setTargetLanguageMutable(true);
}
@NonNull
@Override
public String name() {
return "在线翻译";
}
@NonNull
@Override
public List<String> loadSourceLanguages() {
return List.of("auto", "en", "zh-CN", "ja", "ko");
}
@NonNull
@Override
public List<String> loadTargetLanguages(String sourceLanguage) {
return List.of("en", "zh-CN", "ja", "ko");
}
@NonNull
@Override
public String translate(String text, String sourceLanguage, String targetLanguage) throws IOException {
Request request = new Request.Builder()
.url("https://api.example.com/translate?text=" + text
+ "&from=" + sourceLanguage
+ "&to=" + targetLanguage)
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("翻译请求失败: " + response.code());
}
return response.body().string();
}
}
@Override
public boolean onError(Exception e) {
if (e instanceof IOException) {
getContext().showToastL("网络错误:" + e.getMessage());
return true;
}
return false;
}
}
# 二、普通翻译接口的分隔线批量翻译
本节仅适用于“只实现 TranslationEngine、未实现 BatchTranslationEngine”的引擎。
# 启用方式
ConfigurationBuilder setAllowBatchTranslationBySeparator(boolean allowBatchTranslationBySeparator)
将该选项设为 true 后,翻译模式会启用分隔线批量翻译。
# 处理流程
在翻译模式中,MT 会把多个词条拼接成一个字符串,通过一次 translate(...) 调用降低网络往返。
- 词条之间使用
"\n" + divider + "\n"拼接。 - 分隔线会按当前批次动态生成,保证与本批原文不冲突。
- 如果翻译结果按分隔线拆分后数量不匹配,会自动切换另一套分隔线策略重试一次。
- 若重试后仍无法正确拆分,MT 会记录原始合并文本和翻译结果日志,并抛出
IOException。 - 分批时会把“分隔线开销”一并计入长度估算,长度口径由
textLengthCalculator(默认String.length())决定,而不是只看原文词条长度。 - 默认每批最多合并 100 条词条,达到上限会开启下一批请求。
# 与超长文本的关系
当 maxTranslationTextLength > 0 时,超长文本不会直接塞入分隔线合并请求,会先进入拆分翻译路径;其余文本仍按分隔线批量流程处理。
# 实现建议
translate(...)尽量保持分隔线和换行不变(不要自动裁剪、重排、改写标点)。- 如果上游翻译服务无法稳定保留分隔线,建议关闭此优化(
setAllowBatchTranslationBySeparator(false))。
# 三、批量翻译接口(BatchTranslationEngine)
当上游翻译 API 原生支持“多文本数组”请求时,建议实现 BatchTranslationEngine(通常继承 BaseBatchTranslationEngine)。
# 接口概览
BatchTranslationEngine 扩展自 TranslationEngine,除下表中的批量相关方法外,还继承 TranslationEngine 的全部方法(如生命周期、语言加载、错误处理等)。
| 方法 | 说明 |
|---|---|
String translate(String text, String sourceLanguage, String targetLanguage) | 兼容签名(@Deprecated,MT 运行时不会调用;翻译逻辑请实现于 batchTranslate(...)) |
String[] batchTranslate(String[] texts, String sourceLanguage, String targetLanguage) | 执行一批文本翻译(子线程,可多次) |
BatchingStrategy createBatchingStrategy() | 创建分批策略,控制 MT 如何拆批 |
# BatchingStrategy 概览
| 方法 | 说明 |
|---|---|
void reset() | 每个新批次开始前调用,重置内部累计状态 |
boolean tryAdd(String text) | 尝试把文本加入当前批次,返回 false 时 MT 会按批次流程回退/换批 |
# 核心契约
# translate(兼容签名)
@NonNull
@Deprecated
String translate(String text, String sourceLanguage, String targetLanguage) throws IOException
该方法仅为兼容 TranslationEngine 签名而保留,MT 运行时不会调用。
# batchTranslate
@NonNull
String[] batchTranslate(String[] texts, String sourceLanguage, String targetLanguage) throws IOException
texts:当前批次文本数组(不为空,可视为已通过当前BatchingStrategy容量校验)- 返回值:结果数组长度必须与
texts.length一致,数组与数组元素都不能为null - 异常:网络/IO 错误可抛出
IOException
# createBatchingStrategy
BatchingStrategy createBatchingStrategy()
返回分批策略实例,由 MT 调用 reset() / tryAdd(...) 来组织批次。
tryAdd(text) 返回 false 时,MT 的处理流程为:
- 当前批次不为空:先翻译当前批次,
reset()后再用同一文本重试一次tryAdd(...)(同一文本可能触发两次tryAdd)。 - 当前批次为空:拆分该文本使每一片段都符合当前策略,再逐段调用
batchTranslate(...)翻译并合并结果。
# BaseBatchTranslationEngine 基类
BaseBatchTranslationEngine 在 BaseTranslationEngine 基础上增加了 BatchTranslationEngine 的默认实现:
translate(...)为兼容入口(final,调用即抛异常)- 默认
createBatchingStrategy()返回DefaultBatchingStrategy(100, 5000);其中该策略的长度口径使用textLengthCalculator(未设置时按String.length())
BaseBatchTranslationEngine 的构造方式:
BaseBatchTranslationEngine():先调用onBuildConfiguration(builder)再构建配置BaseBatchTranslationEngine(Configuration configuration):直接使用传入配置,不调用onBuildConfiguration(...)
# 配置语义(批量翻译接口)
allowBatchTranslationBySeparator:在实现BatchTranslationEngine时不起作用(不生效);批量流程由batchTranslate(...)与createBatchingStrategy()接管。maxTranslationTextLength:在实现BatchTranslationEngine时不起作用(不生效);批量路径下的单文本拆分由BatchingStrategy容量探测与分段流程决定。acceptTranslated、forceNotToSkipTranslated、targetLanguageMutable、autoRepairFormatSpecifiersError、disableAutoHideLanguage:仍按各自语义生效。
# 示例(批量翻译接口)
public class OnlineBatchTranslationEngine extends BaseBatchTranslationEngine {
@Override
protected void onBuildConfiguration(ConfigurationBuilder builder) {
// 调用父类默认配置:会将 autoRepairFormatSpecifiersError 设为 true。
super.onBuildConfiguration(builder);
builder.setTargetLanguageMutable(true);
// 这里使用 UTF-8 字节数作为长度口径,和下方 DefaultBatchingStrategy 的长度限制保持一致。
builder.setTextLengthCalculator(text -> text.getBytes(StandardCharsets.UTF_8).length);
}
@NonNull
@Override
public String name() {
return "在线翻译(批量)";
}
@NonNull
@Override
public List<String> loadSourceLanguages() {
return List.of("auto", "en", "zh-CN", "ja", "ko");
}
@NonNull
@Override
public List<String> loadTargetLanguages(String sourceLanguage) {
return List.of("en", "zh-CN", "ja", "ko");
}
@NonNull
@Override
public String[] batchTranslate(String[] texts, String sourceLanguage, String targetLanguage) throws IOException {
String[] results = callBatchTranslationApi(texts, sourceLanguage, targetLanguage);
if (results == null || results.length != texts.length) {
throw new IOException("批量翻译返回结果长度不匹配");
}
return results;
}
@Override
public BatchingStrategy createBatchingStrategy() {
// maxTextLength=8000 按 UTF-8 字节数计算,而不是按字符数计算。
return new DefaultBatchingStrategy(100, 8000);
}
}
# 接口注册
所有翻译引擎实现都需要在模块的 build.gradle 中注册:
mtPlugin {
pluginID = "com.example.myplugin"
versionCode = 1
versionName = "v1.0"
name = "翻译插件"
interfaces = [
"com.example.myplugin.OnlineTranslationEngine",
"com.example.myplugin.OnlineBatchTranslationEngine",
]
}
# 相关接口
- PluginContext - 插件上下文
- LocalString - 本地化文本