This commit is contained in:
xxnuo
2025-07-21 01:56:14 +08:00
parent 1ee0d33589
commit f56312116e
13 changed files with 1142 additions and 3 deletions

86
js/mts.js Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env node
const fastify = require('fastify');
const cors = require('@fastify/cors');
const { getConfig, validateToken } = require('./utils/config');
const { authenticate, errorHandler } = require('./utils/middleware');
const { getSupportedLanguages, preloadModel, shutdown } = require('./utils/translator');
const registerCoreRoutes = require('./routes/core');
const registerTranslateRoutes = require('./routes/translate');
const registerPluginRoutes = require('./routes/plugins');
// 获取配置
const config = getConfig();
// 创建Fastify实例
const server = fastify({
logger: {
level: config.logLevel,
transport: {
target: 'pino-pretty',
options: {
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname'
}
}
}
});
// 注册CORS中间件
server.register(cors, {
origin: true,
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'Key']
});
// 设置错误处理器
server.setErrorHandler(errorHandler);
// 路由选项
const routeOptions = {
authenticate: authenticate,
validateToken: validateToken
};
// 注册路由
server.register(registerCoreRoutes, routeOptions);
server.register(registerTranslateRoutes, routeOptions);
server.register(registerPluginRoutes, routeOptions);
// 启动服务器
async function start() {
try {
// 输出服务信息
console.log(`Service port: ${config.port}`);
// 获取支持的语言列表
const languages = getSupportedLanguages();
// 预加载常用语言对
// await preloadModel('en', 'zh-Hans');
// 监听端口
await server.listen({ port: config.port, host: config.host });
} catch (err) {
server.log.error(err);
process.exit(1);
}
}
// 处理进程退出
process.on('SIGINT', async () => {
console.log('Shutting down server...');
await shutdown();
await server.close();
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('Shutting down server...');
await shutdown();
await server.close();
process.exit(0);
});
// 启动服务器
start();

40
js/routes/core.js Normal file
View File

@@ -0,0 +1,40 @@
const { getVersion } = require('../utils/config');
const { getLoadedModels } = require('../utils/translator');
/**
* 注册核心路由
* @param {Object} fastify Fastify实例
* @param {Object} options 选项
*/
function registerCoreRoutes(fastify, options) {
// 版本信息
fastify.get('/version', async (request, reply) => {
return { version: getVersion() };
});
// 健康检查
fastify.get('/health', async (request, reply) => {
return { status: 'ok' };
});
// 心跳检查
fastify.get('/__heartbeat__', async (request, reply) => {
reply.type('text/plain');
return 'Ready';
});
// 负载均衡心跳检查
fastify.get('/__lbheartbeat__', async (request, reply) => {
reply.type('text/plain');
return 'Ready';
});
// 获取已加载的模型列表
fastify.get('/models', {
preHandler: options.authenticate
}, async (request, reply) => {
return { models: getLoadedModels() };
});
}
module.exports = registerCoreRoutes;

90
js/routes/plugins.js Normal file
View File

@@ -0,0 +1,90 @@
const { translate, batchTranslate } = require('../utils/translator');
/**
* 注册翻译插件兼容路由
* @param {Object} fastify Fastify实例
* @param {Object} options 选项
*/
function registerPluginRoutes(fastify, options) {
// 沉浸式翻译插件API
fastify.post('/imme', async (request, reply) => {
// 验证token
const token = request.query.token;
if (!options.validateToken(token)) {
return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
}
try {
const { source_lang, target_lang, text, texts } = request.body;
// 处理批量翻译
if (Array.isArray(texts) && texts.length > 0) {
const results = await batchTranslate(texts, source_lang || 'auto', target_lang || 'zh-Hans');
return { data: results };
}
// 处理单个文本翻译
if (text) {
const result = await translate(text, source_lang || 'auto', target_lang || 'zh-Hans');
return { data: result };
}
return reply.code(400).send({ error: 'BadRequest', message: 'Missing text or texts parameter' });
} catch (error) {
return reply.code(500).send({ error: 'TranslationError', message: error.message });
}
});
// 简约翻译插件API
fastify.post('/kiss', async (request, reply) => {
// 验证token
const token = request.headers.key;
if (!options.validateToken(token)) {
return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
}
try {
const { from, to, text, texts } = request.body;
// 处理批量翻译
if (Array.isArray(texts) && texts.length > 0) {
const results = await batchTranslate(texts, from || 'auto', to || 'zh-Hans');
return { code: 200, text: results.join('\n') };
}
// 处理单个文本翻译
if (text) {
const result = await translate(text, from || 'auto', to || 'zh-Hans');
return { code: 200, text: result };
}
return reply.code(400).send({ code: 400, error: 'Missing text or texts parameter' });
} catch (error) {
return reply.code(500).send({ code: 500, error: error.message });
}
});
// 划词翻译插件API
fastify.post('/hcfy', async (request, reply) => {
// 验证token
const token = request.query.token;
if (!options.validateToken(token)) {
return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
}
try {
const { text, from, to } = request.body;
if (!text) {
return reply.code(400).send({ error: 'BadRequest', message: 'Missing text parameter' });
}
const result = await translate(text, from || 'auto', to || 'zh-Hans');
return { translation: result };
} catch (error) {
return reply.code(500).send({ error: 'TranslationError', message: error.message });
}
});
}
module.exports = registerPluginRoutes;

