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 實驗室 著作權所有 &copy; 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">&times;</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">&times;</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>