网易有道Api翻译

285 阅读4分钟

序言:最近接触一个新的PLM系统,但是没有中文,查看了官网提供了汉化包,但是按照教程安装时发现没用,通过检查汉化文件发现里面都是空的,只是提供了一个模板,真坑!手动汉化是不可能的,所以决定写一个小工具进行xml配置文件的汉化。这里只讲解翻译过程。

至于为什么用网易有道的api,因为Google和Microsoft注册需要信用卡,所以不考虑了。

工具类

AuthV3Util.java

package com.youdao.aicloud.translate.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.UUID;

public class AuthV3Util {

    /**
     * 添加鉴权相关参数 -
     * appKey : 应用ID
     * salt : 随机值
     * curtime : 当前时间戳(秒)
     * signType : 签名版本
     * sign : 请求签名
     *
     * @param appKey    您的应用ID
     * @param appSecret 您的应用密钥
     * @param paramsMap 请求参数表
     */
    public static void addAuthParams(String appKey, String appSecret, Map<String, String[]> paramsMap)
            throws NoSuchAlgorithmException {
        String[] qArray = paramsMap.get("q");
        if (qArray == null) {
            qArray = paramsMap.get("img");
        }
        StringBuilder q = new StringBuilder();
        for (String item : qArray) {
            q.append(item);
        }
        String salt = UUID.randomUUID().toString();
        String curtime = String.valueOf(System.currentTimeMillis() / 1000);
        String sign = calculateSign(appKey, appSecret, q.toString(), salt, curtime);
        paramsMap.put("appKey", new String[]{appKey});
        paramsMap.put("salt", new String[]{salt});
        paramsMap.put("curtime", new String[]{curtime});
        paramsMap.put("signType", new String[]{"v3"});
        paramsMap.put("sign", new String[]{sign});
    }

    /**
     * 计算鉴权签名 -
     * 计算方式 : sign = sha256(appKey + input(q) + salt + curtime + appSecret)
     *
     * @param appKey    您的应用ID
     * @param appSecret 您的应用密钥
     * @param q         请求内容
     * @param salt      随机值
     * @param curtime   当前时间戳(秒)
     * @return 鉴权签名sign
     */
    public static String calculateSign(String appKey, String appSecret, String q, String salt, String curtime)
            throws NoSuchAlgorithmException {
        String strSrc = appKey + getInput(q) + salt + curtime + appSecret;
        return encrypt(strSrc);
    }

    private static String encrypt(String strSrc) throws NoSuchAlgorithmException {
        byte[] bt = strSrc.getBytes();
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(bt);
        byte[] bts = md.digest();
        StringBuilder des = new StringBuilder();
        for (byte b : bts) {
            String tmp = (Integer.toHexString(b & 0xFF));
            if (tmp.length() == 1) {
                des.append("0");
            }
            des.append(tmp);
        }
        return des.toString();
    }

    private static String getInput(String input) {
        if (input == null) {
            return null;
        }
        String result;
        int len = input.length();
        if (len <= 20) {
            result = input;
        } else {
            String startStr = input.substring(0, 10);
            String endStr = input.substring(len - 10, len);
            result = startStr + len + endStr;
        }
        return result;
    }
}

AuthV4Util.java

package com.youdao.aicloud.translate.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.UUID;

public class AuthV4Util {

    /**
     * 添加鉴权相关参数 -
     * appKey : 应用ID
     * salt : 随机值
     * curtime : 当前时间戳(秒)
     * signType : 签名版本
     * sign : 请求签名
     *
     * @param appKey    您的应用ID
     * @param appSecret 您的应用密钥
     * @param paramsMap 请求参数表
     */
    public static void addAuthParams(String appKey, String appSecret, Map<String, String[]> paramsMap)
            throws NoSuchAlgorithmException {
        String salt = UUID.randomUUID().toString();
        String curtime = String.valueOf(System.currentTimeMillis() / 1000);
        String sign = calculateSign(appKey, appSecret, salt, curtime);
        paramsMap.put("appKey", new String[]{appKey});
        paramsMap.put("salt", new String[]{salt});
        paramsMap.put("curtime", new String[]{curtime});
        paramsMap.put("signType", new String[]{"v4"});
        paramsMap.put("sign", new String[]{sign});
    }