104
js/routes/translate.js Normal file
View File

@@ -0,0 +1,104 @@
const { translate, batchTranslate } = require('../utils/translator');
/**
* 注册翻译路由
* @param {Object} fastify Fastify实例
* @param {Object} options 选项
*/
function registerTranslateRoutes(fastify, options) {
// 普通翻译API
fastify.post('/translate', {
preHandler: options.authenticate,
schema: {
body: {
type: 'object',
required: ['from', 'to', 'text'],
properties: {
from: { type: 'string' },
to: { type: 'string' },
text: { type: 'string' }
}
}
}
}, async (request, reply) => {
const { from, to, text } = request.body;
try {
const result = await translate(text, from, to);
return { result };
} catch (error) {
reply.code(500).send({
error: 'TranslationError',
message: error.message
});
}
});
// 批量翻译API
fastify.post('/translate/batch', {
preHandler: options.authenticate,
schema: {
body: {
type: 'object',
required: ['from', 'to', 'texts'],
properties: {
from: { type: 'string' },
to: { type: 'string' },
texts: {
type: 'array',
items: { type: 'string' }
}
}
}
}
}, async (request, reply) => {
const { from, to, texts } = request.body;
try {
const results = await batchTranslate(texts, from, to);
return { results };
} catch (error) {
reply.code(500).send({
error: 'BatchTranslationError',
message: error.message
});
}
});
// Google翻译兼容API
fastify.post('/language/translate/v2', {
preHandler: options.authenticate,
schema: {
body: {
type: 'object',
required: ['q', 'source', 'target'],
properties: {
q: { type: 'string' },
source: { type: 'string' },
target: { type: 'string' },
format: { type: 'string', default: 'text' }
}
}
}
}, async (request, reply) => {
const { q, source, target } = request.body;
try {
const translatedText = await translate(q, source, target);
return {
data: {
translations: [
{ translatedText }
]
}
};
} catch (error) {
reply.code(500).send({
error: 'TranslationError',
message: error.message
});
}
});
}
module.exports = registerTranslateRoutes;

48
js/utils/config.js Normal file
View File

@@ -0,0 +1,48 @@
/**
* 配置管理模块
*/
// 默认配置
const defaultConfig = {
port: process.env.PORT || 8989,
host: process.env.HOST || '0.0.0.0',
apiToken: process.env.CORE_API_TOKEN || '',
logLevel: process.env.LOG_LEVEL || 'info'
};
/**
* 获取配置
* @returns {Object} 配置对象
*/
function getConfig() {
return { ...defaultConfig };
}
/**
* 验证API令牌
* @param {string} token 待验证的令牌
* @returns {boolean} 是否有效
*/
function validateToken(token) {
// 如果未设置API令牌则不需要验证
if (!defaultConfig.apiToken) {
return true;
}
return token === defaultConfig.apiToken;
}
/**
* 获取服务器版本
* @returns {string} 版本号
*/
function getVersion() {
const packageJson = require('../../package.json');
return packageJson.version || 'unknown';
}
module.exports = {
getConfig,
validateToken,
getVersion
};

40
js/utils/middleware.js Normal file
View File

