全网最强翻译工具制作

最近在开发个海外项目,由于对接的支付平台文档还有邮件交流都是用的英文,但使用传统工具翻译会”机翻感”很重,一看就是机器翻译的,而且经常会出现词不达意现象,比如:我们做个翻译:“有人的地方就有江湖”,来看看网易有道词典的翻译:

翻译结果:Where there are people, there are rivers and lakes!

可以看出,**机器不理解“江湖”在中文是什么意思**,把它直接翻译成了“江”和“湖”两样东西,其实这在中文里是个隐喻,指的是:只要在有人聚集的地方,就会有争斗,纷争!形容人际关系复杂!

接下来,我们再来翻译首泰戈尔经典句子“Let life be beautiful like summer flowers and death like autumn leaves”,如果使用逐字翻译,翻出的内容是:“让生命像夏天的花儿一样美丽,让死亡像秋天落叶般离去”,这样翻译出来非常呆板,而且缺乏中文文学之美,正确的翻译应该是“**生如夏花之绚烂,死如秋叶之静美**”

目前市面上主流的翻译软件有传统的机翻工具:谷歌翻译、微软翻译、DeepL、有道词典、腾讯翻译、百度翻译,大模型翻译工具有:OpenAI、Claude、零一万物、百度千帆大模型、混元大模型、豆包大模型。

那么怎么翻译效果更好呢?

如果单独使用传统机翻或者大模型翻译,都不能达到完美翻译状态,**最佳的方案便是将两者结合起来一起使用!**

传统机翻我们采用:DeepL,它**被誉为全世界最精准的机器翻译,比最接近他们的竞争对手准确三倍以上,大模型我们采用:OpenAI最新的gpt4o模型,先使用DeepL做第一道翻译,再使用gpt4o进行翻译后结果意译润色!**

体验Demo

我搭建的翻译工具:http://translate.quanyouhulian.com/,可以体验下,采用deepl+gpt4o润色,全球最强翻译!

搭建翻译页面

这里我们模仿deepL的页面去生成,可以参考我之前的文章:这款工具能一键将图片内容生成前端源代码),

对应的html页面源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<html>

<head>
<meta name="referrer" content="no-referrer">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<script>
let selectedLanguage = "中文(简体)"; // Default language

// 在页面加载时读取localStorage中的内容
window.onload = function () {
const inputText = document.getElementById('inputText');
const savedText = localStorage.getItem('inputText');
if (savedText) {
inputText.value = savedText;
}
// 添加input事件监听器,实现边输入边保存
inputText.addEventListener('input', function () {
localStorage.setItem('inputText', inputText.value);
});

// New code to handle openid
const urlParams = new URLSearchParams(window.location.search);
const openid = urlParams.get('openid');
if (openid) {
localStorage.setItem('openid', openid);
} else {
const storedOpenid = localStorage.getItem('openid');
if (!storedOpenid) {
showIllegalSourceModal();
}
}
}

async function translateText() {
const openid = localStorage.getItem('openid');
if (!openid) {
showIllegalSourceModal();
return;
}

// 先清楚之前记录
clearOutputText()

// 调用成功提示
showSuccessModal()

const inputText = document.getElementById('inputText').value;
// 在翻译前保存输入的内容到localStorage
localStorage.setItem('inputText', inputText);
// 这里ip和端口改成你自己的服务器的
const response = await fetch('http://ip:端口/translate/deepl', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: inputText,
target_lang: selectedLanguage,
openid: openid
}) // 确保发送的是JSON格式
});
const result = await response.json();
document.getElementById('outputText').value = result.data;
}

function toggleDropdown() {
const dropdown = document.getElementById('languageDropdown');
dropdown.classList.toggle('hidden');
}

function selectLanguage(lang) {
const langElement = document.querySelector('.flex.items-center.space-x-2.border-l.pl-4 span');
langElement.textContent = lang;
selectedLanguage = lang; // Update the selected language
toggleDropdown(); // 隐藏下拉框
}

function clearInputText() {
document.getElementById('inputText').value = '';
localStorage.removeItem('inputText'); // 清除localStorage中的内容
}

function clearOutputText() {
document.getElementById('outputText').value = '';
}

