跳到内容

Translate Starter

受众:开发者 摘要:统一翻译 Facade。LibreTranslate / Google / 腾讯云 / AI Model provider,占位符保护,文本 / HTML / JSON / 批量翻译,后台翻译协作。

何时使用

场景建议
单条文本翻译Translate.text(src, fromLocale, toLocale)
批量文本翻译Translate.texts(list, fromLocale, toLocale)
HTML 翻译(保留标签)Translate.html(...) / Translate.htmls(...)
JSON 翻译(只翻字符串值,不翻 key)Translate.json(...)
后台批量补译 i18n 文案用 i18n starter 的 /translate-batch API
需要详细失败原因Translate.translateWithDetails(...) 返回 Outcome
多 provider 自动切换default-provider: auto

Translate 默认启用,但默认 default-provider: none,不会在未配置 provider 时访问真实翻译服务。需要实际翻译时,显式选择并启用 provider。

I18n 负责「拿到正确文案」,Translate 负责「把文案翻译成另一种语言」。配套使用见 i18n.md

快速开始

yaml
spring:
  open:
    translate:
      enabled: true
      default-provider: tencent-cloud
      providers:
        tencent-cloud:
          enabled: true
          secret-id: ${TENCENT_TRANSLATE_SECRET_ID:}
          secret-key: ${TENCENT_TRANSLATE_SECRET_KEY:}
java
var result = Translate.text("你好,世界", Locale.SIMPLIFIED_CHINESE, Locale.ENGLISH);

Facade API

java
// 单条文本
Translate.text(text, fromLocale, toLocale);

// 批量文本
Translate.texts(List.of("文本1", "文本2"), fromLocale, toLocale);

// HTML(保留标签结构)
Translate.html("<p>你好 {name}</p>", fromLocale, toLocale);
Translate.htmls(List.of("<p>...</p>", "<strong>...</strong>"), fromLocale, toLocale);

// JSON(只翻译字符串值,不翻 key / 不动数字 / 布尔 / null / 数组结构)
Translate.json("{\"title\":\"你好\",\"items\":[\"用户名\",\"密码\"]}", fromLocale, toLocale);

// 详细结果(含失败原因)
TranslateOutcome outcome = Translate.translateWithDetails(
    TranslateRequest.of(text, fromLocale, toLocale));

TranslateOutcome 用于后台维护场景,可识别失败原因:翻译未启用、provider 未配置、provider 不存在、provider 异常、空结果。

配置项

通用配置

yaml
spring:
  open:
    translate:
      enabled: true                        # 默认启用;provider 未配置时不调用外部服务
      default-provider: none               # none / auto / libre-translate / google-translate / tencent-cloud / ai-model
      preserve-placeholders: true          # 保护 {0} / {name} / ${APP_NAME} / %s 等占位符
      placeholder-patterns: []             # 自定义占位符正则
配置默认值说明
enabledtrue启用开关;显式设为 false 时关闭翻译能力
default-providernone默认 provider
preserve-placeholderstrue占位符保护
placeholder-patterns内置规则占位符保护正则(顺序敏感)

default-provider: auto 适合开发和兜底;生产建议显式配置 provider,便于排查成本、限流、错误。

LibreTranslate