@@ -0,0 +1,40 @@
const { validateToken } = require('./config');
/**
* 认证中间件
* @param {Object} request Fastify请求对象
* @param {Object} reply Fastify响应对象
* @param {Function} done 完成回调
*/
function authenticate(request, reply, done) {
const authHeader = request.headers.authorization;
const token = request.query.token;
// 检查Authorization头或URL中的token参数
if (validateToken(authHeader) || validateToken(token)) {
done();
} else {
reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or missing API token' });
}
}
/**
* 错误处理中间件
* @param {Error} error 错误对象
* @param {Object} request Fastify请求对象
* @param {Object} reply Fastify响应对象
*/
function errorHandler(error, request, reply) {
console.error(`Error processing request: ${error.message}`);
// 返回适当的错误响应
reply.code(error.statusCode || 500).send({
error: error.name || 'InternalServerError',
message: error.message || 'An unknown error occurred'
});
}
module.exports = {
authenticate,
errorHandler
};

82
js/utils/translator.js Normal file
View File

@@ -0,0 +1,82 @@
const Translator = require("@mtran/core");
// 缓存已加载的模型
const loadedModels = new Set();
/**
* 获取支持的语言列表
* @returns {Array} 支持的语言列表
*/
function getSupportedLanguages() {
return Translator.GetSupportLanguages();
}
/**
* 预加载翻译模型
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<void>}
*/
async function preloadModel(from, to) {
const modelKey = `${from}_${to}`;
if (!loadedModels.has(modelKey)) {
await Translator.Preload(from, to);
loadedModels.add(modelKey);
console.log(`Successfully loaded model for language pair: ${modelKey}`);
}
}
/**
* 翻译文本
* @param {string} text 要翻译的文本
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<string>} 翻译结果
*/
async function translate(text, from, to) {
// 如果模型未加载,先加载模型
await preloadModel(from, to);
return Translator.Translate(text, from, to);
}
/**
* 批量翻译文本
* @param {string[]} texts 要翻译的文本数组
* @param {string} from 源语言
* @param {string} to 目标语言
* @returns {Promise<string[]>} 翻译结果数组
*/
async function batchTranslate(texts, from, to) {
// 如果模型未加载,先加载模型
await preloadModel(from, to);
// 并行处理翻译请求
const promises = texts.map(text => Translator.Translate(text, from, to));
return Promise.all(promises);
}
/**
* 关闭翻译引擎
* @returns {Promise<void>}
*/
async function shutdown() {
await Translator.Shutdown();
console.log("Translation engine shutdown complete");
}
/**
* 获取已加载的模型列表
* @returns {string[]} 已加载的模型列表
*/
function getLoadedModels() {
return Array.from(loadedModels);
}
module.exports = {
getSupportedLanguages,
preloadModel,
translate,
batchTranslate,
shutdown,
getLoadedModels
};

View File

@@ -3,9 +3,9 @@
"homepage": "https://github.com/xxnuo",
"version": "3.0.0",
"type": "commonjs",
"main": "dist/mts.js",
"main": "js/mts.js",
"bin": {
"mt": "dist/mts.js"
"mt": "js/mts.js"
},
"keywords": [
"translation",
@@ -21,6 +21,9 @@
"node": ">=18.0.0"
},
"dependencies": {
"@mtran/core": "file:packages/mtran-core.tgz"
"@fastify/cors": "^11.0.1",
"@mtran/core": "file:packages/mtran-core.tgz",
"fastify": "^5.4.0",
"pino-pretty": "^13.0.0"
}
}

25
start.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
# 翻译服务器启动脚本
# 获取脚本所在目录的绝对路径
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
# 切换到脚本所在目录
cd "$SCRIPT_DIR" || exit 1
# 检查是否设置了环境变量
if [ -z "$PORT" ]; then
export PORT=8989
fi
if [ -z "$HOST" ]; then
export HOST=0.0.0.0
fi
# 启动服务
echo "Starting MTranServer..."
node js/mts.js
# 脚本结束
exit 0

36
test.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/sh
# 测试运行脚本
# 获取脚本所在目录的绝对路径
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
# 切换到脚本所在目录
cd "$SCRIPT_DIR" || exit 1
# 设置环境变量
export HOST=${HOST:-localhost}
export PORT=${PORT:-8989}
export CORE_API_TOKEN=${CORE_API_TOKEN:-}
# 显示测试环境
echo "测试环境:"
echo "HOST: $HOST"
echo "PORT: $PORT"
echo "TOKEN: ${CORE_API_TOKEN:-(未设置)}"
echo ""
# 运行测试
echo "=== 运行核心API测试 ==="
node tests/core-api.js
echo ""
echo "=== 运行翻译API测试 ==="
node tests/translate-api.js
echo ""
echo "=== 运行翻译插件兼容API测试 ==="
node tests/plugin-api.js
echo ""
echo "所有测试完成!"

