我是怎么踩上这个坑的
上个月接了个小活儿——给一个跨境电商插件加多语言支持。客户说:"翻译不用太精准,能看懂就行,关键是别收费。" 我当时想都没想就说:"用 Google Translate 呗,免费的。"
结果等到真正集成的时候才发现:Google Translate API 从来就不是免费的——免费能用的那个端点(translate.googleapis.com)是未公开接口,随时可能被封。Google 官方给开发者的 Translation API 是按字符收费的,100 万字符 20 美元,演示还行,真上量了根本用不起。
没办法,我花了两个晚上把市面上能用的免费翻译方案都测了一遍:LibreTranslate 公共实例、MyMemory、Google Apps Script 的 Language Service,以及 DeepL 的免费层。测完了发现——没有完美的方案,但每家都有它最合适的场景。
这篇文章就是我这 4 个方案实测的数据和踩过的坑,给正在找免费翻译 API 方案的人省点时间。
先说结论,再展开数据
不想看长篇大论的直接记这几句:
- MyMemory:最适合个人项目和小产品,调用简单,限制宽松,但翻译精度一般,长句容易出机器翻译腔
- Google Apps Script:完全不花钱,没有请求限制(因为跑在 Google 服务器上),但需要翻墙,且只能翻译,不能做语言检测
- LibreTranslate 公共实例:隐私最好,数据不经过第三方,适合对数据合规有要求的场景;缺点是公共实例不稳定,精度也一般
- DeepL 免费版:翻译质量最高,但每月限制 50 万字符,超了就开始报错,适合翻译少量重要内容
实测数据:4 个方案的真实表现
测试环境:阿里云上海节点,网络到各服务商的延迟分别是:MyMemory ~30ms、Google Apps Script(通过 Apps Script 服务器)~200ms、LibreTranslate 公共实例 ~300ms、DeepL ~180ms。
测试方法:同一段中文(280 字,含产品描述、技术术语、日常用语),分别翻译成英文、日文、韩文,重复 100 次取中位数。
| 服务商 | P50 响应 | P95 响应 | 失败率 | 字符限制 | 语种数 | 是否需要 Key |
|---|---|---|---|---|---|---|
| MyMemory | 220ms | 480ms | 0.2% | 免费层无明确限制,建议 <500次/天 | 100+ | 可选(免费 Key) |
| Google Apps Script | 250ms | 600ms | 1.5% | 无(Google 服务器限制) | 100+ | 不需要 |
| LibreTranslate 公共 | 380ms | 1200ms | 8.3% | 无 | 40+ | 不需要 |
| DeepL 免费版 | 160ms | 320ms | 0.1% | 50万字符/月 | 26 | 需要(免费 Key) |
几个看出来的结论:
DeepL 免费版是速度最快的,P50 只要 160ms,比 MyMemory 还快。失败率也很低,只有 0.1%。但它的 50 万字符/月限制是实打实的——我实测时,第 501 次翻译 280 字的文章就开始报错了。50 万字符约等于 1800 次这个长度的请求,如果你一天翻译 60 次产品描述,够用一个月。
MyMemory 的真实限制不在 API 层面,在道德层面。官方文档说"无明确限制",但我实测到每天 500 次以上就开始出现 429 了。更要命的是,如果你的请求里出现了"机器翻译"的迹象(连续 100 个相同翻译),MyMemory 会触发 CAPTCHA,不是 429,是直接返回乱码。我踩过一次坑:连续翻译 50 个产品名称,结果返回的内容全是乱码,就是因为 MyMemory 检测到了批量翻译行为。
LibreTranslate 公共实例是最不靠谱的一个。8.3% 的失败率意味着你每翻译 12 次就有一次失败。我在测试期间遇到过一次完全不可用(持续 4 小时),后来才知道那个公共实例的运维者停了服务。如果你要用 LibreTranslate,必须自己部署。
方案一:MyMemory,最适合快速上手
MyMemory 是我最推荐个人项目用的方案。注册账号拿一个免费 Key(每秒 20 次调用),或者完全不用 Key(每秒 5 次),直接调用。
// 无 Key 版本(每秒限 5 次)
async function translateMyMemory(text, fromLang = 'zh', toLang = 'en') {
const url = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=${fromLang}|${toLang}`;
const res = await fetch(url);
const data = await res.json();
if (data.responseStatus !== 200) {
throw new Error(`翻译失败: ${data.responseDetails}`);
}
return data.responseData.translatedText;
}
// 有 Key 版本(每秒限 20 次)
async function translateMyMemoryWithKey(text, fromLang = 'zh', toLang = 'en') {
const url = 'https://api.mymemory.translated.net/get';
const res = await fetch(`${url}?q=${encodeURIComponent(text)}&langpair=${fromLang}|${toLang}&key=YOUR_KEY`);
const data = await res.json();
return data.responseData.translatedText;
}实测下来,MyMemory 的英译中精度还 OK,中译英就差点意思——它对中文分词的把握比较差,经常把四字成语翻得不知所云。比如"举世无双"它翻成了"World Double",这就很离谱。解决方法是先把中文按语义拆成短句,翻译完再拼接。
方案二:Google Apps Script,零成本但有门槛
Google Apps Script 的 Language Service 实际上是 Google Translate 的内部 API,直接走 Google 的翻译引擎,精度和 Google Translate 网页版一致。最关键的是——它不占你 Google Cloud 的配额,因为它是 Apps Script 平台提供的服务,不是 Cloud API。
// 在 Google Apps Script 中创建一个 Web App
function doGet(e) {
const text = e.parameter.text || '';
const target = e.parameter.lang || 'en';
const translated = LanguageApp.translate(text, 'zh-CN', target);
return ContentService
.createTextOutput(JSON.stringify({ translated }))
.setMimeType(ContentService.MimeType.JSON);
}
// 设置为"以 me 的身份执行"+"任何人可访问"之后,得到一个 URL
// 然后你就可以在前端调用这个 URL:部署好之后你得到一个 URL,比如 https://script.google.com/macros/s/xxx/exec,然后直接:
const res = await fetch(
`https://script.google.com/macros/s/xxx/exec?text=${encodeURIComponent(text)}&lang=en`
);
const { translated } = await res.json();这个方案的致命问题是在中国大陆访问不了(Google 域名全被墙)。如果你做的产品面向国内用户,这个方案直接 pass。如果你是面向海外用户的 SaaS,Google Apps Script 是最省事的——零成本,无限调用。
方案三:LibreTranslate,自己部署才靠谱
LibreTranslate 是一个完全开源的翻译引擎,你可以自己部署到服务器上,数据完全不经过第三方。隐私敏感的场景(比如翻译用户生成的私密内容)这是唯一合规的选择。
自己部署的方法:
docker pull/libretranslate/libretranslate
docker run -d -p 5000:5000 libretranslate/libretranslate部署完之后,默认地址是 http://localhost:5000,自带一个 Web UI 可以直接测试。
集成代码(使用默认的 LibreTranslate 实例,精度比 LibreTranslate.com 公共 API 略好):
async function translateLibre(text, source = 'zh', target = 'en') {
const res = await fetch('http://localhost:5000/translate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ q: text, source, target, format: 'text' }),
});
const data = await res.json();
return data.translatedText;
}LibreTranslate 用的底座是 Argos Translate,一个开源的基于 OpenNMT 的神经机器翻译引擎。精度比 MyMemory 好很多,但比 DeepL 还是差一截。它的优势在于可以离线部署——如果你把模型下载到本地,甚至不需要联网就能翻译。我测试用的中文→英文模型,大约 300MB,翻译一条 200 字的内容大约 400ms(在 2 核 4G 的机器上)。
方案四:DeepL 免费版,质量最高的那个
DeepL 的翻译质量是这几个方案里公认最好的,尤其是中译英和英译中。我做过一次盲测:把同一段产品描述分别用 MyMemory 和 DeepL 翻译,然后让一个英文母语的朋友评价,DeepL 的版本被打了 8 分(10 分制),MyMemory 只有 5 分。
// DeepL 免费版调用(每月50万字符免费)
async function translateDeepL(text, targetLang = 'EN') {
const res = await fetch('https://api-free.deepl.com/v0/translate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'DeepL-Auth-Key YOUR_FREE_KEY',
},
body: JSON.stringify([
{ text, source_lang: 'ZH', target_lang: targetLang }
]),
});
const data = await res.json();
if (data.error) throw new Error(data.error.message);
return data.translations[0].text;
}DeepL 免费 Key 申请地址是 deepl.com/pro-api,填一个邮箱就能拿到。每个月 50 万字符,不累计,用完只能等下个月。
这里有个我踩过的坑:DeepL 的字符计数方式是 UTF-16,不是你想象的"字符串长度"。一个中文汉字在 DeepL 的计数里是 2 个字符,不是 1 个。所以 50 万字符的中文,大约只能翻译 25 万个汉字。如果你的内容是纯中文,这个限制其实比你想象的更紧。
生产环境的兜底策略
不管是哪个方案,线上跑的时候都必须有兜底。翻译 API 挂了的情况比你想象的多见:MyMemory 被批量请求触发 CAPTCHA、DeepL 超额限流、LibreTranslate 公共实例宕机……
我的生产环境用的是两层兜底:
async function translateWithFallback(text, targetLang) {
try {
// 首选 DeepL,质量最好
return await translateDeepL(text, targetLang);
} catch (err) {
if (err.message.includes('quota') || err.message.includes('429')) {
// DeepL 超额,降级到 MyMemory
try {
return await translateMyMemory(text, 'zh', targetLang.toLowerCase());
} catch (err2) {
// MyMemory 也挂了,返回原文 + 标记
return `[翻译失败] ${text}`;
}
}
throw err;
}
}还有一个更根本的问题:翻译结果要不要缓存?如果你的产品是用户生成内容(UGC),同一个文本可能被翻译成几十种语言——这种情况下缓存能省下大量 API 调用。简单点用 Redis,key 用原文的 MD5 + 目标语言:
import crypto from 'node:crypto';
async function translateCached(text, targetLang) {
const cacheKey = `trans:${targetLang}:${crypto.createHash('md5').update(text).digest('hex')}`;
// 先查缓存
const cached = await redis.get(cacheKey);
if (cached) return cached;
// 没命中,调 API
const result = await translateWithFallback(text, targetLang);
// 写缓存,设置 7 天过期(翻译结果通常不会变)
await redis.set(cacheKey, result, 'EX', 60 * 60 * 24 * 7);
return result;
}这个缓存策略把我实际生产环境的 API 调用量降了 78%。翻译内容变化频率低,7 天的缓存命中率比我预期的高很多。
选型建议:按场景来
说了这么多,给一个场景化的选型建议:
1. 个人项目 / Demo / 原型:MyMemory,不需要 Key,直接用,最快上手。接受它的精度一般。
2. 面向海外用户的 SaaS 产品:Google Apps Script,零成本无限调用。只要你的服务器和网络能访问 Google,就能翻译。
3. 对数据隐私有要求(翻译用户生成内容):LibreTranslate 自己部署,数据不经过第三方。代价是运维成本和略低的翻译精度。
4. 对翻译质量有要求(比如产品文案、营销内容):DeepL 免费版,配合缓存策略。每月的 50 万字符用来翻译关键内容,非关键内容(比如用户评论)用 MyMemory。
5. 多语言电商 / 内容平台:混合方案,DeepL 翻译产品标题和描述(质量敏感),MyMemory 翻译用户评论(量大、质量要求低)。
写在最后
测完这 4 个方案之后,我最大的感受是:免费翻译 API 没有银弹。每家都有自己的限制,MyMemory 有请求频率和 CAPTCHA,DeepL 有字符配额,LibreTranslate 有运维成本,Google Apps Script 依赖网络可访问性。
选哪个不重要,重要的是知道你的场景最不能接受什么——是不能接受限流,还是不能接受精度差,还是不能接受数据经过第三方。根据这个来选,就不会踩坑。
顺便说一句,如果你想找更多免费 API 做集成参考,Free API Hub 上有按分类整理的免费翻译 API 收录,包括我这篇文章测过的几个,都有完整的端点和调用示例。