翻译中显示已经翻译的
Browse files- youtube_sub.js +39 -10
youtube_sub.js
CHANGED
|
@@ -354,7 +354,7 @@ GM_addStyle(`
|
|
| 354 |
<div class="markdown"></div>
|
| 355 |
</div>
|
| 356 |
`;
|
| 357 |
-
const CHUNK_SIZE = 200;
|
| 358 |
|
| 359 |
// Apply main styles
|
| 360 |
GM_addStyle(styles);
|
|
@@ -1133,7 +1133,7 @@ const CHUNK_SIZE = 200;
|
|
| 1133 |
const isActive = lineIndex === newIndex;
|
| 1134 |
|
| 1135 |
line.classList.toggle('active', isActive);
|
| 1136 |
-
if (isActive) {
|
| 1137 |
highlightWords(currentTime, line);
|
| 1138 |
if (lineIndex !== lastActiveIndex) {
|
| 1139 |
line.scrollIntoView({
|
|
@@ -1191,13 +1191,13 @@ const CHUNK_SIZE = 200;
|
|
| 1191 |
|
| 1192 |
async translateInChunks(subtitleData) {
|
| 1193 |
|
| 1194 |
-
|
| 1195 |
// Get video URL as cache key
|
| 1196 |
-
|
| 1197 |
const videoUrl = window.location.href;
|
| 1198 |
const cacheKey = `translations_${CHUNK_SIZE}_${videoUrl}`;
|
| 1199 |
const CACHE_EXPIRY = 365 * 24 * 60 * 60 * 1000; // 7 days
|
| 1200 |
-
|
| 1201 |
const chunks = [];
|
| 1202 |
let translations = [];
|
| 1203 |
const DELAY_BETWEEN_CHUNKS = 1000; // 1 second delay
|
|
@@ -1216,7 +1216,7 @@ const CHUNK_SIZE = 200;
|
|
| 1216 |
} else {
|
| 1217 |
// Resume from last successful chunk
|
| 1218 |
debug.log(`Resuming from chunk ${lastProcessedChunk + 1}`);
|
| 1219 |
-
translations = [...cachedTranslations];
|
| 1220 |
lastChunkIndex = lastProcessedChunk + 1;
|
| 1221 |
}
|
| 1222 |
} else {
|
|
@@ -1226,7 +1226,20 @@ const CHUNK_SIZE = 200;
|
|
| 1226 |
} catch (e) {
|
| 1227 |
debug.error('Cache read error:', e);
|
| 1228 |
}
|
| 1229 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1230 |
|
| 1231 |
// Split remaining data into chunks
|
| 1232 |
|
|
@@ -1293,6 +1306,20 @@ const CHUNK_SIZE = 200;
|
|
| 1293 |
const parsedResponse = JSON.parse(jsonMatch[1]);
|
| 1294 |
translations.push(...parsedResponse.translations);
|
| 1295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1296 |
try {
|
| 1297 |
localStorage.setItem(cacheKey, JSON.stringify({
|
| 1298 |
translations,
|
|
@@ -1301,6 +1328,8 @@ const CHUNK_SIZE = 200;
|
|
| 1301 |
total: totalChunks
|
| 1302 |
}));
|
| 1303 |
debug.log(`Saved progress: ${currentChunkIndex + 1}/${totalChunks}`);
|
|
|
|
|
|
|
| 1304 |
} catch (e) {
|
| 1305 |
debug.error('Cache write error:', e);
|
| 1306 |
}
|
|
@@ -1356,10 +1385,10 @@ const CHUNK_SIZE = 200;
|
|
| 1356 |
if (this.subtitles.english.length > 0 && !this.subtitles.chinese.length) {
|
| 1357 |
|
| 1358 |
const videoUrl = window.location.href;
|
| 1359 |
-
|
| 1360 |
-
|
| 1361 |
const cacheKey = `translations_${CHUNK_SIZE}_${videoUrl}`;
|
| 1362 |
-
|
| 1363 |
|
| 1364 |
// Try cache first
|
| 1365 |
try {
|
|
|
|
| 354 |
<div class="markdown"></div>
|
| 355 |
</div>
|
| 356 |
`;
|
| 357 |
+
const CHUNK_SIZE = 200;
|
| 358 |
|
| 359 |
// Apply main styles
|
| 360 |
GM_addStyle(styles);
|
|
|
|
| 1133 |
const isActive = lineIndex === newIndex;
|
| 1134 |
|
| 1135 |
line.classList.toggle('active', isActive);
|
| 1136 |
+
if (isActive && subtitles[lineIndex]) {
|
| 1137 |
highlightWords(currentTime, line);
|
| 1138 |
if (lineIndex !== lastActiveIndex) {
|
| 1139 |
line.scrollIntoView({
|
|
|
|
| 1191 |
|
| 1192 |
async translateInChunks(subtitleData) {
|
| 1193 |
|
| 1194 |
+
|
| 1195 |
// Get video URL as cache key
|
| 1196 |
+
|
| 1197 |
const videoUrl = window.location.href;
|
| 1198 |
const cacheKey = `translations_${CHUNK_SIZE}_${videoUrl}`;
|
| 1199 |
const CACHE_EXPIRY = 365 * 24 * 60 * 60 * 1000; // 7 days
|
| 1200 |
+
|
| 1201 |
const chunks = [];
|
| 1202 |
let translations = [];
|
| 1203 |
const DELAY_BETWEEN_CHUNKS = 1000; // 1 second delay
|
|
|
|
| 1216 |
} else {
|
| 1217 |
// Resume from last successful chunk
|
| 1218 |
debug.log(`Resuming from chunk ${lastProcessedChunk + 1}`);
|
| 1219 |
+
translations = [...cachedTranslations];
|
| 1220 |
lastChunkIndex = lastProcessedChunk + 1;
|
| 1221 |
}
|
| 1222 |
} else {
|
|
|
|
| 1226 |
} catch (e) {
|
| 1227 |
debug.error('Cache read error:', e);
|
| 1228 |
}
|
| 1229 |
+
|
| 1230 |
+
// Initialize Chinese subtitles with placeholders
|
| 1231 |
+
this.subtitles.chinese = this.subtitles.english.map((sub, index) => ({
|
| 1232 |
+
startTime: sub.startTime,
|
| 1233 |
+
endTime: sub.endTime,
|
| 1234 |
+
words: [{
|
| 1235 |
+
text: translations[index]?.text || '翻译中...',
|
| 1236 |
+
startTime: sub.startTime,
|
| 1237 |
+
endTime: sub.endTime
|
| 1238 |
+
}]
|
| 1239 |
+
}));
|
| 1240 |
+
|
| 1241 |
+
// Update display immediately
|
| 1242 |
+
this.updateSubtitleDisplay();
|
| 1243 |
|
| 1244 |
// Split remaining data into chunks
|
| 1245 |
|
|
|
|
| 1306 |
const parsedResponse = JSON.parse(jsonMatch[1]);
|
| 1307 |
translations.push(...parsedResponse.translations);
|
| 1308 |
|
| 1309 |
+
// 立即更新中文字幕
|
| 1310 |
+
this.subtitles.chinese = this.subtitles.english.map((sub, index) => ({
|
| 1311 |
+
startTime: sub.startTime,
|
| 1312 |
+
endTime: sub.endTime,
|
| 1313 |
+
words: [{
|
| 1314 |
+
text: translations[index]?.text || '翻译中...',
|
| 1315 |
+
startTime: sub.startTime,
|
| 1316 |
+
endTime: sub.endTime
|
| 1317 |
+
}]
|
| 1318 |
+
}));
|
| 1319 |
+
|
| 1320 |
+
// 先更新字幕显示
|
| 1321 |
+
this.updateSubtitleDisplay();
|
| 1322 |
+
|
| 1323 |
try {
|
| 1324 |
localStorage.setItem(cacheKey, JSON.stringify({
|
| 1325 |
translations,
|
|
|
|
| 1328 |
total: totalChunks
|
| 1329 |
}));
|
| 1330 |
debug.log(`Saved progress: ${currentChunkIndex + 1}/${totalChunks}`);
|
| 1331 |
+
// Refresh display
|
| 1332 |
+
this.updateSubtitleDisplay();
|
| 1333 |
} catch (e) {
|
| 1334 |
debug.error('Cache write error:', e);
|
| 1335 |
}
|
|
|
|
| 1385 |
if (this.subtitles.english.length > 0 && !this.subtitles.chinese.length) {
|
| 1386 |
|
| 1387 |
const videoUrl = window.location.href;
|
| 1388 |
+
|
| 1389 |
+
|
| 1390 |
const cacheKey = `translations_${CHUNK_SIZE}_${videoUrl}`;
|
| 1391 |
+
|
| 1392 |
|
| 1393 |
// Try cache first
|
| 1394 |
try {
|