图片翻译编辑器协议

更新时间:
复制 MD 格式

1、产品简介

该编辑器当前支持图片翻译标准版和图片翻译Pro,融合多模态大模型技术,支持100+语向互译,通过编辑器对图片翻译结果进行局部优化与二次编辑,满足用户对高质量多语言营销物料的制作需求。

编辑器本身不收费,只有当使用了图片翻译标准版,图片翻译Pro版,文本翻译时会触发收费,收费方式详见本文9的计费方式。

主要功能

功能概述

Demo

端面简介

  1. 左侧翻译面板-常驻

    • 传图

      • 展示图片要求,包含格式,尺寸,大小

      • 每次可以传1张,暂不支持传多次

    • 2个版本图片翻译可切换

      • 可选择性接入

    • 原始语向

      • 选择图片翻译Pro版时,原始语向支持自动识别,默认优先展示自动识别,自动识别支持24个语向,详见下方 7.2

    • 目标语向

      • 用户点击下拉框选择想要的语向

    • 品牌词保护

      • 开启品牌保护后主流品牌将不会被翻译,默认开启

    • 立即翻译

      • 点击后则开始执行翻译

      • 翻译成功则进行扣费,计费方式详见下方第 9 节

  2. 顶栏

    • 返回按钮-常驻

    • 图片编辑-常驻

    • 下载-常驻

      • 下载译后图片/编辑后的图片,下载时自动触发保存

    • 保存-常驻

      • 保存已编辑的内容

    • 历史-常驻

      • 可查看历史任务,包含已经翻译成功的任务,和点击了保存的二次编辑内容

      • 点击某个历史任务后可以还原回该任务的历史状态

    • 文字-图翻前常驻,图翻后展示编辑态

      • 点击后可以自定义添加文字

      • 可以对添加后的文字继续进行翻译及其他二次编辑动作,如字号,字体大小,字重等多种功能

    • 贴纸-图翻前常驻,图翻后展示编辑态

      • 平台提供贴纸库

      • 添加贴纸后依然可以对贴纸进行二次编辑,颜色,不透明度,文本

    • 素材-图翻前常驻,图翻后展示编辑态

      • 可以从本地上传素材

      • 支持对素材的二次编辑,颜色,不透明度,倾斜角

  3. 中央画布

    • 翻译前,展示中央画布区及底部缩放功能

    • 翻译后,展示翻译成功的图片,展示右侧二次编辑面板

  1. 翻译前端面样式

image.png

  1. 上传图翻后,未翻译

image.png

  1. 上传图片后,翻译成功,调整译文

image.png

  1. 添加文字

image.png

  1. 添加贴纸

image.png

  1. 添加素材

image.png

2、方案介绍

本期图像编辑器产品对外提供两种接入形态,二者共用同一套「iframe + postMessage」的通信框架,差异仅在于所嵌入的能力路由与输入参数。您可以根据下表选择匹配自身业务的方案。

如何选择:

  • 需要一站式、多能力串联、且希望翻译数据不流出自身业务系统 → 选方案A。

  • 已经在使用图片翻译Pro API、仅需要对既有翻译结果做人工二次编辑 → 选方案B。

维度

方案A:一站式图像工作台

方案B:二次编辑

定位

翻译、抠图、消除、场景图等多能力串联的一站式工作台

在图片翻译 API 结果之上做二次编辑的专用编辑器

典型使用场景

客户希望翻译流程与编辑闭环在一个界面内完成,翻译过程与数据全部在客户侧沉淀

客户已对接图片翻译API,选择目标图片后进入编辑器做局部优化,属于「API + 编辑器」两段式

数据管理

上传、翻译、编辑、导出全部在接入方的工作台内完成

翻译由 API 完成,编辑器仅承接二次编辑;翻译结果与协议由客户自行管理

可组合能力

图片翻译标准版,图片翻译Pro版,以及二次编辑时的文本翻译

计费方式

编辑器本身不收费,使用到翻译API能力时收费,包含图片翻译和文本翻译

3、接入方式

3.1、整体流程

  1. 客户前端向客户服务端发起请求,例如 POST /api/aidge-editor/access-url。

  2. 客户服务端根据当前用户身份,向阿里云登录服务申请一次性 Key,并拼接完整的 iframe URL。

  3. 客户服务端将完整的 iframe URL 返回给客户前端。

  4. 客户前端创建或刷新 iframe,并将 src 设置为该 URL。

  5. 阿里云登录服务对 Key 进行校验。校验通过后,进入编辑器页面。

  6. 编辑器页面加载完成后,通过 postMessage 向父页面发送加载完成事件。

  7. 客户前端收到加载完成事件后,通过 postMessage 向 iframe 发送初始化事件,并携带相应的初始化参数。

建议由客户服务端直接返回完整的 iframe URL,以减少前端拼接错误并降低 Key 泄露风险。客户服务端也可仅返回 Key,由客户前端获取 Key 后立即拼接 iframe URL。

如需对下游用户进行数据隔离,可将用户唯一 ID 传入 RoleSessionName 字段。详见下方 3.2.6 中的 Java 示例代码。

3.2、客户服务端接入

具体实现可参考 免登访问 方案。

3.2.1、创建 RAM 子用户并授权

如子账号已存在,可跳过此步骤。

3.2.2、为 RAM 用户授权 AliyunSTSAssumeRoleAccess

image.png

3.2.3、创建 RAM 角色

使用 RAM 主账号登录控制台并创建 RAM 角色,也可通过 RAM API CreateRole 创建。

image.png

image.png

image.png

3.2.4、为角色授权

搜索“Aidge”,并选择对应的权限策略。

image.png

3.2.5、获取 roleArn、accessKeyId、accessKeySecret 参数

image.png

image.png

image.png

3.2.6、Java 示例代码

<dependencies>
      <dependency>
          <groupId>com.aliyun</groupId>
          <artifactId>aliyun-java-sdk-sts</artifactId>
          <version>3.0.0</version>
      </dependency>
      <dependency>
          <groupId>com.aliyun</groupId>
          <artifactId>aliyun-java-sdk-core</artifactId>
          <version>3.5.0</version>
      </dependency>
      <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
          <version>4.5.5</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.47</version>
      </dependency>
</dependencies>
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URISyntaxException;

/**
 * Aidge 虚商控制台免登接入示例。
 * <p>
 * 流程:AssumeRole 获取临时凭证 → GetSigninToken → 构造 federation 免登链接。
 */
