阿里云专业翻译api对接
最近我们一个商城项目涉及多语言切换,默认中文。用户切换语言可选英语和阿拉伯语言,前端APP和后端返回动态数据都要根据用户选择语言来展示。前端静态内容都做了三套语言,后端商品为了适用这种多语言我们也进行了改造。每一件商品名称,图片,价格等等 分别都有三中语言对应字段,根据前端公共参数(放请求header中的语言标识) 返回不同语言的字段值。
所以在商品的新增,修改等等地方商品名称,介绍等等就需要 根据中文翻译成英文和阿拉伯语保存下来。通过多方对比,最终发现阿里云机器翻译专业版还是最准确的,可能是阿里本来就有海量商品他们翻译引擎训练的比较智能。
接下来我们梳理下整个对接流程,官方文档:
什么是机器翻译JavaSDK_机器翻译(Machine Translation)-阿里云帮助中心
1,引入官方提供的java 版本 maven sdk
<!-- 阿里云翻译sdk --> <!-- https://mvnrepository.com/artifact/com.aliyun/alimt20181012 --> <dependency> <groupId>com.aliyun</groupId> <artifactId>alimt20181012</artifactId> <version>1.3.1</version> <exclusions> <exclusion> <groupId>com.aliyun</groupId> <artifactId>openplatform20191219</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>tea-openapi</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>credentials-java</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>tea-openapi</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>openapiutil</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>oss-util</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>tea</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>tea-rpc</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>tea-util</artifactId> </exclusion> <exclusion> <groupId>com.aliyun</groupId> <artifactId>tea-rpc</artifactId> </exclusion> </exclusions> </dependency>
<!-- 商品图片搜索 --> <dependency> <groupId>com.aliyun</groupId> <artifactId>imagesearch20201214</artifactId> <version>4.0.2</version> </dependency>
因为我们后面又使用了阿里的图片搜索,所以里面很多jar和图像搜索中的有冲突,如果只接入翻译实际上不需要排除。
2,定义配置:
建议使用一个ram账号 拿ram的accessKeyId 和secret,给这个子账号开通对应权限
public class AliYunTranslateConfig { private String accessKeyId; private String accessKeySecret; /** * 华南深圳 mt.aliyuncs.com * 阿联酋(迪拜) mt.aliyuncs.com * */ private String endpoint; }
3,封装 核心翻译方法
public class AliTranslamt20181012 { private AliYunTranslateConfig aliYunTranslateConfig; public AliTranslamt20181012(AliYunTranslateConfig aliYunTranslateConfig) { this.aliYunTranslateConfig = aliYunTranslateConfig; } /** * <b>description</b> : * <p>使用AK&SK初始化账号Client</p> * @return Client * * @throws Exception */ public com.aliyun.alimt20181012.Client createClient() { com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID .setAccessKeyId(aliYunTranslateConfig.getAccessKeyId()) // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 .setAccessKeySecret(aliYunTranslateConfig.getAccessKeySecret()); // Endpoint 请参考 https://api.aliyun.com/product/alimt config.endpoint = aliYunTranslateConfig.getEndpoint(); // 深圳 // 阿联酋(迪拜) mt.aliyuncs.com Client client = null; try { client = new Client(config); } catch (Exception e) { log.error("调用阿里云 翻译 初始化失败cause:{},。,errorMsg:{}",e.getCause().getMessage(),e.getMessage()); e.printStackTrace(); } return client; } /** * 翻译api * * @return */ public List<TranslateResponseBodyDataFromThirdPartDTO> translate(List<AliYunTranslateDTO> dtoList) { StopWatch stopWatch = new StopWatch(); stopWatch.start("thirdPart_wordFromZh2ArAndEn"); com.aliyun.alimt20181012.Client client = this.createClient(); List<TranslateResponseBodyDataFromThirdPartDTO> resultList = new java.util.ArrayList<>(dtoList.size()); dtoList.forEach(dto -> { com.aliyun.alimt20181012.models.TranslateRequest translateRequest = new com.aliyun.alimt20181012.models.TranslateRequest() .setFormatType(dto.getFormatType()) .setTargetLanguage(dto.getTargetLanguage()) .setSourceLanguage(dto.getSourceLanguage()) .setSourceText(dto.getSourceText()) .setScene(dto.getScene()) .setContext(dto.getContext()); com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions(); TranslateResponseBodyDataFromThirdPartDTO result = new TranslateResponseBodyDataFromThirdPartDTO(); result.setRequestKey(dto.getRequestKey()); resultList.add(result); try { TranslateResponse translateResponse = client.translateWithOptions(translateRequest, runtime); log.info("调用翻译 输入参数:{}",JSONUtil.parse(dto)); if(ObjectUtil.isNotNull(translateResponse)){ log.info("调用翻译 得到的结果为:{}", JSONUtil.parse(translateResponse.getBody())); if(200==translateResponse.getStatusCode()){ TranslateResponseBody.TranslateResponseBodyData data = translateResponse.getBody().getData(); BeanUtils.copyProperties(data, result); }else { log.error("调用翻译出错了,statusCode:{}",translateResponse.getStatusCode()); } } } catch (TeaException error) { log.error("调用阿里云翻译出错了,errorMsg:{}",error.getMessage()); com.aliyun.teautil.Common.assertAsString(error.message); } catch (Exception _error) { TeaException error = new TeaException(_error.getMessage(), _error); System.out.println(error.getMessage()); log.error("调用阿里云翻译出错了 exception ,msg:{}",error.getMessage()); com.aliyun.teautil.Common.assertAsString(error.message); } }); stopWatch.stop(); log.info(stopWatch.getLastTaskName()+"耗时:{} 毫秒",stopWatch.getLastTaskTimeMillis()); return resultList; } }
其中 请求的dto结构如下:其中,scene是识别翻译的使用场景,是商品标题还是描述异或者是客服沟通过程中的交流文字?不同场景的设置使翻译更贴近我们的预期翻译结果。
context也是很有用的,上下文语境,我们翻译某一段内容在不同场景下,可能前后与其相搭配的额外词汇。比如title 下我们可以加上 "我在网上商城搜索了 商品标题是"+****+“的商品”。
总之这两个参数的设置都是为了设置商品不同属性, 指定其大概范围的,从而能更准确的获得翻译结果。可以自己多调试下,找到适合自己业务的一些词汇。
public class AliYunTranslateDTO implements Serializable { public static String FROMTYPE_HTML ="html"; public static String FROMTYPE_TEXT ="text"; // from 语言 public static String SOURCELANGUAGE_ZH ="zh"; // 翻译目标语言 public static String TARGETLANGUAGE_EN ="en"; public static String TARGETLANGUAGE_AR ="ar"; // 场景可选取值:商品标题(title),商品描述(description),商品沟通(communication),医疗(medical),社交(social),金融(finance) public static String SCENE_TITLE ="title"; public static String SCENE_DESCRIPTION ="description"; public static String SCENE_COMMUNICATION ="communication"; public static String SCENE_MEDICAL ="medical"; public static String SCENE_SOCIAL ="social"; public static String SCENE_FINANCE ="finance"; /** * 用于标注 翻译的请求唯一标识 * */ @ApiModelProperty(hidden = true) private String requestKey = ""; /** * 翻译文本的格式,html( 网页格式。设置此参数将对待翻译文本以及翻译后文本按照 html 格式进行处理)、text(文本格式。设置此参数将对传入待翻译文本以及翻译后结果不做文本格式处理,统一按纯文本格式处理。 * */ @ApiModelProperty(name = "译文本的格式html 或text") private String FormatType; /** * * 原文语言-from * 英语 - en * 中文 - zh * 阿拉伯语 - ar * */ @ApiModelProperty(name = "原文语言-from") private String SourceLanguage; /** * 译文语言 -to * 英语 - en * 中文 - zh * 阿拉伯语 - ar * */ @ApiModelProperty(name = "译文语言 -to") private String TargetLanguage; /** * 待翻译内容 * */ @ApiModelProperty(name = "待翻译内容") private String SourceText; /** * 场景可选取值:商品标题(title),商品描述(description),商品沟通(communication),医疗(medical),社交(social),金融(finance) * */ @ApiModelProperty(name = "场景可选取值:商品标题(title),商品描述(description),商品沟通(communication),医疗(medical),社交(social),金融(finance)") private String Scene; /** * 上下文信息,可选填 (语境) * 如 我在商城买了一件 */ @ApiModelProperty(name = "上下文信息,可选填 (语境)") private String Context; }
返回结果 dto
public class TranslateResponseBodyDataFromThirdPartDTO { /** * 请求中携带的请求唯一标识,这是我们自定义的一个批次id * */ private String requestKey; /** * zh 源语言传入auto时,语种识别后的源语言代码 */ public String detectedLanguage; /** * 翻译结果 */ public String translated; /** * 总单词数 */ public String wordCount; }