Spaces:
Sleeping
Sleeping
File size: 22,600 Bytes
bc7bdb7 39ff86d 5e981a4 39ff86d bc7bdb7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | <!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ILRDF 太魯閣語 AI 翻譯助手 | Web 旗艦版</title>
<link rel="stylesheet" href="/static/style.css?v=20260727_3">
<!-- FontAwesome icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-4M6KQ8KSY5"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-4M6KQ8KSY5');
</script>
</head>
<body>
<!-- 導覽列 Navbar -->
<nav class="navbar">
<div class="brand">
<i class="fa-solid fa-cube brand-icon"></i>
<span class="brand-title">ILRDF 太魯閣語 AI 翻譯助手</span>
<span class="brand-tag"><i class="fa-solid fa-bolt"></i> Web 旗艦版</span>
</div>
<div class="tribe-selector-container">
<span class="tribe-selector-label"><i class="fa-solid fa-globe"></i> 選擇目標族語:</span>
<select id="tribeSelect" class="tribe-select" disabled>
<option value="太魯閣語" selected>太魯閣語</option>
</select>
</div>
</nav>
<!-- 主應用內容 App Container -->
<div class="app-container">
<!-- 功能分頁頁籤 Header Tabs -->
<div class="tabs-header">
<button class="tab-btn active" data-tab="text-tab">
<i class="fa-solid fa-language"></i> 文字翻譯
</button>
<button class="tab-btn" data-tab="audio-tab">
<i class="fa-solid fa-microphone-lines"></i> 語音辨識與聽寫
</button>
<button class="tab-btn" data-tab="image-tab">
<i class="fa-solid fa-image"></i> 圖片 OCR 翻譯
</button>
<button class="tab-btn" data-tab="video-tab">
<i class="fa-solid fa-file-video"></i> 影片音軌翻譯
</button>
<button class="tab-btn" data-tab="feedback-tab">
<i class="fa-solid fa-comment-dots"></i> 建議與報錯
</button>
</div>
<!-- 1. 文字翻譯面板 (Text Tab) -->
<div id="text-tab" class="tab-content active">
<div class="glass-card">
<!-- 翻譯方向模式選單 -->
<div class="direction-selector-bar">
<span class="direction-label"><i class="fa-solid fa-right-left"></i> 翻譯方向模式:</span>
<div class="direction-options">
<button class="dir-btn active" data-mode="zh_to_native">
華語 ➔ <span class="current-tribe-label">太魯閣語</span> (華語翻族語)
</button>
<button class="dir-btn" data-mode="native_to_zh">
<span class="current-tribe-label">太魯閣語</span> ➔ 華語 (族語翻華語)
</button>
<button class="dir-btn" data-mode="auto">
⚡ 自動判斷
</button>
</div>
</div>
<div class="translation-grid">
<!-- 輸入區 -->
<div class="input-box-wrapper">
<div class="box-header">
<span id="inputBoxTitle"><i class="fa-regular fa-pen-to-square"></i> 原文輸入 (華語)</span>
<span id="charCount">0 字</span>
</div>
<textarea id="textInput" class="text-area-styled" placeholder="請在此輸入華語,將自動翻譯為【太魯閣語】..."></textarea>
</div>
<!-- 輸出區 -->
<div class="output-box-wrapper">
<div class="box-header">
<span><i class="fa-solid fa-wand-magic-sparkles"></i> AI 翻譯結果 (<span class="current-tribe-label">太魯閣語</span>)</span>
<span id="speedTimer"><i class="fa-regular fa-clock"></i> 耗時: -</span>
</div>
<div id="textOutput" class="output-styled empty">
翻譯結果將顯示於此...
</div>
</div>
</div>
<!-- 動作按鈕列 -->
<div class="btn-group">
<button id="translateBtn" class="btn btn-primary">
<i class="fa-solid fa-paper-plane"></i> 開始極速翻譯
</button>
<button id="swapDirectionBtn" class="btn btn-secondary" title="將翻譯結果與原文互相對調並重新翻譯">
<i class="fa-solid fa-arrows-rotate"></i> ⇄ 雙向對調 (換向)
</button>
<button id="ttsBtn" class="btn btn-secondary" disabled>
<i class="fa-solid fa-volume-high"></i> 🔊 聽發音
</button>
<button id="deepTranslateBtn" class="btn btn-secondary" disabled>
<i class="fa-solid fa-brain"></i> 🧠 深度文化潤飾
</button>
<button id="copyBtn" class="btn btn-secondary" disabled>
<i class="fa-regular fa-copy"></i> 複製結果
</button>
</div>
<!-- 信心值與狀態列 -->
<div class="meta-bar">
<div id="confidenceBadge" class="badge-confidence" style="display: none;">
<i class="fa-solid fa-shield-halved"></i> 信心值:<span id="confidenceLevel">高</span> (<span id="confidenceDesc">一般生活簡單句</span>)
</div>
<div style="font-size: 0.85rem; color: var(--text-dim);">
● NLLB 深度學術對齊引擎 + Gemini 文化語意雷達
</div>
</div>
</div>
<!-- 常用單字速查快卡 Section -->
<div class="phrasebook-section">
<div class="section-title">
<i class="fa-solid fa-fire-flame-curved" style="color: var(--accent-gold);"></i> 常用 10 句日常生活速查句卡 (點擊代入翻譯)
</div>
<div class="phrases-grid" id="phrasesGrid">
<!-- JavaScript 動態帶入 -->
</div>
</div>
<!-- 長句測試 Section -->
<div class="phrasebook-section" style="margin-top: 1.5rem;">
<div class="section-title">
<i class="fa-solid fa-book-open-reader" style="color: var(--primary-cyan);"></i> 雙語長句測試區 (點擊代入)
</div>
<div style="display: flex; flex-direction: column; gap: 10px;">
<div class="phrase-card" id="longPhraseZh" style="text-align: left; padding: 15px; width: 100%; max-width: none;">
<div class="phrase-zh" style="font-size: 1rem; line-height: 1.4;">很久以前,天地間只有黑暗沒有白天,人類的生活很辛苦而且沒有發展。就這樣以松樹的木片點火當作燈來做家事及到田間工作。</div>
<div class="phrase-desc" style="margin-top: 5px;">華語長句測試</div>
</div>
<div class="phrase-card" id="longPhraseNative" style="text-align: left; padding: 15px; width: 100%; max-width: none;">
<div class="phrase-zh" style="font-size: 1rem; line-height: 1.4;">Mqaras ku bi qmita sunan, Lituk ka hangan mu, ima ka hangan su? Emptgsa ku ka yaku, ga ku tmgsa kari Truku. Gaga su qmpah qpahun manu?</div>
<div class="phrase-desc" style="margin-top: 5px;">太魯閣語長句測試</div>
</div>
</div>
</div>
<!-- 本地歷史紀錄 Section -->
<div class="phrasebook-section" style="margin-top: 2rem;">
<div class="section-title" style="display: flex; align-items: center; justify-content: space-between;">
<span><i class="fa-solid fa-clock-rotate-left"></i> 最近翻譯歷史紀錄</span>
<button id="clearHistoryBtn" onclick="clearHistory()" title="清除全部歷史" style="background: rgba(255,80,80,0.15); border: 1px solid rgba(255,80,80,0.4); color: #ff6b6b; border-radius: 6px; padding: 4px 12px; font-size: 0.78rem; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; gap: 6px;" onmouseover="this.style.background='rgba(255,80,80,0.35)'" onmouseout="this.style.background='rgba(255,80,80,0.15)'">
<i class="fa-solid fa-trash-can"></i> 清除歷史
</button>
</div>
<div class="history-list" id="historyList">
<div style="color: var(--text-dim); font-size: 0.85rem; padding: 10px;">尚未有翻譯紀錄。</div>
</div>
</div>
</div>
<!-- 2. 語音聽寫面板 (Audio Tab) -->
<div id="audio-tab" class="tab-content">
<div class="glass-card">
<div class="section-title"><i class="fa-solid fa-microphone"></i> 麥克風線上錄音或語音檔上傳</div>
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">
錄下或上傳族語語音 (WAV / MP3 / M4A),原語會 ASR 辨識引擎將自動轉換為文字並翻譯成中文與目標族語。
</p>
<div class="btn-group" style="margin-bottom: 1.5rem;">
<button id="startRecordBtn" class="btn btn-primary">
<i class="fa-solid fa-circle" style="color: #ff4d4d;"></i> 開始錄音
</button>
<button id="stopRecordBtn" class="btn btn-secondary" disabled>
<i class="fa-solid fa-square"></i> 停止錄音並辨識
</button>
</div>
<div id="recordingStatus" style="color: var(--primary-cyan); font-weight: 600; margin-bottom: 1rem; display: none;">
<i class="fa-solid fa-wave-square"></i> 錄音中... 請對麥克風說話
</div>
<div class="dropzone" id="audioDropzone">
<i class="fa-solid fa-cloud-arrow-up dropzone-icon"></i>
<p style="font-weight: 600;">拖曳語音檔案至此處,或點擊選擇檔案</p>
<p style="font-size: 0.8rem; color: var(--text-dim); margin-top: 6px;">支援 .wav, .mp3, .m4a 格式</p>
<input type="file" id="audioFileInput" accept="audio/*" style="display: none;">
</div>
<div id="audioResult" style="margin-top: 1.5rem; display: none;">
<div class="box-header"><span>ASR 語音辨識與翻譯結果</span></div>
<div id="audioOutput" class="output-styled" style="height: auto; min-height: 100px;"></div>
</div>
</div>
</div>
<!-- 3. 圖片 OCR 翻譯面板 (Image Tab) -->
<div id="image-tab" class="tab-content">
<div class="glass-card">
<div class="section-title"><i class="fa-solid fa-camera"></i> 圖片視聽 Vision 多模態 OCR 翻譯</div>
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">
上傳包含文字的圖片(指標、告示牌、課本圖片),Gemini 視覺模型將自動提取內文並進行族語翻譯。
</p>
<div class="dropzone" id="imageDropzone">
<i class="fa-solid fa-file-image dropzone-icon"></i>
<p style="font-weight: 600;">拖曳圖片檔案至此處,或點擊上傳</p>
<p style="font-size: 0.8rem; color: var(--text-dim); margin-top: 6px;">支援 .jpg, .png, .jpeg 格式</p>
<input type="file" id="imageFileInput" accept="image/*" style="display: none;">
</div>
<div id="imagePreviewContainer" style="margin-top: 15px; display: none; text-align: center;">
<img id="imagePreview" src="" alt="Image Preview" style="max-width: 100%; max-height: 300px; border-radius: 8px; border: 1px solid var(--border-color); box-shadow: 0 4px 12px rgba(0,0,0,0.3);">
</div>
<div id="imageResult" style="margin-top: 1.5rem; display: none;">
<div class="box-header" style="display: flex; justify-content: space-between; align-items: center;">
<span>圖片文字辨識與翻譯清單</span>
<div class="action-buttons" style="display: flex; gap: 8px;">
<button id="copyOcrBtn" class="btn btn-primary" style="padding: 4px 12px; font-size: 0.85rem;"><i class="fa-solid fa-copy"></i> 複製全部</button>
<button id="downloadOcrWordBtn" class="btn btn-secondary" style="padding: 4px 12px; font-size: 0.85rem;"><i class="fa-solid fa-file-word"></i> 下載 WORD</button>
</div>
</div>
<div id="imageOutput" style="display: flex; flex-direction: column; gap: 10px; margin-top: 10px;"></div>
</div>
</div>
</div>
<!-- 4. 影片音軌翻譯面板 (Video Tab) -->
<div id="video-tab" class="tab-content">
<div class="glass-card">
<div class="section-title"><i class="fa-solid fa-film"></i> 影片音軌提取與逐字稿翻譯</div>
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">
上傳族語或中文對話影片,後端以 MoviePy 自動提取音軌,並執行 ASR 與文字翻譯。
</p>
<div class="dropzone" id="videoDropzone">
<i class="fa-solid fa-file-video dropzone-icon"></i>
<p style="font-weight: 600;">拖曳影片檔案至此處,或點擊上傳</p>
<p style="font-size: 0.8rem; color: var(--text-dim); margin-top: 6px;">支援 .mp4, .mov, .avi 格式</p>
<input type="file" id="videoFileInput" accept="video/*" style="display: none;">
</div>
<div id="videoPreviewContainer" style="margin-top: 15px; display: none; text-align: center;">
<video id="videoPreview" controls style="max-width: 100%; max-height: 400px; border-radius: 8px; border: 1px solid var(--border-color); box-shadow: 0 4px 12px rgba(0,0,0,0.3);"></video>
</div>
<div id="videoResult" style="margin-top: 1.5rem; display: none;">
<div class="box-header" style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;">
<span>影片字幕與翻譯對照</span>
<div class="action-buttons" style="display: flex; gap: 8px; flex-wrap: wrap;">
<button id="downloadAudioBtn" class="btn btn-secondary" style="padding: 4px 12px; font-size: 0.85rem;"><i class="fa-solid fa-music"></i> 下載純音軌</button>
<button id="downloadSrtBtn" class="btn btn-secondary" style="padding: 4px 12px; font-size: 0.85rem;"><i class="fa-solid fa-closed-captioning"></i> 下載 SRT</button>
<button id="copyVideoBtn" class="btn btn-primary" style="padding: 4px 12px; font-size: 0.85rem;"><i class="fa-solid fa-copy"></i> 複製全部</button>
<button id="downloadVideoWordBtn" class="btn btn-secondary" style="padding: 4px 12px; font-size: 0.85rem;"><i class="fa-solid fa-file-word"></i> 下載 WORD</button>
</div>
</div>
<div id="videoOutput" class="output-styled" style="height: auto; min-height: 120px;"></div>
</div>
</div>
</div>
<!-- 5. 報錯與建議面板 (Feedback Tab) -->
<div id="feedback-tab" class="tab-content">
<div class="glass-card">
<div class="section-title"><i class="fa-solid fa-paper-plane"></i> 系統回饋與翻譯報錯專區</div>
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">
發現翻譯不準確或有修改建議?歡迎在此填寫表單,資訊將自動透過加密郵件發送予語料維護團隊。
</p>
<div style="display: flex; flex-direction: column; gap: 1rem; max-width: 600px;">
<div>
<label style="font-size: 0.9rem; color: var(--text-muted);">您的暱稱:</label>
<input type="text" id="fbNickname" class="text-area-styled" style="height: 45px;" placeholder="例:張小明">
</div>
<div>
<label style="font-size: 0.9rem; color: var(--text-muted);">回饋內容 / 建議修飾字句:</label>
<textarea id="fbComment" class="text-area-styled" style="height: 100px;" placeholder="請詳細說明您發生的問題或希望補充的族語單詞..."></textarea>
</div>
<button id="sendFeedbackBtn" class="btn btn-primary" style="width: 200px;">
<i class="fa-solid fa-envelope"></i> 送出意見回饋
</button>
</div>
</div>
</div>
</div>
<!-- 頁尾 Footer -->
<footer class="footer">
<p>財團法人原住民族語言研究發展基金會 (ILRDF) AI 實驗室 著作權所有 © 2026</p>
<p style="margin-top: 4px; color: var(--text-dim);">Powered by FastAPI, Gradio Client, NLLB-200 & Google Gemini 3</p>
</footer>
<!-- 深度文化潤飾 Modal -->
<div id="deepTranslateModal" class="modal-overlay" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>🧠 深度文化潤飾結果</h3>
<button class="close-btn" id="closeModalBtn">×</button>
</div>
<div class="modal-body" id="deepTranslateResultBody" style="white-space: pre-wrap; max-height: 60vh; overflow-y: auto; padding: 20px; font-size: 1.05rem; line-height: 1.6; color: var(--text-bright);">
</div>
<div class="modal-footer" style="display: flex; gap: 10px; justify-content: space-between; align-items: center; padding: 15px 20px; border-top: 1px solid rgba(255,255,255,0.1); flex-wrap: wrap;">
<button id="changeApiKeyBtn" class="btn" style="background: rgba(245, 158, 11, 0.18); color: #fbbf24; border: 1px solid rgba(245, 158, 11, 0.5); padding: 8px 16px; border-radius: 8px; font-size: 0.95rem; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s ease;">
<i class="fa-solid fa-key"></i> 🔑 更換 API Key
</button>
<div style="display: flex; gap: 10px;">
<button id="copyDeepResultBtn" class="btn btn-secondary"><i class="fa-regular fa-copy"></i> 複製</button>
<button id="downloadWordBtn" class="btn btn-primary"><i class="fa-solid fa-file-word"></i> 下載 WORD</button>
</div>
</div>
</div>
</div>
<!-- 🔑 Gemini API Key 輸入 Modal -->
<div id="apiKeyModal" class="modal-overlay" style="display: none;">
<div class="modal-content" style="max-width: 500px;">
<div class="modal-header">
<h3>🔑 輸入 Google Gemini API Key</h3>
<button class="close-btn" id="closeApiKeyModalBtn">×</button>
</div>
<div class="modal-body" style="padding: 20px;">
<p style="color: var(--text-muted); font-size: 0.95rem; margin-bottom: 15px; line-height: 1.5;">
「深度文化潤飾」功能需使用 Google Gemini AI 進行多層次語法與文化對齊。請輸入您的 API Key 繼續使用:
</p>
<div style="position: relative; margin-bottom: 12px;">
<input type="password" id="geminiApiKeyInput" placeholder="請在此貼上您的 API Key (例: AIzaSy...)"
style="width: 100%; padding: 12px 14px; border-radius: 8px; border: 1px solid var(--border-glow); background: rgba(0,0,0,0.3); color: #fff; font-size: 1rem; box-sizing: border-box;" />
</div>
<div style="font-size: 0.85rem; color: var(--text-dim); display: flex; justify-content: space-between; align-items: center; margin-top: 10px;">
<a href="https://aistudio.google.com/app/apikey" target="_blank" style="color: var(--primary-cyan); text-decoration: underline;">
👉 按此免費申領 Gemini API Key
</a>
<label style="cursor: pointer; display: flex; align-items: center; gap: 5px;">
<input type="checkbox" id="rememberApiKeyCheckbox" checked /> 記住金鑰
</label>
</div>
</div>
<div class="modal-footer" style="display: flex; gap: 10px; justify-content: flex-end; padding: 15px; border-top: 1px solid rgba(255,255,255,0.1);">
<button id="cancelApiKeyBtn" class="btn btn-secondary">取消</button>
<button id="confirmApiKeyBtn" class="btn btn-primary"><i class="fa-solid fa-check"></i> 確認並開始潤飾</button>
</div>
</div>
</div>
<!-- JavaScript 腳本 -->
<script src="/static/script.js?v=20260727_4"></script>
</body>
</html>
|