public class Test {

    private static final String SIGN_IN_DOMAIN = "https://signin.aliyun.com/federation";

    /**
     * 使用安全令牌获取登录令牌
     * https://help.aliyun.com/document_detail/91913.html
     *
     * @param accesskeyId
     * @param accessKeySecret
     * @param securityToken
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    private static String getSignInToken(String accesskeyId, String accessKeySecret, String securityToken)
            throws IOException, URISyntaxException {
        URIBuilder builder = new URIBuilder(SIGN_IN_DOMAIN);

        builder.setParameter("Action", "GetSigninToken")
                .setParameter("AccessKeyId", accesskeyId)
                .setParameter("AccessKeySecret", accessKeySecret)
                .setParameter("SecurityToken", securityToken)
                .setParameter("TicketType", "mini");

        HttpGet request = new HttpGet(builder.build());
        CloseableHttpClient httpclient = HttpClients.createDefault();

        try (CloseableHttpResponse response = httpclient.execute(request)) {
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String context = EntityUtils.toString(response.getEntity());
                JSONObject jsonObject = JSON.parseObject(context);
                return jsonObject.getString("SigninToken");
            } else {
                System.out.println(response.getStatusLine());
            }
        }
        return null;
    }

    private static String getChatbotLoginUrl(String pageUrl, String signInToken) throws URISyntaxException {
        URIBuilder builder = new URIBuilder(SIGN_IN_DOMAIN);
        builder.setParameter("Action", "Login");
        // 登录失效后的跳转地址,一般配置为自建 Web 服务中用于 302 跳转的 URL
        builder.setParameter("LoginUrl", "https://signin.aliyun.com/login.htm");
        // 实际访问的 Aidge 控制台页面,例如首页或编辑器页面
        builder.setParameter("Destination", pageUrl);
        builder.setParameter("SigninToken", signInToken);
        HttpGet request = new HttpGet(builder.build());
        return request.getURI().toString();
    }

    /**
     * 通过 AssumeRole 接口获取用户临时身份
     * 参考 https://help.aliyun.com/document_detail/28763.html
     *
     * @param roleArn         RAM 角色 ARN,格式:acs:ram::&lt;主账号UID&gt;:role/&lt;角色名&gt;
     * @param accessKeyId     调用方 AK
     * @param accessKeySecret 调用方 SK
     * @param roleSessionName 用户自定义会话名,可用于用户级别的访问审计。格式:^[a-zA-Z0-9\.@\-_]+$
     * @return
     * @throws ClientException
     */
    private static AssumeRoleResponse.Credentials assumeRole(String roleArn, String accessKeyId,
                                                             String accessKeySecret, String roleSessionName)
            throws ClientException {
        String defaultRegion = "cn-hangzhou";
        IClientProfile profile = DefaultProfile.getProfile(defaultRegion, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        AssumeRoleRequest request = new AssumeRoleRequest();
        // 直接使用拼接好的角色 ARN
        request.setRoleArn(roleArn);
        // 用户自定义参数。此参数用来区分不同的令牌,可用于用户级别的访问审计。格式:^[a-zA-Z0-9\.@\-_]+$
        request.setRoleSessionName(roleSessionName);
        // 指定过期时间,单位为秒。可设置为 900~3600,默认值为 3600
        request.setDurationSeconds(3600L);
        AssumeRoleResponse response = client.getAcsResponse(request);
        return response.getCredentials();
    }

    public static void main(String[] args) throws IOException, URISyntaxException {
        try {
            /*
             * Step 0:准备子账号并完成权限授权
             */
            // 要扮演的 RAM 角色 ARN(由主账号 UID 和角色名拼接),请替换为真实值 acs:ram::${accountId}:role/${roleName}
            String roleArn = "按需替换";
            // 子账号的 AK 和 SK,需具备 AliyunSTSAssumeRoleAccess 权限,请替换为真实值
            String accessKeyId = "按需替换";
            String accessKeySecret = "按需替换";

            // 业务侧用户 ID:用于同一 RAM 角色下区分真实业务用户,便于访问审计。
            // 建议填写业务系统中的用户唯一标识(如 userId),格式需满足:^[a-zA-Z0-9.@-_]+$,长度为 2~64 个字符
            String userId = "按需替换";

            /*
             * Step 1:通过 AssumeRole 接口获取临时 AK、SK 和 SecurityToken
             */
            AssumeRoleResponse.Credentials credentials =
                    assumeRole(roleArn, accessKeyId, accessKeySecret, userId);

            System.out.println("Expiration: " + credentials.getExpiration());
            System.out.println("Access Key Id: " + credentials.getAccessKeyId());
            System.out.println("Access Key Secret: " + credentials.getAccessKeySecret());
            System.out.println("Security Token: " + credentials.getSecurityToken());
            System.out.println("RoleSessionName: " + userId);

            /*
             * Step 2:获取 SigninToken
             */
            String signInToken = getSignInToken(credentials.getAccessKeyId(),
                    credentials.getAccessKeySecret(),
                    credentials.getSecurityToken());

            System.out.println("Your SigninToken is: " + signInToken);

            // 集成 Aidge 编辑器页
            String pageUrl = "https://ecoa4service.console.aliyun.com/editor";

            String accessUrl = getChatbotLoginUrl(pageUrl, signInToken);
            System.out.println("Your PageUrl is : " + accessUrl);
        } catch (ClientException e) {
            System.out.println("Failed:");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());
        }
    }
}

3.2.7、生成 Key 的服务端要求

  • Key 生成逻辑必须部署在服务端。服务端应妥善保管 AK、SK、RoleArn 和 Secret 等敏感信息。

  • 每次打开编辑器页面时,都应生成新的 Key。

  • 不得将 Key 作为长期凭证持久化存储。如需记录,应仅保留必要的审计信息,并避免将其明文输出至前端日志、Nginx 访问日志或监控系统。

  • Key 生成后应立即使用。一次性 Key 的有效期为 30 秒,且仅可使用一次。

  • 刷新或重新打开页面,以及复制链接后再次访问时,都应重新执行服务端 Key 生成流程。

3.3、客户前端接入

在页面中通过 <iframe> 标签引入编辑器,并将 src 设置为服务端返回的地址。详见上方 3.2。