yaml
spring:
  open:
    translate:
      providers:
        libre-translate:
          enabled: true
          provider: libre-translate
          endpoint: ${TRANSLATE_LIBRE_ENDPOINT:https://libretranslate.example.com/translate}
          api-key: ${TRANSLATE_LIBRE_API_KEY:}
          api-key-header: ""               # 可选 header 名(默认走 body)
          format: text                     # text / html
          timeout: 10s
          locale-mapping:
            zh-CN: zh

Google Translate

yaml
spring:
  open:
    translate:
      providers:
        google-translate:
          enabled: true
          provider: google-translate
          endpoint: https://translation.googleapis.com/language/translate/v2
          api-key: ${GOOGLE_TRANSLATE_API_KEY:}
          format: text
          model: ""                        # 空 = 默认模型
          timeout: 10s
          locale-mapping:
            zh-CN: zh-CN
            zh-TW: zh-TW

腾讯云翻译

yaml
spring:
  open:
    translate:
      providers:
        tencent-cloud:
          enabled: true
          provider: tencent-cloud
          endpoint: https://tmt.tencentcloudapi.com
          secret-id: ${TENCENT_TRANSLATE_SECRET_ID:}
          secret-key: ${TENCENT_TRANSLATE_SECRET_KEY:}
          token: ""                        # 可选临时密钥
          region: ap-guangzhou
          project-id: 0
          timeout: 10s
          locale-mapping:
            zh-CN: zh
            zh-TW: zh-TW

配置优先级:数据库配置同名 key > 环境变量 / .env > application.yml 默认值。

AI Model

ai-model Provider 通过 spring-open-starter-ai-modelAiModelManager 调用统一模型底座,不直接绑定 OpenAI、通义、Claude 或 DeepSeek SDK。它默认关闭,只有应用同时引入 AI Model starter 并显式启用 provider 时才会参与路由。

yaml
spring:
  open:
    translate:
      enabled: true
      default-provider: ai-model
      providers:
        ai-model:
          enabled: true
          model-provider: deepseek          # 对应 spring.open.ai.model.providers.<name>
          model: deepseek-chat
          temperature: 0.1
          max-tokens: 1024
          prompt: |-
            Translate the following {format} content from {sourceLocale} to {targetLocale}.
            Return only the translated content. Preserve placeholders, variables, HTML tags and JSON keys.

            {text}

prompt 支持 {text}{sourceLocale}{targetLocale}{format} 占位。返回的 TranslateResult.metadata() 会带上 aiModelProvideraiModelModelfinishReasoninputTokensoutputTokenstotalTokens,便于后台预览、审计和后续计量归集。

Provider

Provider说明适用
none不选 provider默认
auto依次尝试已启用 provider开发 / 兜底
libre-translateLibreTranslate 或兼容接口自建 / 私有部署
google-translateGoogle Cloud Translation Basic v2海外业务
tencent-cloud腾讯云机器翻译 TMT国内业务
ai-model统一 AI Model starter运营文案、长文本和需要模型质量的翻译

ai-model 只依赖统一 AI Model 抽象,不在 Translate starter 内引入具体模型 SDK。

扩展点与源码骨架

层级主要类型责任
业务 FacadeTranslate面向业务代码提供短名静态 API,转交给 TranslateManager
编排层TranslateManager / DefaultTranslateManager启用开关、provider 路由、auto 兜底、占位符保护、失败原因归一化
请求 / 结果TranslateRequest / TranslateResult / TranslateOutcome统一文本、语言、格式、实际 provider、失败原因
Provider SPITranslateProvider封装单个厂商或兼容接口的协议调用
Provider 贡献者TranslateProviderContributor / DefaultTranslateProviderContributor通过 ServiceLoader 注册内置或外部 provider
运行时配置TranslateRuntimeConfig / TranslateRuntimeConfigSource读取 spring.open.translate.*,支持配置中心覆盖本地配置
占位符保护TranslatePlaceholderProtector翻译前保护模板变量,翻译后还原
JSON 支持TranslateJsonSupport只翻译 JSON 字符串值,保持结构和 key 不变

分层原则:

  • 业务模块只调用 Translate 或注入 TranslateManager,不要直接拼 provider 客户端。
  • I18n 负责文案查询、落库和翻译批处理入口,Translate 只负责“把文本翻译成目标语言”。
  • Manager 负责路由、兜底和错误语义;Provider 只负责具体厂商协议。
  • 配置中心覆盖、本地配置兜底和 provider-specific 语言映射都统一放在 TranslateRuntimeConfig
  • 新增厂商优先实现 TranslateProvider,复杂外部扩展包再提供 TranslateProviderContributor

文本 / HTML / JSON

内容类型推荐方法行为
纯文本Translate.text / texts按 provider format 配置
HTMLTranslate.html / htmlsprovider 的 format=html
JSONTranslate.json解析 JSON,只翻译字符串,不翻 key

JSON 翻译特性:

  • 输出仍是合法 JSON
  • 不动数字 / 布尔 / null / 数组结构 / 对象 key
  • 适合前端文案包、配置说明、通知 payload 样板、后台元数据
  • 非法 JSON 返回空结果
  • 单字符串翻译失败保留原值;整批失败返回空结果
  • HTML 片段优先用 Translate.html(...),不要包在 JSON 字符串里

腾讯云 TMT 当前按普通文本 API 处理,复杂富文本建议先拆分文本节点或用支持 HTML format 的 provider。

占位符保护

preserve-placeholders=true 时翻译前保护常见占位符,翻译后还原,避免第三方翻译把模板变量改坏。

默认保护:

  • Spring i18n / MessageFormat:{0} / {name} / {app.name}
  • 配置或前端变量:${APP_NAME}
  • Java formatter:%s / %1$s
  • 模板变量:&#123;&#123; user.name &#125;&#125;

示例:

text
messages.welcome.text=Hello! Welcome {0} to my [ {1} ] website.

自定义占位符正则(覆盖 placeholder-patterns):

yaml
spring:
  open:
    translate:
      placeholder-patterns:
        - "\\{\\{\\s*[^{}]+\\s*}}"
        - "\\{\\s*[A-Za-z0-9_.-]+(?:\\s*,\\s*[^{}]+){0,2}\\s*}"
        - "\\$\\{[^{}]+}"
        - "%\\d*\\$?[A-Za-z]"
        - "<%\\s*[^%]+\\s*%>"

建议业务文案、Validation 文案和通知模板都保留明确占位符,不要把变量拼接进待翻译文本。

扩展自定义 Provider

实现 TranslateProvider 并注册为 Spring Bean:

java
@Component
public class MyProvider implements TranslateProvider {
    @Override public String name() { return "my-provider"; }
    @Override public Optional<TranslateResult> translate(TranslateRequest request) { ... }
}

外部扩展包可用 TranslateProviderContributor + Java ServiceLoader,让 provider 不直接侵入应用模块。

后台协作

I18n 后台的 /api/v1/admin/i18n/messages/translate-batch 复用 Translate provider:

  1. zh-CN 写入或收集源文案
  2. 配置 Translate provider
  3. 调用 batch 翻译 API 预览
  4. save=true 保存目标语言文案到 i18n_message

保存后 source 记录为 translation:<provider>(例 translation:google-translate)。

AI 模型翻译

详见 .ai/decisions/adr-030-ai-translate-provider.md

设计边界:

  • Translate 只依赖 TranslateProvider 和统一 AI Model 抽象,直接依赖 OpenAI / 通义 / Claude SDK
  • ai-model 默认关闭;缺失翻译收集默认只记录待翻译项,不自动调用模型
  • 后台预览和批量补译可显式选择 ai-model,保存结果时来源记录为 translation:ai-model
  • 翻译前继续保护 {0} / {name} / ${APP_NAME} / %s 等占位符
  • Provider 通过 AI Model starter 承接模型选择、超时、重试、限流和 token usage,Translate 侧保留占位符保护、格式提示和来源元数据

注意事项

  • 生产环境密钥放数据库配置或环境变量,application.yml
  • Translate 模块默认启用;真实翻译仍需要选择并启用至少一个 provider
  • default-provider: auto 多 provider 切换时按声明顺序,第一个成功的返回
  • 不在低延迟链路(订单创建 / 支付回调)实时调用第三方翻译,建议异步 + 缓存

验证命令

bash
./mvnw -pl spring-open-starters/spring-open-starter-translate -am test -DskipITs

相关

  • I18n(多语言文案):i18n.md
  • AI 模型翻译:.ai/decisions/adr-030-ai-translate-provider.md
  • 动态业务元数据本地化:.ai/decisions/adr-029-dynamic-metadata-i18n.md
  • 配置中心(数据库配置覆盖):config.md
  • Provider 扩展模型:provider.md

Released under the Apache License 2.0.