function showSuccessModal() {
const modal = document.createElement('div');
modal.style.position = 'absolute';
modal.style.top = '12%';
modal.style.left = '50%';
modal.style.transform = 'translateX(-50%)';
modal.style.backgroundColor = 'rgba(0,0,0,0.7)';
modal.style.color = 'white';
modal.style.padding = '10px 20px';
modal.style.borderRadius = '5px';
modal.style.zIndex = '1000';
modal.style.display = 'flex';
modal.style.alignItems = 'center';
modal.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';

const message = document.createElement('span');
message.textContent = '调用成功';

const closeButton = document.createElement('button');
closeButton.innerHTML = '<i class="fas fa-check"></i>'; // 确认图标
closeButton.style.backgroundColor = 'transparent';
closeButton.style.border = 'none';
closeButton.style.marginLeft = '10px';
closeButton.style.cursor = 'pointer';
closeButton.onclick = () => document.body.removeChild(modal);

modal.appendChild(message);
modal.appendChild(closeButton);

const targetElement = document.querySelector('.flex.justify-between.items-center.border-b.pb-2');
targetElement.appendChild(modal);

// 自动关闭弹窗
setTimeout(() => targetElement.removeChild(modal), 3000);
}

function showIllegalSourceModal() {
const modal = document.createElement('div');
modal.style.position = 'fixed';
modal.style.top = '0';
modal.style.left = '0';
modal.style.width = '100%';
modal.style.height = '100%';
modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
modal.style.display = 'flex';
modal.style.justifyContent = 'center';
modal.style.alignItems = 'center';
modal.style.zIndex = '1000';

const modalContent = document.createElement('div');
modalContent.style.backgroundColor = 'white';
modalContent.style.padding = '20px';
modalContent.style.borderRadius = '5px';

const message = document.createElement('p');
message.textContent = '用户非法来源,请从圈友互联AI应用中心跳转过来(首次登录使用):';

const link = document.createElement('a');
link.href = 'https://ai.quanyouhulian.com/#/appcenter/index';
link.target = '_blank';
link.textContent = '点击跳转';
link.style.color = 'blue'; // 设置链接颜色为蓝色
link.style.textDecoration = 'underline'; // 设置链接带有下划线

const closeButton = document.createElement('button');
closeButton.textContent = '关闭';
closeButton.onclick = () => document.body.removeChild(modal);

modalContent.appendChild(message);
modalContent.appendChild(link);
modalContent.appendChild(closeButton);
modal.appendChild(modalContent);
document.body.appendChild(modal);
}
</script>
</head>

<body class="bg-gray-50">
<!-- Navigation Bar -->
<nav class="bg-blue-600 text-white p-4">
<div class="flex justify-center items-center">
<div class="text-lg font-bold text-center">全网最精准AI翻译</div>
</div>
<div class="flex justify-center items-center mt-2">
<div class="text-sm text-center">采用deepl专业版翻译+chatgpt4o润色,翻译结果全球最强</div>
</div>
</nav>
<!-- End Navigation Bar -->
<div class="max-w-7xl mx-auto p-4">
<div class="mt-4 bg-white rounded-lg shadow p-4">
<div class="flex justify-between items-center border-b pb-2">
<div class="text-gray-700">系统会自动检测源语言</div>
<div class="flex items-center space-x-2">
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="translateText()">翻译</button>
<div class="flex items-center space-x-2 border-l pl-4 relative">
<span class="text-gray-700">中文(简体)</span>
<i class="fas fa-chevron-down cursor-pointer" onclick="toggleDropdown()"></i>
<div id="languageDropdown"
class="hidden absolute top-full right-0 mt-2 w-48 bg-white border border-gray-300 rounded shadow-lg z-10">
<div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem" onclick="selectLanguage('中文(简体)')">中文(简体)</a>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
role="menuitem" onclick="selectLanguage('English')">English</a>
</div>
</div>
</div>
</div>
</div>
<!-- <div class="mt-4 grid grid-cols-2 gap-4">
<textarea id="inputText" class="w-full h-screen border border-gray-300 rounded focus:outline-none p-2" placeholder="输入并开始翻译。"></textarea>
<textarea id="outputText" class="w-full h-screen border border-gray-300 rounded focus:outline-none p-2" placeholder="翻译结果" readonly></textarea>
</div> -->
<div class="mt-4 grid grid-cols-2 gap-4">
<div class="relative">
<textarea id="inputText"
class="w-full h-screen border border-gray-300 rounded focus:outline-none p-2"
placeholder="输入并点击翻译按钮开始翻译。"></textarea>
<button class="absolute top-2 right-2 bg-red-500 text-white px-2 py-1 rounded" style="background-color: rgba(239, 68, 68, 0.3);" title="清除输入框文本" onmouseover="this.style.backgroundColor='rgba(239, 68, 68, 0.8)'" onmouseout="this.style.backgroundColor='rgba(239, 68, 68, 0.3)'" onclick="clearInputText()">
<i class="fas fa-times"></i> <!-- 透明的X图标 -->
</button>
</div>
<div class="relative">
<textarea id="outputText"
class="w-full h-screen border border-gray-300 rounded focus:outline-none p-2"
placeholder="翻译结果,默认翻译成中文" readonly></textarea>
<button class="absolute top-2 right-2 bg-red-500 text-white px-2 py-1 rounded" style="background-color: rgba(239, 68, 68, 0.3);" title="清除输出框文本" onmouseover="this.style.backgroundColor='rgba(239, 68, 68, 0.8)'" onmouseout="this.style.backgroundColor='rgba(239, 68, 68, 0.3)'" onclick="clearOutputText()">
<i class="fas fa-times"></i> <!-- 透明的X图标 -->
</button>
</div>
</div>
</div>
</div>
</body>

