Files
office_translator/frontend/src/lib/api.ts
sepehr 05c5dfcbbb
Some checks failed
Deploy to Homelab / Deploy Wordly to 192.168.1.151 (push) Has been cancelled
Deploy to Homelab / Deploy Monitoring (if configured) (push) Has been cancelled
fix: add frontend/src/lib/ to git (was ignored by /lib/ pattern)
The root .gitignore had `lib/` which matched frontend/src/lib/,
causing Docker build to fail with "Module not found: Can't resolve
'@/lib/utils'" and '@/lib/i18n'.

Changed to `/lib/` so it only ignores the Python lib at repo root.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 15:17:22 +02:00

162 lines
5.2 KiB
TypeScript

import { API_BASE } from "./config";
export interface TranslatedText {
id: string;
translated_text: string;
}
export interface Language {
code: string;
name: string;
flag: string;
}
export interface Provider {
id: string;
name: string;
icon?: string;
description?: string;
mode?: "classic" | "llm";
}
export const languages: Language[] = [
{ code: "fr", name: "Français", flag: "🇫🇷" },
{ code: "en", name: "English", flag: "🇬🇧" },
{ code: "de", name: "Deutsch", flag: "🇩🇪" },
{ code: "es", name: "Español", flag: "🇪🇸" },
{ code: "it", name: "Italiano", flag: "🇮🇹" },
{ code: "pt", name: "Português", flag: "🇵🇹" },
{ code: "nl", name: "Nederlands", flag: "🇳🇱" },
{ code: "ru", name: "Русский", flag: "🇷🇺" },
{ code: "zh", name: "中文", flag: "🇨🇳" },
{ code: "ja", name: "日本語", flag: "🇯🇵" },
{ code: "ko", name: "한국어", flag: "🇰🇷" },
{ code: "ar", name: "العربية", flag: "🇸🇦" },
{ code: "fa", name: "فارسی", flag: "🇮🇷" },
{ code: "hi", name: "हिन्दी", flag: "🇮🇳" },
{ code: "tr", name: "Türkçe", flag: "🇹🇷" },
{ code: "pl", name: "Polski", flag: "🇵🇱" },
{ code: "sv", name: "Svenska", flag: "🇸🇪" },
{ code: "da", name: "Dansk", flag: "🇩🇰" },
{ code: "fi", name: "Suomi", flag: "🇫🇮" },
{ code: "no", name: "Norsk", flag: "🇳🇴" },
{ code: "cs", name: "Čeština", flag: "🇨🇿" },
{ code: "ro", name: "Română", flag: "🇷🇴" },
{ code: "hu", name: "Magyar", flag: "🇭🇺" },
{ code: "el", name: "Ελληνικά", flag: "🇬🇷" },
{ code: "he", name: "עברית", flag: "🇮🇱" },
{ code: "th", name: "ไทย", flag: "🇹🇭" },
{ code: "vi", name: "Tiếng Việt", flag: "🇻🇳" },
{ code: "id", name: "Bahasa Indonesia", flag: "🇮🇩" },
{ code: "uk", name: "Українська", flag: "🇺🇦" },
];
export const providers: Provider[] = [
{ id: "google", name: "Google Translate", description: "Fast translation, 130+ languages" },
{ id: "deepl", name: "DeepL", description: "High-quality neural translation" },
{ id: "openai", name: "OpenAI", description: "GPT-powered context-aware translation", mode: "llm" },
{ id: "ollama", name: "Ollama (Local)", description: "Self-hosted LLM translation", mode: "llm" },
{ id: "openrouter", name: "OpenRouter", description: "Multi-model AI translation", mode: "llm" },
];
export async function translateDocument(params: {
file: File;
targetLanguage: string;
provider: string;
ollamaModel?: string;
translateImages?: boolean;
systemPrompt?: string;
glossary?: string;
libreUrl?: string;
openaiApiKey?: string;
openaiModel?: string;
openrouterApiKey?: string;
openrouterModel?: string;
}): Promise<Blob> {
const formData = new FormData();
formData.append("file", params.file);
formData.append("target_language", params.targetLanguage);
formData.append("provider", params.provider);
if (params.ollamaModel) formData.append("ollama_model", params.ollamaModel);
if (params.translateImages !== undefined)
formData.append("translate_images", String(params.translateImages));
if (params.systemPrompt) formData.append("system_prompt", params.systemPrompt);
if (params.glossary) formData.append("glossary", params.glossary);
if (params.libreUrl) formData.append("libre_url", params.libreUrl);
const token =
typeof window !== "undefined" ? localStorage.getItem("token") : null;
const headers: Record<string, string> = {};
if (token) headers["Authorization"] = `Bearer ${token}`;
const res = await fetch(`${API_BASE}/api/v1/translate`, {
method: "POST",
headers,
body: formData,
});
if (!res.ok) {
let msg = `HTTP ${res.status}`;
try {
const j = await res.json();
msg = j.message || j.error || msg;
} catch {}
throw new Error(msg);
}
return res.blob();
}
export async function extractTextsFromDocument(
file: File,
): Promise<{ texts: Array<{ id: string; text: string }>; session_id: string }> {
const formData = new FormData();
formData.append("file", file);
const token =
typeof window !== "undefined" ? localStorage.getItem("token") : null;
const headers: Record<string, string> = {};
if (token) headers["Authorization"] = `Bearer ${token}`;
const res = await fetch(`${API_BASE}/api/v1/extract`, {
method: "POST",
headers,
body: formData,
});
if (!res.ok) {
throw new Error(`Extraction failed: HTTP ${res.status}`);
}
return res.json();
}
export async function reconstructDocument(
sessionId: string,
translations: TranslatedText[],
targetLanguage: string,
): Promise<Blob> {
const token =
typeof window !== "undefined" ? localStorage.getItem("token") : null;
const headers: Record<string, string> = {
"Content-Type": "application/json",
};
if (token) headers["Authorization"] = `Bearer ${token}`;
const res = await fetch(`${API_BASE}/api/v1/reconstruct`, {
method: "POST",
headers,
body: JSON.stringify({
session_id: sessionId,
translations,
target_language: targetLanguage,
}),
});
if (!res.ok) {
throw new Error(`Reconstruction failed: HTTP ${res.status}`);
}
return res.blob();
}