客户前端与编辑器通过 postMessage 进行通信。编辑器的 Origin 为 https://ecoa4service.console.aliyun.com。建议客户前端发送消息时指定该 Origin,接收消息时校验该 Origin。详见下方 3.3.7。

当客户前端收到编辑器 iframe 发送的 pageReady 消息后,可向编辑器发送 actioninit 的消息,完成初始化。

window.addEventListener("message", (ev: MessageEvent) => {
  const { action } = ev.data ?? {};

  if (action === "pageReady") {
    iframeEle.contentWindow?.postMessage(
      {
        action: "init",
        data: {
          tool: "translate",
        },
      },
      editorOrigin,
    );
  }
});

3.3.1、编辑器初始化配置项

序号

名称

配置字段

字段类型

是否必填

默认值

说明

1

编辑器能力

tool

string

-

translate:图片翻译标准版

translatePro:图片翻译 Pro 版

translateBoth:图片翻译标准版 + Pro 版,可在编辑器中切换能力

2

图片 URL

imageUrl

string

-

待翻译图片的 URL。请勿直接使用限制图片访问的电商平台图片链接,建议转存后再传入。如不传入,可在编辑器中手动上传

3

原始语向

sourceLanguage

string

-

如不传入,可在编辑器中手动选择。支持的语向详见下方 7.1

4

目标语向

targetLanguage

string

-

如不传入,可在编辑器中手动选择。支持的语向详见下方 7.1

5

原文保留(品牌名)默认值

includingProductAreaDefaultValue

boolean

true

true:默认选中原文保留(品牌名)

false:默认不选中原文保留(品牌名)

6

二次编辑

reEdit

boolean

false

true:直接编辑翻译后的图片,不展示左侧上传面板和历史记录;此时需同时传入翻译后的图层信息 reEditData

false:展示左侧上传面板和历史记录

7

二次编辑数据

reEditData

string

''

翻译后的结果数据,包含图层信息,可从 API 返回结果中获取

8

生产拦截

charge

boolean

false

true:点击“立即翻译”时,先向 iframe 的父页面发送消息;收到父页面返回的确认消息后,再执行实际调用。接入方可借此控制用户的付费 API 调用请求

false:点击“立即翻译”后立即执行调用

9

是否执行调用

enableToolExecution

boolean

true

true:用户点击“立即翻译”后,调用对应接口,记录历史任务,展示“历史”按钮;false:不调用接口,也不记录历史任务,隐藏“历史”按钮,接入方可自行调用翻译 API,并通过 applyToolResult 消息将结果传回编辑器,详见 4.3

10

编辑器 UI 配置

editorConfig

object

{}

对于每个子配置项,如果用户已传入自定义值,则以自定义值为准;未传入的子配置项将使用下表中的默认值

3.3.2、editorConfig 配置项

以下配置项均为选填项。

序号

名称

配置字段

字段类型

默认值

说明

1

返回按钮是否展示

showBack

boolean

false

true:展示返回按钮,点击时会发送消息

false:隐藏返回按钮

2

“图片编辑器”大标题文案

editorTitle

string

"图片编辑器"

-

3

“历史”按钮是否展示

showHistory

boolean

true

true:展示历史按钮(按钮文案可配置)

false:隐藏历史按钮及其图标

4

“历史”按钮文案

historyButtonText

string

"历史"

-

5

“图片翻译”标题文案

imageTransPanelTitle

string

"图片翻译"

-

6

“历史任务”标题文案

historyPanelTitle

string

"历史任务"

-

7

“点击上传图片”按钮文案

imageUploaderButtonText

string

"点击上传图片"

-

8

“标准版”标签文案

imageTransLabel

string

"标准版"

tool = translate 时,标签展示在“图片翻译”标题右侧;设置为 '' 时不展示。tool = translateBoth 时,标签展示在图片上传区域下方;即使设置为 '' 也会展示;且该文案将同时用作历史任务的任务类型标签

9

“Pro 版”标签文案

imageTransProLabel

string

"Pro 版"

tool = translatePro 时,标签展示在“图片翻译”标题右侧;设置为 '' 时不展示。tool = translateBoth 时,标签展示在图片上传区域下方;即使设置为 '' 也会展示;且该文案将同时用作历史任务的任务类型标签

10

“标准版”说明文案

imageTransTip

string

"高性价比"

设置为 '' 时不展示 Tooltip

11

“Pro 版”说明文案

imageTransProTip

string

"翻译更精准"

设置为 '' 时不展示 Tooltip

12

“语言”小标题文案

imageTransOptionsTitle

string

"语言"

-

13

“原始语向”选项标签文案

sourceLanguageLabel

string

"原始语向"

-

14

“原始语向”选项说明文案

sourceLanguageTip

string

"被翻译内容的语向"

设置为 '' 时不展示 Tooltip

15

“目标语向”选项标签文案

targetLanguageLabel

string

"目标语向"

-

16

“目标语向”选项说明文案

targetLanguageTip

string

"想要翻译成的语向"

设置为 '' 时不展示 Tooltip

17

“原文保留(品牌名)”选项标签文案

includingProductAreaLabel

string

"原文保留(品牌名)"

-

18

“原文保留(品牌名)”选项说明文案

includingProductAreaTip

string

"开启后主流品牌将不会被翻译"

设置为 '' 时不展示 Tooltip

19

“立即翻译”按钮文案

imageTransButtonText

string

"立即翻译"

-

20

“文案”按钮是否展示

showAddText

boolean

true

true:展示文案按钮

false:隐藏文案按钮

21

“贴纸”按钮是否展示

showAddSticker

boolean

true

true:展示贴纸按钮

false:隐藏贴纸按钮

22

“素材”按钮是否展示

showAddImage

boolean

true

true:展示素材按钮

false:隐藏素材按钮

3.3.3、编辑器消息体

编辑器通过 postMessage 发送的消息体结构如下:

{
  biz: "translate",
  action: "generate",
  data: {
    imageNum: 1,
  },
}

字段说明:

字段

示例值

是否必返

含义

biz

"translate"

业务标识。图片翻译标准版为 "translate",图片翻译 Pro 版为 "translatePro"

action

"generate"

消息类型

data

{ imageNum: 1 }

消息数据

3.3.4、编辑器报错消息体

编辑器通过 postMessage 发送的报错消息体结构如下:

{
  biz: "translate",
  action: "error",
  errCode: "translate-taskError",
  errMessage: errMsg,
}

字段说明:

字段

