Description
This page translation plugin, powered by a large translation model, adds one-click multilingual transformation to your website.
How it works

Integrate the JSSDK
Step 1: Add the script
<html>
<head></head>
<body>
<!-- Insert the translation script before the closing </body> tag -->
<script src="https://g.alicdn.com/translate-js-sdk/translate-js-sdk-stable/2.0.6/light.js"></script>
</body>
</html>
Step 2: Configure the JSSDK
interface ITokenResponseData {
code: 200;
data: {
url: string,
host: string,
method: "POST",
headers: {
"host": string,
"x-acs-action": "BatchTranslateForHtml",
"x-acs-version": string,
"x-acs-date": string;
"x-acs-signature-nonce": string;
"content-type": "application/json",
"x-acs-content-sha256": string;
Authorization: string;
};
body: string;
};
}
interface ITokenRequestData {
sourceLanguage: string;
targetLanguage: string;
streaming: false,
text: {[index: number]: string}
scene: 'mt-turbo',
fallbackTimeoutMs: number;
}
interface ISetupConfig {
getToken: (data: ITokenRequestData) => Promise<ITokenResponseData>;
}
// Initialize only once.
__AliTranslate.setup({
getToken: async (data) => {
const res = await fetch('YOUR_GET_TOKEN_URL', { method: 'post', body: JSON.stringify(data) });
return (await res.json()).data;
}
});
Step 3: Call page translation
Display translation only
interface IPageTranslate {
srcLanguage?: string; // The source language. The default value is 'auto'.
tgtLanguage?: string; // The target language. The default value is 'en'.
lazyload?: boolean; // Specifies whether to translate only the visible area. The default value is false.
lazyOffset?: number; // The offset for extending the visible area.
target?: HTMLElement; // The target area to translate. The default value is body.
except?: string; // The areas to exclude from translation. Default value is an empty string.
}
const instance = __AliTranslate.pageTranslate({
lazyload: true,
lazyOffset: 500
});
Side-by-side translation
interface IParagraphTranslate {
srcLanguage?: string; // The source language. The default value is 'auto'.
tgtLanguage?: string; // The target language. The default value is 'en'.
target?: HTMLElement; // The target area to translate. The default value is body.
dynamic?: boolean; // Specifies whether to enable dynamic translation. The default value is false.
}
const instance = __AliTranslate.paragraphTranslate({
srcLanguage: 'zh',
tgtLanguage: 'en'
});
Step 4: Cancel translation
// Cancels the translation and restores the original page content.
instance.destroy();
PageTranslate parameters
|
Parameter |
Description |
Type |
Default |
|
|
The source language. |
String |
|
|
|
The target language. |
String |
|
|
|
Specifies whether to translate only the visible area. |
Boolean |
|
|
|
The pixel offset for extending the |
Number |
|
|
|
The target area to translate. |
HTMLElement | HTMLElement[] |
|
|
|
A CSS selector for areas to exclude from translation. |
Selector(String) |
'' (empty string) |
ParagraphTranslate parameters
|
Parameter |
Description |
Type |
Default |
|
|
The source language. |
String |
|
|
|
The target language. |
String |
|
|
|
The target area to translate. |
HTMLElement | HTMLElement[] |
|
|
|
If true, the page is automatically re-translated when its content changes. If false, the page is translated only once. |
Boolean |
|
|
|
Specifies whether to translate only the visible area. |
Boolean |
|
|
|
The pixel offset for extending the |
Number |
|
Implement a token service
Sign requests using the V3 request body and signature mechanism of Alibaba Cloud.
// Generate a signature by using the calculateSignature method.
import * as crypto from 'crypto';
export interface SignatureRequest {
httpMethod: string;
canonicalUri: string;
host: string;
xAcsAction: string;
xAcsVersion: string;
headers: Record<string, string>;
body: any;
queryParam: Record<string, any>;
}
export interface BatchTranslateRequest {
scene: string;
sourceLanguage: string;
streaming: boolean;
targetLanguage: string;
text: { [key: string]: string };
}
export class Request implements SignatureRequest {
httpMethod: string;
canonicalUri: string;
host: string;
xAcsAction: string;
xAcsVersion: string;
headers: Record<string, string>;
body: any;
queryParam: Record<string, any>;
constructor(httpMethod: string, canonicalUri: string, host: string, xAcsAction: string, xAcsVersion: string) {
this.httpMethod = httpMethod;
this.canonicalUri = canonicalUri || '/';
this.host = host;
this.xAcsAction = xAcsAction;
this.xAcsVersion = xAcsVersion;
this.headers = {};
this.body = null;
this.queryParam = {};
this.initHeader();
}
private initHeader() {
const date = new Date();
this.headers = {
'host': this.host,
'x-acs-action': this.xAcsAction,
'x-acs-version': this.xAcsVersion,
'x-acs-date': date.toISOString().replace(/\..+/, 'Z'),
'x-acs-signature-nonce': crypto.randomBytes(16).toString('hex')
}
}
}
const ALGORITHM = 'ACS3-HMAC-SHA256';
const accessKeyId = process.env.ACCESS_KEY_ID; // Your Access Key ID.
const accessKeySecret = process.env.ACCESS_KEY_SECRET; // Your Access Key Secret.
const workspaceId = process.env.WORKSPACE_ID; // Your workspace ID from Model Studio.
const encoder = new TextEncoder();
const httpMethod = 'POST';
const canonicalUri = '/anytrans/translate/batchForHtml';
const xAcsAction = 'BatchTranslateForHtml';
const xAcsVersion = '2025-07-07';
const host = 'anytrans.cn-beijing.aliyuncs.com';
export interface SignedRequest {
url: string;
method: string;
host: string;
headers: Record<string, string>;
body?: any; // Can be a Uint8Array or a Base64 string.
}
export function getAuthorization(signRequest: SignatureRequest): SignedRequest {
try {
const newQueryParam: Record<string, any> = {};
processObject(newQueryParam, "", signRequest.queryParam);
signRequest.queryParam = newQueryParam;
// Step 1: Build the canonical request string.
const canonicalQueryString = Object.entries(signRequest.queryParam)
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, value]) => `${percentCode(key)}=${percentCode(value)}`)
.join('&');
// The request payload. For requests with an empty body, such as GET requests, the RequestPayload is an empty string.
const requestPayload = signRequest.body || encoder.encode('');
const hashedRequestPayload = sha256Hex(requestPayload);
signRequest.headers['x-acs-content-sha256'] = hashedRequestPayload;
// Convert all keys to lowercase.
signRequest.headers = Object.fromEntries(
Object.entries(signRequest.headers).map(([key, value]) => [key.toLowerCase(), value])
);
const sortedKeys = Object.keys(signRequest.headers)
.filter(key => key.startsWith('x-acs-') || key === 'host' || key === 'content-type')
.sort();
// A list of signed headers. The header names are in lowercase, sorted alphabetically, and separated by semicolons (;).
const signedHeaders = sortedKeys.join(";")
// Construct the canonical headers. The canonical headers are concatenated in ascending order of their lowercase header names.
const canonicalHeaders = sortedKeys.map(key => `${key}:${signRequest.headers[key]}`).join('\n') + '\n';
const canonicalRequest = [
signRequest.httpMethod,
signRequest.canonicalUri,
canonicalQueryString,
canonicalHeaders,
signedHeaders,
hashedRequestPayload
].join('\n');
console.log('canonicalRequest=========>\n', canonicalRequest);
// Step 2: Build the string to sign.
const hashedCanonicalRequest = sha256Hex(encoder.encode(canonicalRequest));
const stringToSign = `${ALGORITHM}\n${hashedCanonicalRequest}`;
console.log('stringToSign=========>', stringToSign);
// Step 3: Calculate the signature.
const signature = hmac256(accessKeySecret!, stringToSign);
console.log('signature=========>', signature);
// Step 4: Build the Authorization header.
const authorization = `${ALGORITHM} Credential=${accessKeyId},SignedHeaders=${signedHeaders},Signature=${signature}`;
console.log('authorization=========>', authorization);
signRequest.headers['Authorization'] = authorization;
// Build the complete URL.
let url = `https://${signRequest.host}${signRequest.canonicalUri}`;
if (signRequest.queryParam && Object.keys(signRequest.queryParam).length > 0) {
const query = new URLSearchParams(signRequest.queryParam);
url += '?' + query.toString();
}
return {
url,
host: signRequest.host,
method: signRequest.httpMethod.toUpperCase(),
headers: signRequest.headers,
body: signRequest.body
};
} catch (error) {
console.error('Failed to get authorization');
console.error(error);
throw error;
}
}
function percentCode(str: string): string {
return encodeURIComponent(str)
.replace(/\+/g, '%20')
.replace(/\*/g, '%2A')
.replace(/~/g, '%7E');
}
function hmac256(key: string, data: string): string {
const hmac = crypto.createHmac('sha256', key);
hmac.update(data, 'utf8');
return hmac.digest('hex').toLowerCase();
}
function sha256Hex(bytes: any): string {
const hash = crypto.createHash('sha256');
const digest = hash.update(bytes).digest('hex');
return digest.toLowerCase();
}
function processObject(map: Record<string, any>, key: string, value: any): void {
// If the value is null, no further processing is required.
if (value === null) {
return;
}
if (key === null) {
key = "";
}
// If the value is an array, iterate over each element and process it recursively.
if (Array.isArray(value)) {
value.forEach((item, index) => {
processObject(map, `${key}.${index + 1}`, item);
});
} else if (typeof value === 'object' && value !== null) {
// If the value is an object, iterate over each key-value pair and process it recursively.
Object.entries(value).forEach(([subKey, subValue]) => {
processObject(map, `${key}.${subKey}`, subValue);
});
} else {
// For keys that start with a period (.), remove the leading period to maintain key continuity.
if (key.startsWith('.')) {
key = key.slice(1);
}
map[key] = String(value);
}
}
export function formDataToString(formData: Record<string, any>): string {
const tmp: Record<string, any> = {};
processObject(tmp, "", formData);
let queryString = '';
for (let [key, value] of Object.entries(tmp)) {
if (queryString !== '') {
queryString += '&';
}
queryString += encodeURIComponent(key) + '=' + encodeURIComponent(value);
}
return queryString;
}
// Method for calculating signatures with fixed variables.
export interface FixedSignatureResult {
httpMethod: string;
canonicalUri: string;
host: string;
xAcsAction: string;
xAcsVersion: string;
signature: string;
date: string;
nonce: string;
workspaceId: string;
authorization: string;
}
export function calculateSignature(req: BatchTranslateRequest): SignedRequest {
// Create a request instance.
const signRequest = new Request(httpMethod, canonicalUri, host, xAcsAction, xAcsVersion);
// Set query parameters.
signRequest.queryParam = {
RegionId: 'cn-beijing',
};
// Create a Uint8Array for the body.
const bodyUint8Array = encoder.encode(JSON.stringify({
...req,
workspaceId,
}));
// The request body used for signature calculation.
signRequest.body = bodyUint8Array;
signRequest.headers['content-type'] = 'application/json';
// Get the signature.
const result = getAuthorization(signRequest);
// Convert the body to a Base64 string for transmission.
const bodyBase64 = Buffer.from(bodyUint8Array).toString('base64');
return {
...result,
body: bodyBase64 // Return a Base64 string instead of a Uint8Array.
};
} // Generate a signature by using the calculateSignature method.
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
/**
* Signature request interface.
*/
interface SignatureRequest {
String getHttpMethod();
String getCanonicalUri();
String getHost();
String getXAcsAction();
String getXAcsVersion();
Map<String, String> getHeaders();
byte[] getBody();
Map<String, Object> getQueryParam();
void setHeaders(Map<String, String> headers);
void setBody(byte[] body);
void setQueryParam(Map<String, Object> queryParam);
}
/**
* Data class for batch translation requests.
*/
class BatchTranslateRequest {
private String scene;
private String sourceLanguage;
private boolean streaming;
private String targetLanguage;
private Map<String, String> text;
// Constructor
public BatchTranslateRequest() {}
public BatchTranslateRequest(String scene,
String sourceLanguage, boolean streaming,
String targetLanguage, Map<String, String> text) {
this.scene = scene;
this.sourceLanguage = sourceLanguage;
this.streaming = streaming;
this.targetLanguage = targetLanguage;
this.text = text;
}
// Getters and Setters
public String getScene() { return scene; }
public void setScene(String scene) { this.scene = scene; }
public String getSourceLanguage() { return sourceLanguage; }
public void setSourceLanguage(String sourceLanguage) { this.sourceLanguage = sourceLanguage; }
public boolean isStreaming() { return streaming; }
public void setStreaming(boolean streaming) { this.streaming = streaming; }
public String getTargetLanguage() { return targetLanguage; }
public void setTargetLanguage(String targetLanguage) { this.targetLanguage = targetLanguage; }
public Map<String, String> getText() { return text; }
public void setText(Map<String, String> text) { this.text = text; }
}
/**
* Request implementation class.
*/
class Request implements SignatureRequest {
private String httpMethod;
private String canonicalUri;
private String host;
private String xAcsAction;
private String xAcsVersion;
private Map<String, String> headers;
private byte[] body;
private Map<String, Object> queryParam;
public Request(String httpMethod, String canonicalUri, String host,
String xAcsAction, String xAcsVersion) {
this.httpMethod = httpMethod;
this.canonicalUri = canonicalUri != null ? canonicalUri : "/";
this.host = host;
this.xAcsAction = xAcsAction;
this.xAcsVersion = xAcsVersion;
this.headers = new HashMap<>();
this.body = null;
this.queryParam = new HashMap<>();
initHeader();
}
private void initHeader() {
Instant now = Instant.now();
String date = DateTimeFormatter.ISO_INSTANT.format(now);
String nonce = generateRandomHex(16);
this.headers.put("host", this.host);
this.headers.put("x-acs-action", this.xAcsAction);
this.headers.put("x-acs-version", this.xAcsVersion);
this.headers.put("x-acs-date", date);
this.headers.put("x-acs-signature-nonce", nonce);
}
private String generateRandomHex(int length) {
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[length];
random.nextBytes(bytes);
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
// Getters
@Override
public String getHttpMethod() { return httpMethod; }
@Override
public String getCanonicalUri() { return canonicalUri; }
@Override
public String getHost() { return host; }
@Override
public String getXAcsAction() { return xAcsAction; }
@Override
public String getXAcsVersion() { return xAcsVersion; }
@Override
public Map<String, String> getHeaders() { return headers; }
@Override
public byte[] getBody() { return body; }
@Override
public Map<String, Object> getQueryParam() { return queryParam; }
// Setters
@Override
public void setHeaders(Map<String, String> headers) { this.headers = headers; }
@Override
public void setBody(byte[] body) { this.body = body; }
@Override
public void setQueryParam(Map<String, Object> queryParam) { this.queryParam = queryParam; }
}
/**
* Signed request result.
*/
class SignedRequest {
private String url;
private String method;
private String host;
private Map<String, String> headers;
private String body; // Base64 string.
public SignedRequest(String url, String method, String host,
Map<String, String> headers, String body) {
this.url = url;
this.method = method;
this.host = host;
this.headers = headers;
this.body = body;
}
// Getters
public String getUrl() { return url; }
public String getMethod() { return method; }
public String getHost() { return host; }
public Map<String, String> getHeaders() { return headers; }
public String getBody() { return body; }
}
/**
* Interface for fixed signature results.
*/
interface FixedSignatureResult {
String getHttpMethod();
String getCanonicalUri();
String getHost();
String getXAcsAction();
String getXAcsVersion();
String getSignature();
String getDate();
String getNonce();
String getWorkspaceId();
String getAuthorization();
}
/**
* Main class for signature calculation.
*/
public class NodeSignature {
private static final String ALGORITHM = "ACS3-HMAC-SHA256";
private static final String ACCESS_KEY_ID = System.getenv("ACCESS_KEY_ID"); // Your Access Key ID.
private static final String ACCESS_KEY_SECRET = System.getenv("ACCESS_KEY_SECRET"); // Your Access Key Secret.
private static final String WORKSPACE_ID = System.getenv("WORKSPACE_ID"); // Your workspace ID from Model Studio.
private static final String HTTP_METHOD = "POST";
private static final String CANONICAL_URI = "/anytrans/translate/batchForHtml";
private static final String X_ACS_ACTION = "BatchTranslateForHtml";
private static final String X_ACS_VERSION = "2025-07-07";
private static final String HOST = "anytrans.cn-beijing.aliyuncs.com";
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* Get authorization information.
*/
public static SignedRequest getAuthorization(SignatureRequest signRequest) {
try {
Map<String, Object> newQueryParam = new HashMap<>();
processObject(newQueryParam, "", signRequest.getQueryParam());
signRequest.setQueryParam(newQueryParam);
// Step 1: Build the canonical request string.
String canonicalQueryString = signRequest.getQueryParam().entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue())))
.collect(Collectors.joining("&"));
// The request payload. For requests with an empty body, such as GET requests, the RequestPayload is an empty string.
byte[] requestPayload = signRequest.getBody() != null ? signRequest.getBody() : new byte[0];
String hashedRequestPayload = sha256Hex(requestPayload);
signRequest.getHeaders().put("x-acs-content-sha256", hashedRequestPayload);
// Convert all keys to lowercase.
Map<String, String> lowerCaseHeaders = signRequest.getHeaders().entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().toLowerCase(),
Map.Entry::getValue
));
signRequest.setHeaders(lowerCaseHeaders);
List<String> sortedKeys = lowerCaseHeaders.keySet().stream()
.filter(key -> key.startsWith("x-acs-") || key.equals("host") || key.equals("content-type"))
.sorted()
.collect(Collectors.toList());
// A list of signed headers. The header names are in lowercase, sorted alphabetically, and separated by semicolons (;).
String signedHeaders = String.join(";", sortedKeys);
// Construct the canonical headers. The canonical headers are concatenated in ascending order of their lowercase header names.
String canonicalHeaders = sortedKeys.stream()
.map(key -> key + ":" + lowerCaseHeaders.get(key))
.collect(Collectors.joining("\n")) + "\n";
String canonicalRequest = String.join("\n", Arrays.asList(
signRequest.getHttpMethod(),
signRequest.getCanonicalUri(),
canonicalQueryString,
canonicalHeaders,
signedHeaders,
hashedRequestPayload
));
System.out.println("canonicalRequest=========>\n" + canonicalRequest);
// Step 2: Build the string to sign.
String hashedCanonicalRequest = sha256Hex(canonicalRequest.getBytes(StandardCharsets.UTF_8));
String stringToSign = ALGORITHM + "\n" + hashedCanonicalRequest;
System.out.println("stringToSign=========>" + stringToSign);
// Step 3: Calculate the signature.
String signature = hmac256(ACCESS_KEY_SECRET, stringToSign);
System.out.println("signature=========>" + signature);
// Step 4: Build the Authorization header.
String authorization = String.format("%s Credential=%s,SignedHeaders=%s,Signature=%s",
ALGORITHM, ACCESS_KEY_ID, signedHeaders, signature);
System.out.println("authorization=========>" + authorization);
lowerCaseHeaders.put("authorization", authorization);
// Build the complete URL.
String url = "https://" + signRequest.getHost() + signRequest.getCanonicalUri();
if (signRequest.getQueryParam() != null && !signRequest.getQueryParam().isEmpty()) {
String query = signRequest.getQueryParam().entrySet().stream()
.map(entry -> {
try {
return URLEncoder.encode(entry.getKey(), "UTF-8") + "=" +
URLEncoder.encode(String.valueOf(entry.getValue()), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.joining("&"));
url += "?" + query;
}
String bodyString = signRequest.getBody() != null ?
Base64.getEncoder().encodeToString(signRequest.getBody()) : null;
return new SignedRequest(url, signRequest.getHttpMethod().toUpperCase(),
signRequest.getHost(), lowerCaseHeaders, bodyString);
} catch (Exception error) {
System.err.println("Failed to get authorization");
error.printStackTrace();
throw new RuntimeException(error);
}
}
/**
* URL encoding.
*/
private static String percentCode(String str) {
try {
return URLEncoder.encode(str, "UTF-8")
.replace("+", "%20")
.replace("*", "%2A")
.replace("~", "%7E");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* HMAC-SHA256 encryption.
*/
private static String hmac256(String key, String data) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKeySpec);
byte[] hmacBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hmacBytes).toLowerCase();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* SHA-256 hash.
*/
private static String sha256Hex(byte[] bytes) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(bytes);
return bytesToHex(hashBytes).toLowerCase();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Converts a byte array to a hexadecimal string.
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
/**
* Processes an object to flatten nested objects.
*/
private static void processObject(Map<String, Object> map, String key, Object value) {
// If the value is null, no further processing is required.
if (value == null) {
return;
}
if (key == null) {
key = "";
}
// If the value is a list, iterate over each element and process it recursively.
if (value instanceof List) {
List<?> list = (List<?>) value;
for (int i = 0; i < list.size(); i++) {
processObject(map, key + "." + (i + 1), list.get(i));
}
} else if (value instanceof Object[] || value.getClass().isArray()) {
Object[] array = (Object[]) value;
for (int i = 0; i < array.length; i++) {
processObject(map, key + "." + (i + 1), array[i]);
}
} else if (value instanceof Map) {
// If the value is an object, iterate over each key-value pair and process it recursively.
Map<?, ?> objectMap = (Map<?, ?>) value;
for (Map.Entry<?, ?> entry : objectMap.entrySet()) {
processObject(map, key + "." + entry.getKey(), entry.getValue());
}
} else {
// For keys that start with a period (.), remove the leading period to maintain key continuity.
if (key.startsWith(".")) {
key = key.substring(1);
}
map.put(key, String.valueOf(value));
}
}
/**
* Converts form data to a string.
*/
public static String formDataToString(Map<String, Object> formData) {
Map<String, Object> tmp = new HashMap<>();
processObject(tmp, "", formData);
return tmp.entrySet().stream()
.map(entry -> {
try {
return URLEncoder.encode(entry.getKey(), "UTF-8") + "=" +
URLEncoder.encode(String.valueOf(entry.getValue()), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.joining("&"));
}
/**
* Method for calculating signatures with fixed variables.
*/
public static SignedRequest calculateSignature(BatchTranslateRequest req) {
try {
// Create a request instance.
Request signRequest = new Request(HTTP_METHOD, CANONICAL_URI, HOST, X_ACS_ACTION, X_ACS_VERSION);
// Set query parameters.
Map<String, Object> queryParam = new HashMap<>();
queryParam.put("RegionId", "cn-beijing");
signRequest.setQueryParam(queryParam);
// Create request body data.
Map<String, Object> bodyData = new HashMap<>();
bodyData.put("scene", req.getScene());
bodyData.put("sourceLanguage", req.getSourceLanguage());
bodyData.put("streaming", req.isStreaming());
bodyData.put("targetLanguage", req.getTargetLanguage());
bodyData.put("text", req.getText());
bodyData.put("workspaceId", WORKSPACE_ID);
// Create a byte array for the body.
String jsonString = objectMapper.writeValueAsString(bodyData);
byte[] bodyBytes = jsonString.getBytes(StandardCharsets.UTF_8);
// The request body used for signature calculation.
signRequest.setBody(bodyBytes);
signRequest.getHeaders().put("content-type", "application/json");
// Get the signature.
SignedRequest result = getAuthorization(signRequest);
return result;
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON serialization failed", e);
}
}
}FAQ
1. How to obtain an AccessKey pair?
Obtain an AccessKey pair from the AccessKey Management section of the Alibaba Cloud console.
2. How to find the workspace ID?
Log in to the Alibaba Cloud account that is associated with your AccessKey pair. In the Model Studio console, find the workspace details in the lower-left corner.
The Workspace ID in the pop-up window is the required workspaceId. Click the copy icon to the right of the field to copy the ID.
3. API permission error
This error indicates that Tongyi Multimodal Translation is not activated. To resolve this, use your Alibaba Cloud account to activate the service in the Tongyi Multimodal Translation console.
Change log
March 2026
|
Version |
Release date |
Description |
|
2.0.6 |
March 5, 2026 |
Added the |