Türkçe çeviri özelliği eklendi (GLM 4.6 ile çeviri yapılıyor)

This commit is contained in:
2025-11-16 23:02:15 +03:00
parent cd0b59945b
commit daf39e35c0
9 changed files with 446 additions and 8 deletions

View File

@@ -0,0 +1,142 @@
const GLM_API_KEY = process.env.ZAI_GLM_API_KEY || process.env.ANTHROPIC_API_KEY;
const GLM_MODEL = process.env.ANTHROPIC_MODEL || process.env.ZAI_GLM_MODEL || 'glm-4.6';
const resolveEndpoint = () => {
const base =
process.env.ANTHROPIC_BASE_URL || process.env.ZAI_GLM_API_URL || 'https://api.z.ai/api/anthropic';
const normalized = base.replace(/\/$/, '');
if (/\/messages$/.test(normalized)) {
return normalized;
}
if (/\/v\d+$/.test(normalized)) {
return `${normalized}/messages`;
}
if (/\/v\d+\/.+/.test(normalized)) {
return normalized;
}
return `${normalized}/v1/messages`;
};
const GLM_API_URL = resolveEndpoint();
const IS_ANTHROPIC_STYLE = /anthropic/.test(GLM_API_URL);
const SYSTEM_PROMPT =
'You are a professional localization editor. Translate any given English or mixed-language text into fluent, publication-ready Turkish. Keep the original meaning, respect formatting, and avoid adding explanations.';
const extractContent = (payload) => {
if (!payload) return '';
if (Array.isArray(payload.content)) {
return payload.content
.map((item) => {
if (!item) return '';
if (typeof item === 'string') return item;
if (Array.isArray(item.text)) {
return item.text.map((inner) => inner?.text || inner || '').join('');
}
if (typeof item.text === 'string') return item.text;
if (Array.isArray(item.content)) {
return item.content
.map((inner) => (typeof inner === 'string' ? inner : inner?.text || ''))
.join('');
}
return '';
})
.filter(Boolean)
.join('\n')
.trim();
}
if (Array.isArray(payload.output)) {
return payload.output
.map((item) => item.content || item.text || '')
.filter(Boolean)
.join('')
.trim();
}
if (Array.isArray(payload.choices) && payload.choices.length > 0) {
const choice = payload.choices[0];
if (choice.message?.content) {
if (Array.isArray(choice.message.content)) {
return choice.message.content
.map((c) => (typeof c === 'string' ? c : c.text || ''))
.join('')
.trim();
}
return `${choice.message.content}`.trim();
}
if (choice.text) {
return `${choice.text}`.trim();
}
}
if (payload.data?.output_text?.length) {
return payload.data.output_text.join('\n').trim();
}
if (typeof payload.content === 'string') {
return payload.content.trim();
}
if (typeof payload.text === 'string') {
return payload.text.trim();
}
return '';
};
export const translateWithGlm = async (text) => {
if (!GLM_API_KEY) {
throw new Error('ZAI_GLM_API_KEY veya ANTHROPIC_API_KEY tanımlı değil.');
}
const prompt =
`Aşağıdaki metni Türkçe'ye çevir. Yalnızca çeviriyi döndür:\n\n"""${text}"""`;
let body;
if (IS_ANTHROPIC_STYLE) {
body = {
model: GLM_MODEL,
max_tokens: 1024,
temperature: 0.1,
system: SYSTEM_PROMPT,
messages: [
{
role: 'user',
content: [{ type: 'text', text: prompt }],
},
],
};
} else {
body = {
model: GLM_MODEL,
max_tokens: 1024,
temperature: 0.1,
messages: [
{ role: 'system', content: SYSTEM_PROMPT },
{ role: 'user', content: prompt },
],
};
}
const response = await fetch(GLM_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${GLM_API_KEY}`,
...(IS_ANTHROPIC_STYLE && {
'x-api-key': GLM_API_KEY,
'anthropic-version': process.env.ANTHROPIC_VERSION || '2023-06-01',
}),
},
body: JSON.stringify(body),
});
const payload = await response.json().catch(() => ({}));
if (!response.ok) {
const message =
payload?.error?.message ||
payload?.msg ||
`GLM isteği başarısız oldu (status: ${response.status})`;
throw new Error(message);
}
const translated = extractContent(payload);
if (!translated) {
throw new Error('GLM çıktısı boş döndü.');
}
return translated;
};