示例值

是否必返

含义

biz

"translate"

发生错误的业务标识

action

"error"

消息类型。报错消息固定为 "error"

errCode

"translate-taskError"

"translate-taskError":翻译失败

errMessage

errMsg

错误信息

接入方可根据 errCode 自定义面向用户的错误提示。

3.3.5、编辑器发送的消息

通信方向:编辑器 iframe → 客户前端

action

触发时机

消息体

关键数据

关联消息

pageReady

编辑器页面加载完成

{ action: "pageReady" }

无其他字段

客户前端收到后发送 init

back

用户点击返回按钮,且初始化配置中 editorConfig.showBacktrue

{ action: "back" }

无其他字段

-

generate

用户准备发起付费 API 调用,且初始化配置中 chargetrue

{ biz, action: "generate", data }

data.imageNum:本次准备生成的图片数量

data.params:本次调用的参数

客户前端需返回 respond

error

编辑器业务执行失败

{ biz, action: "error", errCode, errMessage }

errCode:错误码

errMessage:错误信息

详见上方 3.3.4

-

taskSuccess

生成任务执行成功

{ biz, action: "taskSuccess", data }

data: ResultItem[]

详见下方 5.1

-

submitAll

用户点击“保存”或“下载”,或编辑器响应 requestResult

{ biz, action: "submitAll", data }

data: ResultType[]

详见下方 5.3

可由 requestResult 主动触发

3.3.6、编辑器可接收的消息

通信方向:客户前端 → 编辑器 iframe

action

发送时机

消息体

关键数据

编辑器处理结果

init

客户前端收到 pageReady

{ action: "init", data }

data.tool:编辑器能力,必传

详见上方 3.3.1

根据配置完成编辑器初始化

respond

客户前端收到 generate

{ biz, action: "respond", success }

biz:需与 generate.biz 保持一致

success: true:继续生产

success: false:中断生产

详见下方 4.1

根据 success 决定是否执行付费 API 调用

applyToolResult

客户前端自行完成 API 调用后

{ biz, action: "applyToolResult", data }

biz:需与 generate.biz 保持一致

data:API 调用的结果数据

详见下方 4.3

加载并展示结果

requestResult

客户前端需主动获取当前完整结果时

{ action: "requestResult" }

无其他字段

详见下方 5.1

编辑器通过 submitAll 返回完整结果

3.3.7、示例前端代码

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Aidge 编辑器接入示例</title>

    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        margin: 0;
      }

      #editorIframe {
        display: block;
        width: 100%;
        height: 100%;
        border: 0;
      }
    </style>
  </head>

  <body>
    <iframe
      id="editorIframe"
      title="Aidge 在线编辑器"
      allow="clipboard-read; clipboard-write"
      ></iframe>

    <script>
      const editorIframe = document.getElementById("editorIframe");

      // 编辑器页面的 Origin,用于校验和发送 postMessage。
      const editorOrigin = "https://ecoa4service.console.aliyun.com";

      // 编辑器初始化参数。请根据实际业务替换示例值。
      const editorInitData = {
        // translate:图片翻译标准版
        // translatePro:图片翻译 Pro 版
        // translateBoth:标准版 + Pro 版,可在编辑器中切换
        tool: "translateBoth",

        // 以下三项为选填项。不传 imageUrl 时,可在编辑器中手动上传图片。
        imageUrl: "https://example.com/source.jpg",
        sourceLanguage: "zh",
        targetLanguage: "en",

        // 开启生产拦截。编辑器发送 generate 后,会等待父页面返回 respond。
        charge: true,

        // editorConfig 及其所有子配置项均为选填项。
        editorConfig: {
          editorTitle: "图片编辑器",
          showHistory: true,
          historyButtonText: "历史",
          imageTransPanelTitle: "图片翻译",
          historyPanelTitle: "历史任务",
          imageUploaderButtonText: "点击上传图片",
          imageTransLabel: "标准版",
          imageTransProLabel: "Pro 版",
          imageTransTip: "高性价比",
          imageTransProTip: "翻译更精准",
          imageTransOptionsTitle: "语言",
          sourceLanguageLabel: "原始语向",
          sourceLanguageTip: "被翻译内容的语向",
          targetLanguageLabel: "目标语向",
          targetLanguageTip: "想要翻译成的语向",
          includingProductAreaLabel: "原文保留(品牌名)",
          includingProductAreaTip: "开启后主流品牌将不会被翻译",
          includingProductAreaDefaultValue: true,
          imageTransButtonText: "开始翻译",
          showAddText: true,
          showAddSticker: true,
          showAddImage: true
        }
      };

      /**
     * 判断是否允许本次付费 API 调用。
     * 实际接入时,请在此处调用客户服务端,校验用户余额或权限。
     */
      async function checkGenerationPermission({ biz, imageNum, data }) {
        console.log("待确认的生产请求:", {
          biz,
          imageNum,
          data
        });

        // TODO:根据实际业务返回校验结果。
        return true;
      }

      /**
     * 处理生产拦截请求。
     */
      async function handleGenerate(message) {
        const { biz, data } = message;
        const { imageNum } = data ?? {};
        let success = false;

        try {
          success = await checkGenerationPermission({
            biz,
            imageNum,
            data
          });
        } catch (error) {
          console.error("生产请求校验失败:", error);
        }

        // biz 必须与编辑器发送的 generate 消息保持一致。
        editorIframe.contentWindow.postMessage(
          {
            biz,
            action: "respond",
            success
          },
          editorOrigin
        );
      }

      /**
     * 处理编辑器报错。
     */
      function handleEditorError(message) {
        const { biz, errCode, errMessage } = message;

        console.error("编辑器报错:", {
          biz,
          errCode,
          errMessage
        });

        // TODO:可根据 errCode 自定义面向用户的错误提示。
      }

      /**
     * 处理算法生成结果。
     * 该结果不包含用户在编辑器中的后续编辑操作。
     */
      function handleTaskSuccess(message) {
        const { biz, data } = message;
        const results = Array.isArray(data) ? data : [];

        console.log("生成任务完成:", {
          biz,
          results
        });

        // TODO:根据实际业务处理算法生成结果。
      }

      /**
     * 处理用户点击“保存”或“下载”后返回的最终结果。
     */
      function handleSubmitAll(message) {
        const results = Array.isArray(message.data) ? message.data : [];

        console.log("收到编辑器最终结果:", results);

        // TODO:将 schema 原样保存,不得修改其内容。
        // TODO:及时转存结果图片,返回的图片 URL 默认有效期为 7 天。
      }

      /**
     * 监听编辑器 iframe 发送的消息。
     */
      window.addEventListener("message", function (event) {
        // 只接收当前编辑器 iframe 发送的消息。
        if (event.source !== editorIframe.contentWindow) {
          return;
        }

        // 校验消息来源,避免处理其他网站发送的消息。
        if (event.origin !== editorOrigin) {
          console.warn("忽略未知来源的消息:", event.origin);
          return;
        }

        const message = event.data;

        if (!message || typeof message !== "object") {
          return;
        }

        switch (message.action) {
          case "pageReady":
            console.log("编辑器页面已准备就绪");

            // 收到 pageReady 后发送初始化参数。
            editorIframe.contentWindow.postMessage(
              {
                action: "init",
                data: editorInitData
              },
              editorOrigin
            );
            break;

          case "generate":
            // 生产拦截为异步流程,处理结果将通过 respond 返回编辑器。
            void handleGenerate(message);
            break;

          case "error":
            handleEditorError(message);
            break;

          case "taskSuccess":
            handleTaskSuccess(message);
            break;

          case "submitAll":
            handleSubmitAll(message);
            break;

          default:
            console.warn("收到未识别的编辑器消息:", message);
        }
      });

      /**
     * 从客户服务端获取编辑器地址,并设置 iframe src。
     */
      async function loadEditor() {
        try {
          const response = await fetch("/api/aidge-editor/access-url", {
            method: "POST",
            cache: "no-store"
          });

          if (!response.ok) {
            throw new Error(`获取编辑器地址失败:HTTP ${response.status}`);
          }

          const result = await response.json();

          if (!result.src) {
            throw new Error("服务端未返回编辑器 src");
          }

          const editorUrl = new URL(result.src);

          if (editorUrl.protocol !== "https:") {
            throw new Error("编辑器地址必须使用 HTTPS");
          }

          // 消息监听器注册完成后再加载 iframe,避免错过 pageReady。
          // 一次性 Key 生成后应立即使用。
          editorIframe.src = editorUrl.href;
        } catch (error) {
          console.error("编辑器加载失败:", error);
        }
      }

      loadEditor();
    </script>
  </body>
