use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
pub type TerminologyMap = BTreeMap<String, String>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TerminologyEntry {
pub source: String,
pub target: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GlossaryEntry {
pub source: String,
pub target: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct TranslationCue {
pub id: String,
pub text: String,
}
#[derive(Debug, Clone)]
pub struct TranslationRequest {
pub target_language: String,
pub source_language: Option<String>,
pub glossary_text: Option<String>,
pub context: Option<String>,
pub glossary_entries: Vec<GlossaryEntry>,
}
#[derive(Debug, Clone)]
pub struct TranslationBatch {
pub cues: Vec<TranslationCue>,
}
#[derive(Debug, Clone, Default)]
pub struct TranslationOutcome {
pub effective_terminology: TerminologyMap,
pub translated_cue_count: usize,
pub batch_count: usize,
}
#[derive(Debug, Clone)]
pub struct TranslationResult {
pub subtitle: crate::core::formats::Subtitle,
pub outcome: TranslationOutcome,
}
pub fn merge_terminology(generated: TerminologyMap, glossary: &[GlossaryEntry]) -> TerminologyMap {
let mut merged = generated;
for entry in glossary {
let source = entry.source.trim().to_string();
let target = entry.target.trim().to_string();
if source.is_empty() || target.is_empty() {
continue;
}
merged.insert(source, target);
}
merged
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn glossary_overrides_generated_terms() {
let mut generated = TerminologyMap::new();
generated.insert("Alice".to_string(), "愛麗絲".to_string());
generated.insert("Bob".to_string(), "鮑伯".to_string());
let glossary = vec![GlossaryEntry {
source: "Alice".to_string(),
target: "艾莉絲".to_string(),
}];
let merged = merge_terminology(generated, &glossary);
assert_eq!(merged.get("Alice").unwrap(), "艾莉絲");
assert_eq!(merged.get("Bob").unwrap(), "鮑伯");
}
#[test]
fn empty_glossary_entries_are_ignored() {
let mut generated = TerminologyMap::new();
generated.insert("Alice".to_string(), "愛麗絲".to_string());
let glossary = vec![GlossaryEntry {
source: " ".to_string(),
target: "x".to_string(),
}];
let merged = merge_terminology(generated, &glossary);
assert_eq!(merged.len(), 1);
}
}