</html>

搭建后端翻译接口

后端采用java实现,java启动demo可以参考我之前文章(https://mp.weixin.qq.com/s/ZVTSVVAO2UejZKhDqSMn6w)挑选个demo即可快速本地运行!

以下是实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
private static String PRO_DEEPL_URL = "https://api.deepl.com/v2/translate";

// 你的deepl密钥
private static String PRO_DEEPL_KEY = "";

@RequestMapping("/deepl")
public CommonResult<String> deepl(HttpServletRequest req, @RequestBody TranslateBody translateBody) {

try {
log.info("开始使用deepl翻译,body:{}", JSON.toJSONString(translateBody));

// 暂时免费使用,后面再做处理
String openid = translateBody.getOpenid();

String content = translateBody.getText();

Map<String, Object> map = new HashMap<String, Object>();
// 根据换行符分割body,并将每一行添加到list中
List<String> list = Arrays.asList(content.split("\\r?\\n"));
map.put("text", list);
log.info("list size:{}", list.size());
String targetLang = translateBody.getTarget_lang();
if ("English".equals(targetLang)) {
map.put("target_lang", "EN");
} else {
// 默认翻译成中文
map.put("target_lang", "ZH");
}

String bodyMap = JSON.toJSONString(map);

log.info("开始翻译,bodymap:{}", bodyMap);
String result = HttpRequest.post(PRO_DEEPL_URL).header("Content-Type", "application/json").header("Authorization", "DeepL-Auth-Key " + PRO_DEEPL_KEY).body(bodyMap).execute().body();

log.info("翻译结果:{}", result);

// 将JSON字符串转换为JSONObject
JSONObject jsonObject = JSON.parseObject(result);

// 提取translations数组
JSONArray translations = jsonObject.getJSONArray("translations");

// 创建一个StringBuilder来拼接翻译后的文本
StringBuilder translatedText = new StringBuilder();

// 遍历translations数组,获取每个翻译后的文本并拼接起来
for (int i = 0; i < translations.size(); i++) {
JSONObject translation = translations.getJSONObject(i);
String translatedLine = translation.getString("text");
translatedText.append(translatedLine);
if (i < translations.size() - 1) {
translatedText.append("\n"); // 保持原有的换行符
}
}

log.info("Translated text:{}", translatedText.toString());

// 这里再去对translatedText做中文润色

return CommonResult.success(translatedText.toString());
} catch (Exception e) {
log.error("异常", e);
return CommonResult.success("翻译异常");
}

}

翻译结果采用gpt4o进行中文润色

角色设定

这里对gpt4o设定3个角色:英语老师、语文老师、校长

  • 英语老师精通英文,先将英文文章直译为中文
  • 语文老师精通中文,将直译的结果意译润色
  • 校长,同时精通中文和英文,对翻译结果进行校验,指出文章中存在问题的地方,最后再让语文老师去修改。

为什么要使用这3个角色?

借助直译 + 意译,我们让翻译的质量大幅提升,但是也有朋友反馈,意译的时候,可能会偏离原意,把意译的内容重新翻译成英文再做下比对,即可得到最准确的翻译内容

中文润色翻译流程

  1. deepL先直译英文文章为中文,形成直译稿
  2. 语文老师再意译润色,形成意译初稿
  3. 英语老师将意译稿回译为英文,形成回译稿
  4. 校长对比原文、意译稿和回译稿,指出问题提出修改意见
  5. 语文老师根据校长的反馈,修改意译初稿,形成终稿

优缺点

这样经过五步校验,可以有效的避免翻译中存在的遗漏和偏离,翻译质量会更高一些。

但是这样做的缺点也很明显:

  1. 需要五步才能完成翻译,耗时长,消耗 Token 多,性价比不高
  2. 翻译质量受第一稿的影响很大,如果第一稿就质量不高,那么后面的翻译质量都会受到影响

Prompt 参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
现在你要帮忙解释一篇专业的技术文章成简体中文给大学生阅读。

规则:
- 翻译时要准确传达学术论文的事实和背景,同时风格上保持为通俗易懂并且严谨的科普文风格。
- 保留特定的英文术语、数字或名字,并在其前后加上空格,例如:"中 UN 文""不超过 10 秒"
- 即使上意译也要保留术语,例如 FLAC,JPEG 等。保留公司缩写,例如 Microsoft, Amazon 等。
- 保留引用的论文,例如 [20] 这样的引用;同时也要保留针对图例的引用,例如保留 Figure 1 并翻译为图 1
- 全角括号换成半角括号,并在左括号前面加半角空格,右括号后面加半角空格。
- 输入格式为Markdown格式,输出格式也必须保留原始Markdown格式


现在有三个角色:
- 英语老师,精通英文,能精确的理解英文并用中文表达
- 中文老师,精通中文,擅长按照中文使用喜欢撰写通俗易懂的科普文
- 校长,精通中文和英文,擅长校对审查


和步骤来翻译这篇文章,每一步都必须遵守以上规则,打印每一步的输出结果:

Step 1:现在你是英语老师,精通英文,对原文按照字面意思直译,务必遵守原意,翻译时保持原始英文的段落结构,不要合并分段

Step 2:扮演中文老师,精通中文,擅长写通俗易懂的科普文章,对英语老师翻译的内容重新意译,遵守原意的前提下让内容更通俗易懂,符合中文表达习惯,但不要增加和删减内容,保持原始分段

Step 3: 英文老师将中文老师的文稿反向翻译成英文(回译稿)

Step 4:扮演校长,精通中文和英文,校对回译稿和原稿中的区别,重点检查两点:翻译稿和原文有出入的位置;不符合中文表达习惯的位置;

Step 5:中文老师基于校长的修改意见,修改初稿

本条消息只需要回复OK,接下来的消息我将会给你发送完整内容,收到后请按照上面的规则和下面的格式打印翻译结果,返回格式如下,"{xxx}"表示占位符:

### 英语老师直译结果
{英语老师直译结果}

### 中文老师意译初稿
{中文老师意译初稿}

### 英语老师回译
{英语老师回译稿}

### 校长校对意见

以下是在中文翻译中缺失的部分:

{重复以下列表,直到列出所有缺失的内容}
- 对比原文缺失或表达歧义部分{1...n}:
- 原文:“{English}”
- 译文:“{译文}”
- 建议:{新增翻译 or 修改翻译}


以下是中文翻译表达不符合中文习惯的部分:

{重复以下列表,直到列出所有需要修改的内容}
- 修改{1...n}:
- 原文:“{English}”
- 译文:“{译文}”
- 建议:{修改后内容}


### 中文老师翻译终稿
{中文老师翻译终稿}

总结

在实际使用中,需要根据实际的情况进行平衡:如果你在乎成本,两步就足够了,再配合人工校对,对翻译结果中的关键部分进行人工校对;如果你不在乎成本,甚至可以再引入更多的角色,比如,一开始让 2-3 个不同风格英语老师去翻译,然后让语文老师选择一个最好的结果进行意译,这样就可以避免因为第一次翻译结果不好,导致后面的翻译质量也不好的问题。

大家快去体验全球最强翻译工具吧:http://translate.quanyouhulian.com/


全网最强翻译工具制作
http://example.com/2023/12/05/后端技术互联/全网最强翻译工具制作/
作者
技术Z先生
发布于
2023年12月5日
许可协议