</html>

4、定制化功能

4.1、生产拦截

仅当编辑器初始化配置中的 charge 设置为 true 时,生产拦截功能才会生效。

生产拦截功能允许接入方控制用户的付费 API 调用请求。编辑器将根据接入方返回的结果,决定是否继续执行调用,从而实现调用前的二次确认。

使用场景:用户每次在编辑器中调用付费 API 时,接入方可验证用户的可用余额或权限是否满足要求

实现步骤:

  1. 监听编辑器页面发送的消息,并实现接入方的业务判断逻辑。

let receiveBiz = "";

window.addEventListener("message", (ev: MessageEvent) => {
  const { data, action, biz } = ev.data ?? {};
  if (action === "generate") {
    // 保存业务类型,回复编辑器时需要原样传回
    receiveBiz = biz;

    // 本次用户准备生成的图片数量
    const { imageNum } = data ?? {};

    console.log("生产请求:", {
      biz,
      imageNum,
      data,
    });

    // TODO:在这里判断用户余额、权限等
  }
});
  1. 返回消息,控制是否继续生产流程。当返回消息中的 successtrue 时,继续执行调用;为 false 时,中断调用并向用户显示提示。

// true:继续生产并产生费用
// false:中断生产流程

const success = true;

iframeEle.contentWindow?.postMessage(
  {
    biz: receiveBiz,
    action: "respond",
    success,
  },
  editorOrigin,
);

4.2、二次编辑

仅当编辑器初始化配置中的 reEdit 设置为 true 时,二次编辑功能才会生效。

二次编辑功能支持在编辑器中加载历史结果数据并继续编辑。启用该功能时,接入方需通过初始化配置中的 reEditData 传入历史结果数据。该数据可使用 API 返回结果中的 genFiles 字段(详见下方第 6 节),也可使用编辑器返回的结果数据(详见下方 5.2 和 5.3)。

reEditDatastring 类型,反序列化后为符合 EditorData 结构的对象数组。目前仅支持单张图片的二次编辑,因此数组中只能包含一个元素。详见下方 5.3。

