前言
在Unity项目开发过程中,经常需要处理多语言文本。本文将介绍如何实现一个简单实用的在线翻译功能,通过调用Google翻译API,帮助开发者快速完成文本翻译工作。既可以在编辑器中使用,也可以在运行时调用,满足不同场景的翻译需求。
一、效果演示(编辑器扩展)
<iframe allowfullscreen="true" data-mediaembed="csdn" frameborder="0" id="1WxfVKOZ-1731550943254" src="https://live.csdn.net/v/embed/433997"></iframe>TranslateTest
二、制作过程
简言
主要使用Unity 的网络请求类UnityWebRequest,使用Google翻译的公开接口发送https的POST请求。以下拆分来逐步实现,完整代码在最后。
1.安装依赖包Newtonsoft Json(特别注意以下说明!)
首先说明,不安装此包也是可以的,需要把请求的Json和返回的Json单独写两个类使用Unity的JsonUtility进行序列化和反序列化也可以。本文使用Newtonsoft Json工具,功能更加强大。
安装方式如下
1、打开Unity的Package Manager
2、选择注册表中的包并搜索Newtonsoft Json进行安装
3、安装后重启代码编辑器Visual Studio或Visual Studio Code等,不然可能出现搜索不到对应的API和命名空间。
2.定义字段和方法
代码如下(示例):
//Google翻译的API接口
public const string TranslateUrl = "https://googlet.deno.dev/translate";
public string originalText; // 输入内容
public string translatedText; // 输出内容
public int targetLanguage; // 目标语言
public bool isTranslating; // 是否正在翻译
//翻译目标语言字典,还支持其他常见语言,可自行搜索添加,本处为常用的几种语言
public Dictionary<string, string> targetLanguages = new Dictionary<string, string>()
{
{"auto", "自动"},
{"zh", "中文"},
{"en", "英语"},
{"de", "德语"},
{"ru", "俄语"},
{"fr", "法语"},
{"ja", "日语"},
{"ko", "韩语"},
};
//调用协程请求方法
public void Translate(string originalText, string targetLanguage = "auto", Action<string> onTranslate = null)
{
if (isTranslating || string.IsNullOrEmpty(originalText)) return;
StartCoroutine(TranslateCoroutine(originalText, targetLanguage, onTranslate));
}
/// <summary>
/// 用协程处理翻译请求
/// </summary>
/// <param name="originalText">输入内容</param>
/// <param name="targetLanguage">目标语言</param>
/// <param name="onTranslate">翻译完成回调</param>
/// <returns></returns>
IEnumerator TranslateCoroutine(string originalText, string targetLanguage, Action<string> onTranslate)
{
isTranslating = true;
/* 请求格式,请求方式为POST请求:
{
"text": “"test",
"source_lang": "auto",
"target lang": "zh"
}*/
/* 回复格式:
{
"code"”: 200,
"data":“测试”
} */
JObject translateData = new JObject()//这里使用Newtonsoft.Json库来处理json请求数据格式
{
["text"] = originalText,
["source_lang"] = "auto",
["target_lang"] = targetLanguage,
};
UnityWebRequest request = new UnityWebRequest(TranslateUrl, "POST");//创建一个Post请求
byte[] bodyRaw = Encoding.UTF8.GetBytes(translateData.ToString());
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");//设置请求头
yield return request.SendWebRequest();//发送请求
if (request.isNetworkError || request.isHttpError)
{
Debug.LogError(request.error);
}
else
{
try
{
JObject responseData = JObject.Parse(request.downloadHandler.text);//解析回复数据
onTranslate?.Invoke(responseData["data"].ToString());//获取data字段内容并调用回调函数
}
catch (Exception e)
{
Debug.LogError(e);
}
}
isTranslating = false;
}
现在就可以在运行时通过调用Translate方法进行使用了,本文再讲一下实现编辑器扩展在未播放时使用。
3.编写编辑器扩展方法
/// <summary>
/// 编辑器扩展
/// </summary>
#if UNITY_EDITOR
[CustomEditor(typeof(TranslateRequest))]
public class TranslateRequestEditor : Editor
{
private TranslateRequest translateRequest;//翻译组件
private GUIStyle textAreaStyle;//文本区域样式
private Vector2 inputScrollPos;//输入区域滚动位置
private void OnEnable()
{
translateRequest = (TranslateRequest)target;
textAreaStyle = new GUIStyle(EditorStyles.textArea)
{
wordWrap = true//自动换行
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();//更新序列化对象
// 输入区域
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField("输入内容", GUILayout.MaxWidth(50));
using (var scrollView = new EditorGUILayout.ScrollViewScope(inputScrollPos))//绘制输入区域
{
inputScrollPos = scrollView.scrollPosition;
translateRequest.originalText = EditorGUILayout.TextArea(
translateRequest.originalText,
textAreaStyle,
GUILayout.ExpandHeight(true)
);
}
}
// 输出区域
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField("翻译结果", GUILayout.MaxWidth(50));
translateRequest.translatedText = EditorGUILayout.TextArea(
translateRequest.translatedText,
textAreaStyle
);
}
using (new EditorGUILayout.HorizontalScope())
{
translateRequest.targetLanguage = EditorGUILayout.Popup(translateRequest.targetLanguage, translateRequest.targetLanguages.Values.ToArray(), GUILayout.MaxWidth(100));
if (GUILayout.Button("清空"))
{
translateRequest.translatedText = "";
}
if (GUILayout.Button("复制"))
{
GUIUtility.systemCopyBuffer = translateRequest.translatedText;
}
}
GUI.enabled = !translateRequest.isTranslating;//翻译时不可编辑
if (GUILayout.Button(translateRequest.isTranslating ? "翻译中..." : "翻译"))
{
translateRequest.Translate(translateRequest.originalText, translateRequest.targetLanguages.Keys.ToArray()[translateRequest.targetLanguage], x =>
{
translateRequest.translatedText = x;
});
}
GUI.enabled = true;//恢复编辑
serializedObject.ApplyModifiedProperties();//应用修改
}
}
#endif
编写后将脚本挂载在一个空物体身上,检查器面板上效果如下:
三、完整代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
public class TranslateRequest : MonoBehaviour
{
public const string TranslateUrl = "https://googlet.deno.dev/translate";//翻译接口
public string originalText;//输入内容
public string translatedText;//输出内容
public int targetLanguage;//目标语言
public bool isTranslating;//是否正在翻译
public Dictionary<string, string> targetLanguages = new Dictionary<string, string>()//目标语言
{
{"auto", "自动"},
{"zh", "中文"},
{"en", "英语"},
{"de", "德语"},
{"ru", "俄语"},
{"fr", "法语"},
{"ja", "日语"},
{"ko", "韩语"},
};
public void Translate(string originalText, string targetLanguage = "auto", Action<string> onTranslate = null)
{
if (isTranslating || string.IsNullOrEmpty(originalText)) return;
StartCoroutine(TranslateCoroutine(originalText, targetLanguage, onTranslate));
}
/// <summary>
/// 用协程处理翻译请求
/// </summary>
/// <param name="originalText">输入内容</param>
/// <param name="targetLanguage">目标语言</param>
/// <param name="onTranslate">翻译完成回调</param>
/// <returns></returns>
IEnumerator TranslateCoroutine(string originalText, string targetLanguage, Action<string> onTranslate)
{
isTranslating = true;
/* 请求格式,请求方式为POST请求:
{
"text": “"test",
"source_lang": "auto",
"target lang": "zh"
}*/
/* 回复格式:
{
"code"”: 200,
"data":“测试”
} */
JObject translateData = new JObject()//这里使用Newtonsoft.Json库来处理json请求数据格式
{
["text"] = originalText,
["source_lang"] = "auto",
["target_lang"] = targetLanguage,
};
UnityWebRequest request = new UnityWebRequest(TranslateUrl, "POST");//创建一个Post请求
byte[] bodyRaw = Encoding.UTF8.GetBytes(translateData.ToString());
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");//设置请求头
yield return request.SendWebRequest();//发送请求
if (request.isNetworkError || request.isHttpError)
{
Debug.LogError(request.error);
}
else
{
try
{
JObject responseData = JObject.Parse(request.downloadHandler.text);//解析回复数据
onTranslate?.Invoke(responseData["data"].ToString());//获取data字段内容并调用回调函数
}
catch (Exception e)
{
Debug.LogError(e);
}
}
isTranslating = false;
}
}
/// <summary>
/// 编辑器扩展
/// </summary>
#if UNITY_EDITOR
[CustomEditor(typeof(TranslateRequest))]
public class TranslateRequestEditor : Editor
{
private TranslateRequest translateRequest;//翻译组件
private GUIStyle textAreaStyle;//文本区域样式
private Vector2 inputScrollPos;//输入区域滚动位置
private void OnEnable()
{
translateRequest = (TranslateRequest)target;
textAreaStyle = new GUIStyle(EditorStyles.textArea)
{
wordWrap = true//自动换行
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();//更新序列化对象
// 输入区域
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField("输入内容", GUILayout.MaxWidth(50));
using (var scrollView = new EditorGUILayout.ScrollViewScope(inputScrollPos))//绘制输入区域
{
inputScrollPos = scrollView.scrollPosition;
translateRequest.originalText = EditorGUILayout.TextArea(
translateRequest.originalText,
textAreaStyle,
GUILayout.ExpandHeight(true)
);
}
}
// 输出区域
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField("翻译结果", GUILayout.MaxWidth(50));
translateRequest.translatedText = EditorGUILayout.TextArea(
translateRequest.translatedText,
textAreaStyle
);
}
using (new EditorGUILayout.HorizontalScope())
{
translateRequest.targetLanguage = EditorGUILayout.Popup(translateRequest.targetLanguage, translateRequest.targetLanguages.Values.ToArray(), GUILayout.MaxWidth(100));
if (GUILayout.Button("清空"))
{
translateRequest.translatedText = "";
}
if (GUILayout.Button("复制"))
{
GUIUtility.systemCopyBuffer = translateRequest.translatedText;
}
}
GUI.enabled = !translateRequest.isTranslating;//翻译时不可编辑
if (GUILayout.Button(translateRequest.isTranslating ? "翻译中..." : "翻译"))
{
translateRequest.Translate(translateRequest.originalText, translateRequest.targetLanguages.Keys.ToArray()[translateRequest.targetLanguage], x =>
{
translateRequest.translatedText = x;
});
}
GUI.enabled = true;//恢复编辑
serializedObject.ApplyModifiedProperties();//应用修改
}
}
#endif