    /**
     * 计算鉴权签名 -
     * 计算方式 : sign = sha256(appKey + salt + curtime + appSecret)
     *
     * @param appKey    您的应用ID
     * @param appSecret 您的应用密钥
     * @param salt      随机值
     * @param curtime   当前时间戳(秒)
     * @return 鉴权签名sign
     */
    public static String calculateSign(String appKey, String appSecret, String salt, String curtime)
            throws NoSuchAlgorithmException {
        String strSrc = appKey + salt + curtime + appSecret;
        return encrypt(strSrc);
    }

    private static String encrypt(String strSrc) throws NoSuchAlgorithmException {
        byte[] bt = strSrc.getBytes();
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(bt);
        byte[] bts = md.digest();
        StringBuilder des = new StringBuilder();
        for (byte b : bts) {
            String tmp = (Integer.toHexString(b & 0xFF));
            if (tmp.length() == 1) {
                des.append("0");
            }
            des.append(tmp);
        }
        return des.toString();
    }
}

FileUtil.java

package com.youdao.aicloud.translate.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class FileUtil {

    public static String loadMediaAsBase64(String path) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(path);
        byte[] temp = new byte[1024 * 1024];
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int l = 0;
        while ((l = fileInputStream.read(temp)) != -1) {
            bos.write(temp, 0, l);
        }
        fileInputStream.close();
        bos.close();
        return Base64.getEncoder().encodeToString(bos.toByteArray());
    }

    public static String saveFile(String path, byte[] data, boolean needDecode) throws IOException {
        File file = new File(path);
        if (!file.exists()) {
            file.createNewFile();
        }
        byte[] bytes = data;
        if (needDecode) {
            String base64 = new String(data, StandardCharsets.UTF_8);
            bytes = Base64.getDecoder().decode(base64);
        }
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(bytes);
        fileOutputStream.close();
        return path;
    }
}

HttpUtil.java

package com.youdao.aicloud.translate.utils;

import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

public class HttpUtil {

    private static OkHttpClient httpClient = new OkHttpClient.Builder().build();

    public static byte[] doGet(String url, Map<String, String[]> header, Map<String, String[]> params, String expectContentType) {
        Request.Builder builder = new Request.Builder();
        addHeader(builder, header);
        addUrlParam(builder, url, params);
        return requestExec(builder.build(), expectContentType);
    }

    public static byte[] doPost(String url, Map<String, String[]> header, Map<String, String[]> body, String expectContentType) {
        Request.Builder builder = new Request.Builder().url(url);
        addHeader(builder, header);
        addBodyParam(builder, body, "POST");
        return requestExec(builder.build(), expectContentType);
    }

    private static void addHeader(Request.Builder builder, Map<String, String[]> header) {
        if (header == null) {
            return;
        }
        for (String key : header.keySet()) {
            String[] values = header.get(key);
            if (values != null) {
                for (String value : values) {
                    builder.addHeader(key, value);
                }
            }
        }
    }

    private static void addUrlParam(Request.Builder builder, String url, Map<String, String[]> params) {
        if (params == null) {
            return;
        }
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        for (String key : params.keySet()) {
            String[] values = params.get(key);
            if (values != null) {
                for (String value : values) {
                    urlBuilder.addQueryParameter(key, value);
                }
            }
        }
        builder.url(urlBuilder.build());
    }

    private static void addBodyParam(Request.Builder builder, Map<String, String[]> body, String method) {
        if (body == null) {
            return;
        }
        FormBody.Builder formBodyBuilder = new FormBody.Builder(StandardCharsets.UTF_8);
        for (String key : body.keySet()) {
            String[] values = body.get(key);
            if (values != null) {
                for (String value : values) {
                    formBodyBuilder.add(key, value);
                }
            }
        }
        builder.method(method, formBodyBuilder.build());
    }

    private static byte[] requestExec(Request request, String expectContentType) {
        Objects.requireNonNull(request, "okHttp request is null");

        try (Response response = httpClient.newCall(request).execute()) {
            if (response.code() == 200) {
                ResponseBody body = response.body();
                if (body != null) {
                    String contentType = response.header("Content-Type");
                    if (contentType != null && !contentType.contains(expectContentType)) {
                        String res = new String(body.bytes(), StandardCharsets.UTF_8);
                        System.out.println(res);
                        return null;
                    }
                    return body.bytes();
                }
                System.out.println("response body is null");
            } else {
                System.out.println("request failed, http code: " + response.code());
            }
        } catch (IOException ioException) {
            System.out.println("request exec error: " + ioException.getMessage());
        }
        return null;
    }
}

WebSocketUtil.java