iframeEle.contentWindow?.postMessage(
  {
    action: "init",
    data: {
      tool: "translate",
      reEdit: true,
      reEditData: JSON.stringify(
        [
          {
            editInfo: {
              goodsRects: {
                top: 0,
                left: 0,
                width: 802,
                height: 802,
                degree: 0,
              },
              languages: ["en"],
              textAreas: [
                {
                  verticalLayout: "top",
                  horizontalLayout: "center",
                  texts: [
                    {
                      valid: true,
                      verticalLayout: "top",
                      horizontalLayout: "center",
                      color: "#f6eec1",
                      imageRect: {
                        top: 27,
                        left: 68,
                        width: 692,
                        height: 100,
                        degree: 0,
                      },
                      fontsize: 50,
                      language: "en",
                      textRect: {
                        top: 27,
                        left: 68,
                        width: 692,
                        height: 100,
                        degree: 0,
                      },
                      value: "Hello Kitty Sleep Companion Night Light",
                      lineCount: 1,
                      stroke: "#000000",
                      strokeWidth: 1,
                      paintFirst: "stroke",
                      shadow: {
                        offsetX: 0,
                        offsetY: 0,
                        blur: 1,
                        color: "#000000",
                      },
                    },
                  ],
                  color: "#f6eec1",
                  fontsize: 50,
                  lineCount: 1,
                  content: "凯蒂猫伴睡小夜灯",
                },
                {
                  verticalLayout: "top",
                  horizontalLayout: "center",
                  texts: [
                    {
                      valid: true,
                      verticalLayout: "top",
                      horizontalLayout: "center",
                      color: "#f6edc2",
                      imageRect: {
                        top: 154,
                        left: 262,
                        width: 290,
                        height: 26,
                        degree: 0,
                      },
                      fontsize: 26,
                      language: "en",
                      textRect: {
                        top: 154,
                        left: 262,
                        width: 290,
                        height: 26,
                        degree: 0,
                      },
                      value: "Tap, squeeze, and play",
                      lineCount: 1,
                    },
                  ],
                  color: "#f6edc2",
                  fontsize: 26,
                  lineCount: 1,
                  content: "任拍任捏任打",
                },
                {
                  verticalLayout: "top",
                  horizontalLayout: "center",
                  texts: [
                    {
                      valid: true,
                      verticalLayout: "top",
                      horizontalLayout: "center",
                      color: "#f9eac5",
                      imageRect: {
                        top: 328,
                        left: 206,
                        width: 112,
                        height: 12,
                        degree: 12,
                      },
                      fontsize: 11,
                      language: "en",
                      textRect: {
                        top: 328,
                        left: 206,
                        width: 112,
                        height: 12,
                        degree: 12,
                      },
                      value: "Gently tap to light up",
                      lineCount: 1,
                    },
                  ],
                  color: "#f9eac5",
                  fontsize: 11,
                  lineCount: 1,
                  content: "轻拍点亮",
                },
                {
                  verticalLayout: "top",
                  horizontalLayout: "center",
                  texts: [
                    {
                      valid: true,
                      verticalLayout: "top",
                      horizontalLayout: "center",
                      color: "#f7e8c2",
                      imageRect: {
                        top: 355,
                        left: 206,
                        width: 150,
                        height: 12,
                        degree: 13,
                      },
                      fontsize: 11,
                      language: "en",
                      textRect: {
                        top: 355,
                        left: 206,
                        width: 150,
                        height: 12,
                        degree: 13,
                      },
                      value: "Soft light for eye protection!",
                      lineCount: 1,
                      stroke: "#000000",
                      strokeWidth: 41,
                      paintFirst: "stroke",
                    },
                  ],
                  color: "#f7e8c2",
                  fontsize: 11,
                  lineCount: 1,
                  content: "柔光更护眼!",
                },
              ],
              resultImageIds: [
                "xxx",
              ],
              repairedUrl: "xxx",
              font: ["AlibabaSans-Regular"],
            },
            srcImage: "xxx",
            resultList: [
              {
                language: "en",
                fileUrl: "xxx",
              },
            ],
          },
        ]
      ),
    },
  },
  editorOrigin,
);

4.3、接入方自行调用 API

仅当编辑器初始化配置中的 enableToolExecution 设置为 false 时,接入方自行调用 API 功能才会生效。

该功能允许接入方自行调用当前能力对应的 API,并将调用结果回传给编辑器。用户在编辑器中触发能力后,编辑器不会直接调用 API,而是通过 generate 消息将调用信息发送给客户前端。客户前端完成 API 调用后,需通过 applyToolResult 消息将结果回传给编辑器,由编辑器加载并展示结果。

实现步骤:

  1. 监听编辑器发送的 generate 消息,并根据消息中的 bizdata 调用对应的 API。

  2. API 调用成功后,通过 applyToolResult 消息将结果数据回传给编辑器。biz 需与 generate.biz 保持一致,data 的数据结构需与 init 消息中的 reEditData 一致。

  3. API 调用失败时,可将 data 设置为空字符串 "" 并回传给编辑器。接入方需同时通过 Toast 等方式自行向用户展示错误提示。

window.addEventListener("message", async (event) => {
  const { action, biz, data } = event.data ?? {};

  if (action === "generate") {
    try {
      // 由接入方实现对应能力的 API 调用
      // invokeToolApi 为示例方法,需由接入方根据实际业务实现。
      const apiResult = await invokeToolApi({ biz, data });
  
      // 图片翻译 API 可直接使用 genFiles 字段
      const resultData = apiResult.genFiles;
  
      iframeEle.contentWindow.postMessage(
        {
          biz,
          action: "applyToolResult",
          data: resultData,
        },
        editorOrigin,
      );
    } catch (error) {
      console.error("能力 API 调用失败:", error);
  
      // TODO:由接入方通过 Toast 等方式向用户展示错误提示。
  
      iframeEle.contentWindow.postMessage(
        {
          biz,
          action: "applyToolResult",
          data: "",
        },
        editorOrigin,
      );
    }
  }
});

5、结果获取

5.1、生成任务结果获取

用户发起生成请求且调用成功后,接入方可通过监听 actiontaskSuccess 的消息,获取当次任务的结果数据。

注意:此处的任务结果是算法生成的结果,不是用户修改后的最终结果,因此不包含用户在编辑器中的编辑操作。
interface ResultItem {
  id: string;
  url: string;
}

type Result = ResultItem[];

window.addEventListener("message", (ev: MessageEvent) => {
  const { data, action, biz } = ev.data ?? {};

  if (action === "taskSuccess") {
    const result: Result = data;

    console.log("业务:", biz, "生产任务完成,结果:", result);
  }
});

5.2、最终结果获取

方式1:事件监听

用户执行以下操作时,编辑器会向接入方返回结果数据:

  1. 点击“保存”按钮:返回当前画布的结果图片和协议。

  2. 点击“下载”按钮:将结果图片下载到本地,同时返回结果图片和协议。

window.addEventListener("message", (ev: MessageEvent) => {
  const { data, action } = ev.data ?? {};

  if (action === "submitAll") {
    // TODO:在这里处理最终任务结果
    console.log("收到任务结果:", data);
  }
});

方式2:主动获取

接入方可发送 actionrequestResult 的消息,主动获取编辑器中的结果数据。

iframe.contentWindow?.postMessage(
  {
    action: "requestResult",
  },
  editorOrigin,
);

编辑器收到上述消息后,会按以下方式返回完整的结果数据。

window.addEventListener("message", (ev: MessageEvent) => {
  const { data, action } = ev.data ?? {};
 

  if (action === "submitAll") {
    // TODO:在这里处理最终任务结果
    console.log("收到任务结果:", data);
  }
});

5.3、返回的数据格式

返回数据包含用户当前画布的结果图片 url 和结果数据 editData

结果数据需由接入方自行保存。开启二次编辑功能时,将该数据传入编辑器,即可加载并继续编辑。

注意:结果数据在存储和传输过程中不得进行任何修改,否则可能导致编辑器无法正确读取或加载历史数据。结果图片 URL 的默认有效期为 7 天,请接入方及时转存,以免因链接过期而无法访问。
interface ResultType {
  /**
   * 本次是否由用户点击「下载图片」触发。
   * 下载与保存的报文体完全相同,接入方靠它判断该不该重复计数 / 提示。
   */
  isDownload: boolean;