184
tests/core-api.js Executable file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/env node
/**
* 测试核心API
* 包括版本、健康检查、心跳检查和模型列表API
*/
const http = require('http');
// 配置
const config = {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8989,
token: process.env.CORE_API_TOKEN || ''
};
// 测试版本API
function testVersion() {
console.log('测试版本API...');
const options = {
hostname: config.host,
port: config.port,
path: '/version',
method: 'GET'
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${data}`);
console.log('版本API测试完成\n');
// 测试下一个API
testHealth();
});
});
req.on('error', (error) => {
console.error(`版本API测试出错: ${error.message}`);
});
req.end();
}
// 测试健康检查API
function testHealth() {
console.log('测试健康检查API...');
const options = {
hostname: config.host,
port: config.port,
path: '/health',
method: 'GET'
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${data}`);
console.log('健康检查API测试完成\n');
// 测试下一个API
testHeartbeat();
});
});
req.on('error', (error) => {
console.error(`健康检查API测试出错: ${error.message}`);
});
req.end();
}
// 测试心跳检查API
function testHeartbeat() {
console.log('测试心跳检查API...');
const options = {
hostname: config.host,
port: config.port,
path: '/__heartbeat__',
method: 'GET'
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${data}`);
console.log('心跳检查API测试完成\n');
// 测试下一个API
testLBHeartbeat();
});
});
req.on('error', (error) => {
console.error(`心跳检查API测试出错: ${error.message}`);
});
req.end();
}
// 测试负载均衡心跳检查API
function testLBHeartbeat() {
console.log('测试负载均衡心跳检查API...');
const options = {
hostname: config.host,
port: config.port,
path: '/__lbheartbeat__',
method: 'GET'
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${data}`);
console.log('负载均衡心跳检查API测试完成\n');
// 测试下一个API
testModels();
});
});
req.on('error', (error) => {
console.error(`负载均衡心跳检查API测试出错: ${error.message}`);
});
req.end();
}
// 测试模型列表API
function testModels() {
console.log('测试模型列表API...');
const options = {
hostname: config.host,
port: config.port,
path: '/models',
method: 'GET',
headers: {}
};
// 如果有token添加到请求头
if (config.token) {
options.headers['Authorization'] = config.token;
}
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${data}`);
console.log('模型列表API测试完成\n');
console.log('所有核心API测试完成');
});
});
req.on('error', (error) => {
console.error(`模型列表API测试出错: ${error.message}`);
});
req.end();
}
// 开始测试
console.log('开始测试核心API...\n');
testVersion();

241
tests/plugin-api.js Executable file
View File

@@ -0,0 +1,241 @@
#!/usr/bin/env node
/**
* 测试翻译插件兼容API
* 包括沉浸式翻译、简约翻译和划词翻译API
*/
const http = require('http');
// 配置
const config = {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8989,
token: process.env.CORE_API_TOKEN || ''
};
// 测试沉浸式翻译API
function testImmeTranslate() {
console.log('测试沉浸式翻译API...');
const tokenParam = config.token ? `?token=${config.token}` : '';
const options = {
hostname: config.host,
port: config.port,
path: `/imme${tokenParam}`,
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
const data = JSON.stringify({
source_lang: 'en',
target_lang: 'zh-Hans',
text: 'Hello, world!'
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('沉浸式翻译API测试完成\n');
// 测试批量翻译
testImmeBatchTranslate();
});
});
req.on('error', (error) => {
console.error(`沉浸式翻译API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 测试沉浸式翻译批量API
function testImmeBatchTranslate() {
console.log('测试沉浸式翻译批量API...');
const tokenParam = config.token ? `?token=${config.token}` : '';
const options = {
hostname: config.host,
port: config.port,
path: `/imme${tokenParam}`,
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
const data = JSON.stringify({
source_lang: 'en',
target_lang: 'zh-Hans',
texts: ['Hello, world!', 'How are you?']
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('沉浸式翻译批量API测试完成\n');
// 测试下一个API
testKissTranslate();
});
});
req.on('error', (error) => {
console.error(`沉浸式翻译批量API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 测试简约翻译API
function testKissTranslate() {
console.log('测试简约翻译API...');
const options = {
hostname: config.host,
port: config.port,
path: '/kiss',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
// 如果有token添加到请求头
if (config.token) {
options.headers['Key'] = config.token;
}
const data = JSON.stringify({
from: 'en',
to: 'zh-Hans',
text: 'Hello, world!'
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('简约翻译API测试完成\n');
// 测试批量翻译
testKissBatchTranslate();
});
});
req.on('error', (error) => {
console.error(`简约翻译API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 测试简约翻译批量API
function testKissBatchTranslate() {
console.log('测试简约翻译批量API...');
const options = {
hostname: config.host,
port: config.port,
path: '/kiss',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
// 如果有token添加到请求头
if (config.token) {
options.headers['Key'] = config.token;
}
const data = JSON.stringify({
from: 'en',
to: 'zh-Hans',
texts: ['Hello, world!', 'How are you?']
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('简约翻译批量API测试完成\n');
// 测试下一个API
testHcfyTranslate();
});
});
req.on('error', (error) => {
console.error(`简约翻译批量API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 测试划词翻译API
function testHcfyTranslate() {
console.log('测试划词翻译API...');
const tokenParam = config.token ? `?token=${config.token}` : '';
const options = {
hostname: config.host,
port: config.port,
path: `/hcfy${tokenParam}`,
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
const data = JSON.stringify({
text: 'Hello, world!',
from: 'en',
to: 'zh-Hans'
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('划词翻译API测试完成\n');
console.log('所有翻译插件兼容API测试完成');
});
});
req.on('error', (error) => {
console.error(`划词翻译API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 开始测试
console.log('开始测试翻译插件兼容API...\n');
testImmeTranslate();

160
tests/translate-api.js Executable file
View File

@@ -0,0 +1,160 @@
#!/usr/bin/env node
/**
* 测试翻译API
* 包括普通翻译、批量翻译和Google翻译兼容API
*/
const http = require('http');
// 配置
const config = {
host: process.env.HOST || 'localhost',
port: process.env.PORT || 8989,
token: process.env.CORE_API_TOKEN || ''
};
// 测试普通翻译API
function testTranslate() {
console.log('测试普通翻译API...');
const options = {
hostname: config.host,
port: config.port,
path: '/translate',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
// 如果有token添加到请求头
if (config.token) {
options.headers['Authorization'] = config.token;
}
const data = JSON.stringify({
from: 'en',
to: 'zh-Hans',
text: 'Hello, world!'
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('普通翻译API测试完成\n');
// 测试下一个API
testBatchTranslate();
});
});
req.on('error', (error) => {
console.error(`普通翻译API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 测试批量翻译API
function testBatchTranslate() {
console.log('测试批量翻译API...');
const options = {
hostname: config.host,
port: config.port,
path: '/translate/batch',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
// 如果有token添加到请求头
if (config.token) {
options.headers['Authorization'] = config.token;
}
const data = JSON.stringify({
from: 'en',
to: 'zh-Hans',
texts: ['Hello, world!', 'How are you?']
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('批量翻译API测试完成\n');
// 测试下一个API
testGoogleTranslate();
});
});
req.on('error', (error) => {
console.error(`批量翻译API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 测试Google翻译兼容API
function testGoogleTranslate() {
console.log('测试Google翻译兼容API...');
const options = {
hostname: config.host,
port: config.port,
path: '/language/translate/v2',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
// 如果有token添加到请求头
if (config.token) {
options.headers['Authorization'] = config.token;
}
const data = JSON.stringify({
q: 'The Great Pyramid of Giza',
source: 'en',
target: 'zh-Hans',
format: 'text'
});
const req = http.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
console.log(`状态码: ${res.statusCode}`);
console.log(`响应数据: ${responseData}`);
console.log('Google翻译兼容API测试完成\n');
console.log('所有翻译API测试完成');
});
});
req.on('error', (error) => {
console.error(`Google翻译兼容API测试出错: ${error.message}`);
});
req.write(data);
req.end();
}
// 开始测试
console.log('开始测试翻译API...\n');
testTranslate();