feat: 增加中译西辅助、在线翻译、B1词库与三语语音对照

This commit is contained in:
guoqingshan
2026-08-01 17:13:05 +08:00
parent 0d5b0919da
commit a2e705aa30
9 changed files with 1530 additions and 1 deletions
+104
View File
@@ -229,6 +229,106 @@ function saveTextareaSelection() {
savedSelEnd = ta.selectionEnd;
}
// ----- Chinese to Spanish helper -----
var helperDebounceTimer = null;
var helperRequestSeq = 0;
var helperOnlineResult = '';
function openHelperModal() {
var ta = document.getElementById('entry-text');
savedSelStart = ta.selectionStart;
savedSelEnd = ta.selectionEnd;
helperOnlineResult = '';
if (helperDebounceTimer) clearTimeout(helperDebounceTimer);
document.getElementById('helper-input').value = '';
document.getElementById('helper-result').textContent = '';
document.getElementById('helper-confirm').disabled = true;
document.getElementById('helper-modal-overlay').classList.add('show');
setTimeout(function() { document.getElementById('helper-input').focus(); }, 0);
}
function closeHelperModal() {
if (helperDebounceTimer) clearTimeout(helperDebounceTimer);
helperRequestSeq++;
document.getElementById('helper-modal-overlay').classList.remove('show');
}
function updateHelperPreview() {
var zh = document.getElementById('helper-input').value;
helperOnlineResult = '';
if (helperDebounceTimer) clearTimeout(helperDebounceTimer);
if (!zh.trim()) {
document.getElementById('helper-result').textContent = '';
document.getElementById('helper-confirm').disabled = true;
return;
}
var local = translateZhToEs(zh);
document.getElementById('helper-result').textContent = local || '本地词典未收录,正在尝试在线翻译...';
document.getElementById('helper-confirm').disabled = !local;
helperDebounceTimer = setTimeout(function() {
translateZhOnline(zh);
}, 600);
}
function translateZhOnline(zh) {
var seq = ++helperRequestSeq;
var url = 'https://api.mymemory.translated.net/get?q=' +
encodeURIComponent(zh) + '&langpair=zh-CN|es';
fetch(url)
.then(function(res) { return res.json(); })
.then(function(data) {
if (seq !== helperRequestSeq) return;
var text = data && data.responseData && data.responseData.translatedText;
if (text && !data.quotaFinished) {
helperOnlineResult = text.trim();
document.getElementById('helper-result').textContent = helperOnlineResult;
document.getElementById('helper-confirm').disabled = false;
}
})
.catch(function() {
if (seq !== helperRequestSeq) return;
var local = translateZhToEs(zh);
if (local) {
document.getElementById('helper-result').textContent = local;
document.getElementById('helper-confirm').disabled = false;
} else {
document.getElementById('helper-result').textContent = '在线翻译暂不可用,且本地词典未收录';
}
});
}
function getHelperResult() {
if (helperOnlineResult) return helperOnlineResult;
return translateZhToEs(document.getElementById('helper-input').value);
}
function insertSpanishAtCursor(es) {
var ta = document.getElementById('entry-text');
var start = savedSelStart || ta.selectionStart;
var end = savedSelEnd || ta.selectionEnd;
var before = ta.value.slice(0, start);
var after = ta.value.slice(end);
var prefix = '';
var suffix = '';
if (before.length > 0 && !/\s$/.test(before)) prefix = ' ';
if (after.length > 0 && !/^\s/.test(after)) suffix = ' ';
var insert = prefix + es + suffix;
var newPos = start + insert.length;
ta.value = before + insert + after;
ta.focus();
ta.setSelectionRange(newPos, newPos);
savedSelStart = savedSelEnd = newPos;
updateLiveTranslation();
}
function confirmHelperInsert() {
var es = getHelperResult();
if (!es) return;
insertSpanishAtCursor(es);
closeHelperModal();
}
// ----- Speech handler -----
function handleSpeech(lang) {
@@ -260,6 +360,10 @@ function init() {
document.getElementById('btn-new').addEventListener('click', newEntry);
document.getElementById('btn-save').addEventListener('click', saveCurrentEntry);
document.getElementById('btn-helper').addEventListener('click', openHelperModal);
document.getElementById('helper-cancel').addEventListener('click', closeHelperModal);
document.getElementById('helper-confirm').addEventListener('click', confirmHelperInsert);
document.getElementById('helper-input').addEventListener('input', updateHelperPreview);
document.querySelectorAll('.btn-speech').forEach(function(btn) {
btn.addEventListener('click', function() { handleSpeech(btn.dataset.lang); });