  /** 结果 ID,用于跟踪算法结果以及用户调整后的结果 */
  id: string;

  /** 原图地址(单张,可直接访问的签名 URL) */
  originalUrl: string;

  /** 结果图地址(单张,可直接访问的签名 URL) */
  url: string;

  /**
   * 编辑器完整数据,类型为 JSON string
   * 与初始化参数 reEditData 一致,反序列化后为符合 EditorData 结构的对象数组。
   */
  editData: string;
}

interface EditorData {
  /** 编辑器完整数据:文字区、用户新增图层、修复底图、字体等 */
  editInfo: EditInfo;
  /** 原图地址 */
  srcImage: string;
  /** 结果图列表。按语种分项(算法结构),当前单语种翻译故恒为单元素 */
  resultList: ResultImageItem[];
}

interface EditInfo {
  /** 商品区域 */
  goodsRects?: Rect;
  /** 目标语种列表 */
  languages: string[];
  /** 文字区列表(算法识别出的「原文 → 译文」区域) */
  textAreas: TextArea[];
  /** 结果图 ID 列表 */
  resultImageIds: string[];
  /** 去字后的修复底图地址 */
  repairedUrl: string;
  /** 字体列表 */
  font: string[];
  /** 图翻标准版特有:上传的原图地址(Pro 版放在 srcImage) */
  pictUrl?: string;
  /**
   * 用户在编辑器内新增的贴纸 / 素材 / 文本等图层。
   * textAreas 只建模算法识别出的文字区,表达不了这些图层,故单独存放。
   * 算法原始返回不带该字段,用户未新增图层时也不带。
   */
  editorLayers?: EditorLayer[];
}

interface Rect {
  top: number;
  left: number;
  width: number;
  height: number;
  /** 旋转角度 */
  degree: number;
}

interface TextArea {
  /** 垂直对齐:top / center / bottom */
  verticalLayout: string;
  /** 水平对齐:left / center / right */
  horizontalLayout: string;
  /** 译文列表(按语种) */
  texts: TextItem[];
  color: string;
  fontsize: number;
  lineCount: number;
  /** 原文内容 */
  content: string;
}

interface TextItem {
  valid: boolean;
  verticalLayout: string;
  horizontalLayout: string;
  color: string;
  /** 在图片上的位置 */
  imageRect: Rect;
  fontsize: number;
  /** 语种 */
  language: string;
  /** 文字框位置 */
  textRect: Rect;
  /** 译文内容 */
  value: string;
  lineCount: number;

  /** 描边颜色 */
  stroke?: string;
  /** 描边粗细 */
  strokeWidth?: number;
  /** 描边绘制顺序:stroke / fill */
  paintFirst?: string;
  /** 阴影 */
  shadow?: Shadow;
  /** 字间距 */
  charSpacing?: number;
  /** 文字底色 */
  backgroundColor?: string;
  /** 行高 */
  lineHeight?: number;
  /** 文字装饰:underline / line-through */
  textDecoration?: string;
}

interface Shadow {
  color: string;
  offsetX: number;
  offsetY: number;
  /** 模糊度 */
  blur: number;
}

interface ResultImageItem {
  /** 语种 */
  language: string;
  /** 结果图地址 */
  fileUrl: string;
}

6、API 返回的图层信息

图片翻译标准版与 Pro 版 API 返回的图层结构基本一致。两者的原图地址均存储在 srcImage 字段中;区别在于,标准版还会通过特有字段 editInfo.pictUrl 记录上传的原图地址。

Data.GenFiles 在原始 API 响应中为 String,反序列化后为 Array[Object]。下表从第 2 项开始的参数名称,均表示 Data.GenFiles 反序列化后的逻辑结构。

注意:[*] 表示数组中的任意元素。例如,GenFiles[*] 表示任意一项图层数据,TextAreas[*] 表示任意一个文本框,Texts[*] 表示任意一项翻译后文本,ResultList[*] 表示任意一项翻译结果。

序号

参数名称

数据类型

参数描述及示例值

1

Data.GenFiles

String

编辑器协议信息,仅当 UseImageEditor = true 时返回;反序列化后为 Array[Object]

2

Data.GenFiles[*].SrcImage

String

原图 URL

3

Data.GenFiles[*].EditInfo

Object

编辑器详细信息

4

Data.GenFiles[*].EditInfo.PictUrl

String

上传的原图 URL,仅图片翻译标准版返回

5

Data.GenFiles[*].EditInfo.ResultImageIds

Array[String]

翻译后图片的全局 ID 集合

6

Data.GenFiles[*].EditInfo.RepairedUrl

String

所有文字涂抹后的图片 URL

7

Data.GenFiles[*].EditInfo.Languages

Array[String]

翻译语种列表

8

Data.GenFiles[*].EditInfo.TextAreas

Array[Object]

文本框列表

9

Data.GenFiles[*].EditInfo.TextAreas[*].Fontsize

Number

字体大小

10

Data.GenFiles[*].EditInfo.TextAreas[*].Content

String

翻译前的文本

11

Data.GenFiles[*].EditInfo.TextAreas[*].Color

String

文字颜色,例如 "#ffffff"

12

Data.GenFiles[*].EditInfo.TextAreas[*].VerticalLayout

String

垂直对齐方式:"center""top""down"

13

Data.GenFiles[*].EditInfo.TextAreas[*].HorizontalLayout

String

水平对齐方式:"center""left""right"

14

Data.GenFiles[*].EditInfo.TextAreas[*].LineCount

Number

文本框行数

15

Data.GenFiles[*].EditInfo.TextAreas[*].Texts

Array[Object]

翻译后文本列表

16

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].Fontsize

Number

字体大小

17

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].Language

String

语言

18

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].Valid

Boolean

TextItem 是否有效

19

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].ImageRect

Object

图片修复区域

20

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].TextRect

Object

文本框区域

21

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].Color

String

文字颜色

22

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].Value

String

翻译后的文本

23

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].VerticalLayout

String

垂直对齐方式

24

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].HorizontalLayout

String

水平对齐方式

25

Data.GenFiles[*].EditInfo.TextAreas[*].Texts[*].LineCount

Number

文本框行数

26

Data.GenFiles[*].EditInfo.GoodsRects

Object

商品框区域

27

Data.GenFiles[*].EditInfo.Font

Array[String]

字体类型列表

28

Data.GenFiles[*].ResultList

