feat: add document translation via DIFY AI API
Implement document translation feature using DIFY AI API with batch processing: Backend: - Add DIFY client with batch translation support (5000 chars, 20 items per batch) - Add translation service with element extraction and result building - Add translation router with start/status/result/list/delete endpoints - Add translation schemas (TranslationRequest, TranslationStatus, etc.) Frontend: - Enable translation UI in TaskDetailPage - Add translation API methods to apiV2.ts - Add translation types Features: - Batch translation with numbered markers [1], [2], [3]... - Support for text, title, header, footer, paragraph, footnote, table cells - Translation result JSON with statistics (tokens, latency, batch_count) - Background task processing with progress tracking 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,11 @@ import type {
|
||||
DocumentAnalysisResponse,
|
||||
PreprocessingPreviewRequest,
|
||||
PreprocessingPreviewResponse,
|
||||
TranslationRequest,
|
||||
TranslationStartResponse,
|
||||
TranslationStatusResponse,
|
||||
TranslationListResponse,
|
||||
TranslationResult,
|
||||
} from '@/types/apiV2'
|
||||
|
||||
/**
|
||||
@@ -613,6 +618,74 @@ class ApiClientV2 {
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
// ==================== Translation APIs ====================
|
||||
|
||||
/**
|
||||
* Start a translation job
|
||||
*/
|
||||
async startTranslation(taskId: string, request: TranslationRequest): Promise<TranslationStartResponse> {
|
||||
const response = await this.client.post<TranslationStartResponse>(
|
||||
`/translate/${taskId}`,
|
||||
request
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translation status
|
||||
*/
|
||||
async getTranslationStatus(taskId: string): Promise<TranslationStatusResponse> {
|
||||
const response = await this.client.get<TranslationStatusResponse>(
|
||||
`/translate/${taskId}/status`
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translation result
|
||||
*/
|
||||
async getTranslationResult(taskId: string, lang: string): Promise<TranslationResult> {
|
||||
const response = await this.client.get<TranslationResult>(
|
||||
`/translate/${taskId}/result`,
|
||||
{ params: { lang } }
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Download translation result as JSON file
|
||||
*/
|
||||
async downloadTranslation(taskId: string, lang: string): Promise<void> {
|
||||
const response = await this.client.get(`/translate/${taskId}/result`, {
|
||||
params: { lang },
|
||||
responseType: 'blob',
|
||||
})
|
||||
|
||||
const blob = new Blob([response.data], { type: 'application/json' })
|
||||
const link = document.createElement('a')
|
||||
link.href = window.URL.createObjectURL(blob)
|
||||
link.download = `${taskId}_translated_${lang}.json`
|
||||
link.click()
|
||||
window.URL.revokeObjectURL(link.href)
|
||||
}
|
||||
|
||||
/**
|
||||
* List available translations for a task
|
||||
*/
|
||||
async listTranslations(taskId: string): Promise<TranslationListResponse> {
|
||||
const response = await this.client.get<TranslationListResponse>(
|
||||
`/translate/${taskId}/translations`
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a translation
|
||||
*/
|
||||
async deleteTranslation(taskId: string, lang: string): Promise<void> {
|
||||
await this.client.delete(`/translate/${taskId}/translations/${lang}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
|
||||
Reference in New Issue
Block a user