package com.youdao.aicloud.translate.utils;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;

public class WebSocketUtil extends WebSocketListener {

    private static WebSocket webSocket = null;

    private static FileOutputStream savePathStream = null;

    /**
     * 初始化websocket连接
     *
     * @param url paas接口地址
     */
    public static void initConnection(String url) {
        OkHttpClient client = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url(url).build();
        webSocket = client.newWebSocket(request, new WebSocketUtil());
    }

    public static void initConnection(String url, Map<String, String[]> params) {
        StringBuilder paramsBuilder = new StringBuilder();
        for (Map.Entry<String, String[]> entry : params.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            for (String value : values) {
                paramsBuilder.append(key).append("=").append(value).append("&");
            }
        }
        paramsBuilder.deleteCharAt(paramsBuilder.length() - 1);
        initConnection(url + "?" + paramsBuilder);
    }

    /**
     * 配置接收binary message的文件路径
     *
     * @param path 文件路径
     */
    public static void binaryMessageConfig(String path) {
        File file = new File(path);
        try {
            savePathStream = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送text message
     *
     * @param textMsg text message
     */
    public static void sendTextMessage(String textMsg) {
        if (webSocket == null) {
            throw new RuntimeException("websocket connection not established");
        }
        webSocket.send(textMsg);
        System.out.println("send text message: " + textMsg);
    }

    /**
     * 发送binary message
     *
     * @param binaryMsg binary message
     */
    public static void sendBinaryMessage(ByteString binaryMsg) {
        if (webSocket == null) {
            throw new RuntimeException("websocket connection not established");
        }
        webSocket.send(binaryMsg);
        System.out.println("send binary message length: " + binaryMsg.size());
    }

    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        System.out.println("connection open");
    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
        System.out.println("received text message: " + text);
        // 该判断方式仅用作demo展示, 生产环境请使用json解析
        if (!text.contains(""errorCode":"0"")) {
            System.exit(0);
        }
    }

    @Override
    public void onMessage(WebSocket webSocket, ByteString bytes) {
        System.out.println("received text message length: " + bytes.size());
        if (savePathStream != null) {
            try {
                savePathStream.write(bytes.toByteArray());
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    @Override
    public void onClosed(WebSocket webSocket, int code, String reason) {
        System.out.println("connection closed, code: " + code + ", reason: " + reason);
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        System.out.println("connection failed.");
        t.printStackTrace();
    }
}

POM.XML

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.14.9</version>
</dependency>

测试案例

TranslateDemo.java

package com.youdao.aicloud.translate;

import com.youdao.aicloud.translate.utils.AuthV3Util;
import com.youdao.aicloud.translate.utils.HttpUtil;

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

/**
 * 网易有道智云翻译服务api调用demo
 * api接口: https://openapi.youdao.com/api
 */
public class TranslateDemo {

    private static final String APP_KEY = "";     // 应用ID
    private static final String APP_SECRET = "";  // 应用密钥

    public static void main(String[] args) throws NoSuchAlgorithmException {
        // 添加请求参数
        Map<String, String[]> params = createRequestParams();
        // 添加鉴权相关参数
        AuthV3Util.addAuthParams(APP_KEY, APP_SECRET, params);
        // 请求api服务
        byte[] result = HttpUtil.doPost("https://openapi.youdao.com/api", null, params, "application/json");
        // 打印返回结果
        if (result != null) {
            System.out.println(new String(result, StandardCharsets.UTF_8));
        }
        // byte[]转json
        // JSONObject jsonObject = JSON.parseObject(new String(result, StandardCharsets.UTF_8));

        System.exit(1);
    }

    private static Map<String, String[]> createRequestParams() {
        /*
         * note: 将下列变量替换为需要请求的参数
         * 取值参考文档: https://ai.youdao.com/DOCSIRMA/html/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E7%BF%BB%E8%AF%91/API%E6%96%87%E6%A1%A3/%E6%96%87%E6%9C%AC%E7%BF%BB%E8%AF%91%E6%9C%8D%E5%8A%A1/%E6%96%87%E6%9C%AC%E7%BF%BB%E8%AF%91%E6%9C%8D%E5%8A%A1-API%E6%96%87%E6%A1%A3.html
         */
        String q = "待翻译文本";
        String from = "源语言语种";
        String to = "目标语言语种";

        return new HashMap<String, String[]>() {{
            put("q", new String[]{q});
            put("from", new String[]{from});
            put("to", new String[]{to});
        }};
    }
}