Array[Object]

翻译结果列表

29

Data.GenFiles[*].ResultList[*].Language

String

翻译语种

30

Data.GenFiles[*].ResultList[*].FileUrl

String

翻译后的图片 URL

7、翻译支持语向

7.1、语言代码

语言代码采用 ISO 639-1 标准的两位字母表示法。对于特定语言的区域变体,遵循 RFC 5646 格式,即在语言代码后加短横线,并接上 ISO 3166 的两位国家/地区代码。例如,繁体中文的语言代码是 zh-tw。

支持桥接翻译,例如zh-en,en- ar,则可实现zh-en-ar的桥接翻译

序号

源语言

目标语言

语言代码

中文名称

语言代码

中文名称

1

zh

zh-tw

中文(简体)

中文(繁体)

en

英语

2

ja

日语

3

ko

韩语

4

kk

哈萨克语

5

ms

马来语

6

th

泰语

7

ar

阿拉伯语

en

英语

8

tr

土耳其语

9

az

阿塞拜疆语

en

英语

10

bn

孟加拉语

en

英语

11

cs

捷克语

en

英语

12

de

德语

en

英语

13

el

希腊语

en

英语

14

en

英语

ar

阿拉伯语

15

az

阿塞拜疆语

16

bn

孟加拉语

17

bs

波斯尼亚语

18

cs

捷克语

19

da

丹麦语

20

de

德语

21

el

希腊语

22

es

西班牙语

23

et

爱沙尼亚语

24

fi

芬兰语

25

fr

法语

26

he

希伯来语

27

hi

印地语

28

hu

匈牙利语

29

id

印度尼西亚语

30

it

意大利语

31

ja

日语

32

ko

韩语

33

lt

立陶宛语

34

lv

拉脱维亚语

35

ms

马来语

36

my

缅甸语

37

ne

尼泊尔语

38

nl

荷兰语

39

no

挪威语

40

pl

波兰语

41

pt

葡萄牙语(巴西)

42

pt-pt

葡萄牙语(葡萄牙)

43

ro

罗马尼亚语

44

ro_ur

罗马尼亚语(乌尔都)

45

ru

俄语

46

si

僧伽罗语

47

sk

斯洛伐克语

48

sl

斯洛文尼亚语

49

sr

塞尔维亚语

50

sv

瑞典语

51

th

泰语

52

tl

菲律宾语

53

tr

土耳其语

54

uk

乌克兰语

55

ur

乌尔都语

56

vi

越南语

57

zh

中文(简体)

58

es

西班牙语

bg

保加利亚语

59

cs

捷克语

60

da

丹麦语

61

de

德语

62

el

希腊语

63

en

英语

64

et

爱沙尼亚语

65

fi

芬兰语

66

fr

法语

67

hr

克罗地亚语

68

hu

匈牙利语

69

it

意大利语

70

lt

立陶宛语

71

lv

拉脱维亚语

72

nl

荷兰语

73

no

挪威语

74

pl

波兰语

75

pt

葡萄牙语(巴西)

76

ro

罗马尼亚语

77

ru

俄语

78

sk

斯洛伐克语

79

sv

瑞典语

80

pt-pt

葡萄牙语(葡萄牙)

81

fi

芬兰语

en

英语

82

fr

法语

en

英语

83

he

希伯来语

en

英语

84

hi

印地语

en

英语

85

hu

匈牙利语

en

英语

86

id

印度尼西亚语

en

英语

87

it

意大利语

en

英语

88

ja

日语

en

英语

89

ko

韩语

en

英语

90

ms

马来语

en

英语

91

my

缅甸语

en

英语

92

ne

尼泊尔语

en

英语

93

nl

荷兰语

en

英语

94

pl

波兰语

en

英语

95

pt

葡萄牙语(巴西)

en

英语

96

ro

罗马尼亚语

en

英语

97

tr

土耳其语

98

ru

俄语

en

英语

99

si

僧伽罗语

en

英语

100

sv

瑞典语

en

英语

101

th

泰语

en

英语

102

tl

菲律宾语

en

英语

103

tr

土耳其语

ar

阿拉伯语

104

cs

捷克语

105

de

德语

106

el

希腊语

107

en

英语

108

hu

匈牙利语

109

ro

罗马尼亚语

110

sk

斯洛伐克语

111

uk

乌克兰语

en

英语

112

ur

乌尔都语

en

英语

113

vi

越南语

en

英语

114

bg

保加利亚语

en

英语

115

bs

波斯尼亚语

en

英语

116

da

丹麦语

en

英语

117

et

爱沙尼亚语

en

英语

118

hr

克罗地亚语

en

英语

119

lt

立陶宛语

en

英语

120

lv

拉脱维亚语

en

英语

121

no

挪威语

en

英语

122

pt-pt

葡萄牙语(葡萄牙)

en

英语

123

ro_ur

罗马尼亚语(乌尔都)

en

英语

124

sk

斯洛伐克语

en

英语

125

sl

斯洛文尼亚语

en

英语

126

sr

塞尔维亚语

en

英语

7.2、语种识别支持语向

注:仅在使用图片翻译pro版时,原始语向可以自动识别,可识别出的语向如下:

序号

语言名称(英文)

语言代码

语言名称(中文)

1

Arabic

ar

阿拉伯语

2

Bengali

bn

孟加拉语

3

German

de

德语

4

English

en

英语

5

Spanish

es

西班牙语

6

French

fr

法语

7

Hebrew

he

希伯来语

8

Indonesian

id

印度尼西亚语

9

Italian

it

意大利语

10

Japanese

ja

日语

11

Korean

ko

韩语

12

Malay

ms

马来语

13

Dutch

nl

荷兰语

14

Polish

pl

波兰语

15

Portuguese (Brazil)

pt

葡萄牙语(巴西)

16

Russian

ru

俄语

17

Thai

th

泰语

18

Turkish

tr

土耳其语

19

Ukrainian

uk

乌克兰语

20

Urdu

ur

乌尔都语

21

Vietnamese

vi

越南语

22

Chinese (Simplified)

zh

中文(简体)

23

Chinese (Traditional)

zh-tw

中文(繁体)

24

Hindi

hi

印地语

8、计费方式

计费项

计费单位

刊例价(人民币)

文本翻译

每百万字符

¥50

图片翻译(标准版)

每张

¥0.015

图片翻译(Pro 版)

每张

¥0.06