494 lines
16 KiB
JavaScript
494 lines
16 KiB
JavaScript
const MOCK_TRANSLATIONS = {
|
||
'hola': { en: 'Hello', zh: '你好' },
|
||
'buenos días': { en: 'Good morning', zh: '早上好' },
|
||
'buenas tardes': { en: 'Good afternoon', zh: '下午好' },
|
||
'buenas noches': { en: 'Good night', zh: '晚安' },
|
||
'hoy': { en: 'today', zh: '今天' },
|
||
'ayer': { en: 'yesterday', zh: '昨天' },
|
||
'mañana': { en: 'tomorrow', zh: '明天' },
|
||
'fui': { en: 'I went', zh: '我去了' },
|
||
'fui a': { en: 'I went to', zh: '我去了' },
|
||
'voy': { en: 'I go', zh: '我去' },
|
||
'voy a': { en: 'I am going to', zh: '我要去' },
|
||
'estoy': { en: 'I am', zh: '我是' },
|
||
'estoy muy': { en: 'I am very', zh: '我非常' },
|
||
'tengo': { en: 'I have', zh: '我有' },
|
||
'quiero': { en: 'I want', zh: '我想要' },
|
||
'me gusta': { en: 'I like', zh: '我喜欢' },
|
||
'me gustó': { en: 'I liked', zh: '我喜欢了' },
|
||
'aprendí': { en: 'I learned', zh: '我学了' },
|
||
'estudié': { en: 'I studied', zh: '我学习了' },
|
||
'comí': { en: 'I ate', zh: '我吃了' },
|
||
'bebí': { en: 'I drank', zh: '我喝了' },
|
||
'leí': { en: 'I read', zh: '我读了' },
|
||
'escribí': { en: 'I wrote', zh: '我写了' },
|
||
'trabajé': { en: 'I worked', zh: '我工作了' },
|
||
'descansé': { en: 'I rested', zh: '我休息了' },
|
||
'caminé': { en: 'I walked', zh: '我散步了' },
|
||
'corrí': { en: 'I ran', zh: '我跑步了' },
|
||
'compré': { en: 'I bought', zh: '我买了' },
|
||
'vi': { en: 'I saw', zh: '我看了' },
|
||
'el': { en: 'the', zh: '' },
|
||
'la': { en: 'the', zh: '' },
|
||
'los': { en: 'the', zh: '' },
|
||
'las': { en: 'the', zh: '' },
|
||
'un': { en: 'a', zh: '' },
|
||
'una': { en: 'a', zh: '' },
|
||
'unos': { en: 'some', zh: '一些' },
|
||
'unas': { en: 'some', zh: '一些' },
|
||
'al': { en: 'to the', zh: '' },
|
||
'del': { en: 'of the', zh: '' },
|
||
'a': { en: 'to', zh: '' },
|
||
'de': { en: 'of', zh: '' },
|
||
'en': { en: 'in', zh: '在' },
|
||
'para': { en: 'for', zh: '为了' },
|
||
'por': { en: 'for / by', zh: '' },
|
||
'con': { en: 'with', zh: '和' },
|
||
'sin': { en: 'without', zh: '没有' },
|
||
'sobre': { en: 'about', zh: '关于' },
|
||
'mi': { en: 'my', zh: '我的' },
|
||
'tu': { en: 'your', zh: '你的' },
|
||
'su': { en: 'his / her / their', zh: '' },
|
||
'nuestro': { en: 'our', zh: '我们的' },
|
||
'amigo': { en: 'friend', zh: '朋友' },
|
||
'amiga': { en: 'friend', zh: '朋友' },
|
||
'familia': { en: 'family', zh: '家人' },
|
||
'casa': { en: 'home', zh: '家' },
|
||
'trabajo': { en: 'work', zh: '工作' },
|
||
'escuela': { en: 'school', zh: '学校' },
|
||
'parque': { en: 'park', zh: '公园' },
|
||
'restaurante': { en: 'restaurant', zh: '餐厅' },
|
||
'café': { en: 'cafe', zh: '咖啡馆' },
|
||
'libro': { en: 'book', zh: '书' },
|
||
'película': { en: 'movie', zh: '电影' },
|
||
'música': { en: 'music', zh: '音乐' },
|
||
'día': { en: 'day', zh: '天' },
|
||
'noche': { en: 'night', zh: '夜晚' },
|
||
'comida': { en: 'food', zh: '食物' },
|
||
'agua': { en: 'water', zh: '水' },
|
||
'tiempo': { en: 'time / weather', zh: '时间' },
|
||
'feliz': { en: 'happy', zh: '开心的' },
|
||
'cansado': { en: 'tired', zh: '累的' },
|
||
'enfermo': { en: 'sick', zh: '生病的' },
|
||
'bien': { en: 'well', zh: '好' },
|
||
'mal': { en: 'bad', zh: '不好' },
|
||
'muy': { en: 'very', zh: '非常' },
|
||
'un poco': { en: 'a little', zh: '一点' },
|
||
'mucho': { en: 'a lot', zh: '很多' },
|
||
'y': { en: 'and', zh: '和' },
|
||
'pero': { en: 'but', zh: '但是' },
|
||
'porque': { en: 'because', zh: '因为' },
|
||
'también': { en: 'also', zh: '也' },
|
||
'no': { en: 'not', zh: '不' },
|
||
'sí': { en: 'yes', zh: '是的' },
|
||
'gracias': { en: 'thank you', zh: '谢谢' },
|
||
'por favor': { en: 'please', zh: '请' },
|
||
'lo siento': { en: 'sorry', zh: '对不起' },
|
||
'nuevo': { en: 'new', zh: '新的' },
|
||
'viejo': { en: 'old', zh: '旧的' },
|
||
'grande': { en: 'big', zh: '大' },
|
||
'pequeño': { en: 'small', zh: '小' },
|
||
'bueno': { en: 'good', zh: '好的' },
|
||
'malo': { en: 'bad', zh: '坏的' },
|
||
'bonito': { en: 'pretty', zh: '漂亮的' },
|
||
'rápido': { en: 'fast', zh: '快的' },
|
||
'lento': { en: 'slow', zh: '慢的' },
|
||
'aquí': { en: 'here', zh: '这里' },
|
||
'allí': { en: 'there', zh: '那里' },
|
||
'ahora': { en: 'now', zh: '现在' },
|
||
'siempre': { en: 'always', zh: '总是' },
|
||
'nunca': { en: 'never', zh: '从不' },
|
||
'ya': { en: 'already', zh: '已经' },
|
||
'todavía': { en: 'still', zh: '仍然' },
|
||
'después': { en: 'after', zh: '之后' },
|
||
'antes': { en: 'before', zh: '之前' },
|
||
'más': { en: 'more', zh: '更多' },
|
||
'menos': { en: 'less', zh: '更少' },
|
||
'tan': { en: 'so', zh: '如此' },
|
||
'como': { en: 'as / like', zh: '像' },
|
||
'que': { en: 'that / than', zh: '比' },
|
||
'este': { en: 'this', zh: '这个' },
|
||
'ese': { en: 'that', zh: '那个' },
|
||
'qué': { en: 'what', zh: '什么' },
|
||
'quién': { en: 'who', zh: '谁' },
|
||
'cuándo': { en: 'when', zh: '什么时候' },
|
||
'dónde': { en: 'where', zh: '哪里' },
|
||
'por qué': { en: 'why', zh: '为什么' },
|
||
'cómo': { en: 'how', zh: '如何' },
|
||
'mucho gusto': { en: 'nice to meet you', zh: '很高兴认识你' },
|
||
'buena suerte': { en: 'good luck', zh: '好运' },
|
||
'tener que': { en: 'have to', zh: '必须' },
|
||
'tener hambre': { en: 'be hungry', zh: '饿了' },
|
||
'tener sed': { en: 'be thirsty', zh: '渴了' },
|
||
'tener sueño': { en: 'be sleepy', zh: '困了' },
|
||
'tener razón': { en: 'be right', zh: '是对的' },
|
||
'hacer calor': { en: 'be hot (weather)', zh: '热' },
|
||
'hacer frío': { en: 'be cold (weather)', zh: '冷' },
|
||
'estar bien': { en: 'be fine', zh: '没问题' }
|
||
};
|
||
|
||
var SORTED_KEYS = Object.keys(MOCK_TRANSLATIONS).sort(function(a, b) {
|
||
return b.length - a.length;
|
||
});
|
||
|
||
function translateText(text) {
|
||
if (!text || !text.trim()) return { english: '', chinese: '' };
|
||
var lower = text.toLowerCase().trim();
|
||
var enParts = [];
|
||
var zhParts = [];
|
||
var i = 0;
|
||
while (i < lower.length) {
|
||
var matched = false;
|
||
for (var k = 0; k < SORTED_KEYS.length; k++) {
|
||
var key = SORTED_KEYS[k];
|
||
if (lower.indexOf(key, i) === i) {
|
||
var entry = MOCK_TRANSLATIONS[key];
|
||
if (entry.en) enParts.push(entry.en);
|
||
if (entry.zh) zhParts.push(entry.zh);
|
||
i += key.length;
|
||
matched = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!matched) {
|
||
var ch = lower[i];
|
||
if (/[a-zà-ÿñ]/.test(ch)) { enParts.push(ch); }
|
||
i++;
|
||
}
|
||
}
|
||
var enStr = enParts.join(' ').replace(/\s+/g, ' ').trim();
|
||
var zhStr = zhParts.join('').trim();
|
||
enStr = enStr.charAt(0).toUpperCase() + enStr.slice(1);
|
||
return { english: enStr || text, chinese: zhStr || text };
|
||
}
|
||
|
||
function getVocabulary(text) {
|
||
if (!text || !text.trim()) return [];
|
||
var lower = text.toLowerCase().trim();
|
||
var seen = {};
|
||
var result = [];
|
||
var i = 0;
|
||
while (i < lower.length) {
|
||
for (var k = 0; k < SORTED_KEYS.length; k++) {
|
||
var key = SORTED_KEYS[k];
|
||
if (lower.indexOf(key, i) === i) {
|
||
var entry = MOCK_TRANSLATIONS[key];
|
||
if (!seen[key] && entry.zh && key.indexOf(' ') === -1) {
|
||
seen[key] = true;
|
||
result.push({ word: key, english: entry.en, chinese: entry.zh });
|
||
}
|
||
i += key.length;
|
||
break;
|
||
}
|
||
}
|
||
i++;
|
||
}
|
||
result.sort(function(a, b) { return b.word.length - a.word.length; });
|
||
return result;
|
||
}
|
||
|
||
function translateSelection(text) {
|
||
if (!text || !text.trim()) return { english: '', chinese: '' };
|
||
return translateText(text);
|
||
}
|
||
|
||
function getVocabForWord(word) {
|
||
var w = word.toLowerCase().trim();
|
||
var entry = MOCK_TRANSLATIONS[w];
|
||
return entry || null;
|
||
}
|
||
|
||
// Chinese -> Spanish helper dictionary
|
||
const ZH_TO_ES = {
|
||
'你好': 'Hola',
|
||
'早上好': 'Buenos días',
|
||
'下午好': 'Buenas tardes',
|
||
'晚上好': 'Buenas noches',
|
||
'晚安': 'Buenas noches',
|
||
'再见': 'Adiós',
|
||
'谢谢': 'Gracias',
|
||
'请': 'Por favor',
|
||
'对不起': 'Lo siento',
|
||
'很高兴认识你': 'Mucho gusto',
|
||
'祝你好运': 'Buena suerte',
|
||
'是的': 'Sí',
|
||
'不是': 'No',
|
||
'今天': 'Hoy',
|
||
'昨天': 'Ayer',
|
||
'明天': 'Mañana',
|
||
'现在': 'ahora',
|
||
'已经': 'ya',
|
||
'总是': 'siempre',
|
||
'从不': 'nunca',
|
||
'我': 'yo',
|
||
'你': 'tú',
|
||
'他': 'él',
|
||
'她': 'ella',
|
||
'我们': 'nosotros',
|
||
'你们': 'vosotros',
|
||
'他们': 'ellos',
|
||
'我的': 'mi',
|
||
'你的': 'tu',
|
||
'和': 'y',
|
||
'或者': 'o',
|
||
'但是': 'pero',
|
||
'因为': 'porque',
|
||
'也': 'también',
|
||
'非常': 'muy',
|
||
'很': 'muy',
|
||
'一点': 'un poco',
|
||
'很多': 'mucho',
|
||
'好的': 'bien',
|
||
'朋友': 'amigo',
|
||
'家': 'casa',
|
||
'学校': 'escuela',
|
||
'工作': 'trabajo',
|
||
'公园': 'parque',
|
||
'餐厅': 'restaurante',
|
||
'图书馆': 'biblioteca',
|
||
'超市': 'supermercado',
|
||
'医院': 'hospital',
|
||
'书': 'libro',
|
||
'篮球': 'baloncesto',
|
||
'足球': 'fútbol',
|
||
'羽毛球': 'bádminton',
|
||
'游泳': 'nadar',
|
||
'跑步': 'correr',
|
||
'咖啡': 'café',
|
||
'茶': 'té',
|
||
'水': 'agua',
|
||
'电影': 'película',
|
||
'音乐': 'música',
|
||
'天气': 'tiempo',
|
||
'时间': 'tiempo',
|
||
'星期一': 'lunes',
|
||
'星期二': 'martes',
|
||
'星期三': 'miércoles',
|
||
'星期四': 'jueves',
|
||
'星期五': 'viernes',
|
||
'星期六': 'sábado',
|
||
'星期日': 'domingo',
|
||
'一月': 'enero',
|
||
'二月': 'febrero',
|
||
'三月': 'marzo',
|
||
'四月': 'abril',
|
||
'五月': 'mayo',
|
||
'六月': 'junio',
|
||
'七月': 'julio',
|
||
'八月': 'agosto',
|
||
'九月': 'septiembre',
|
||
'十月': 'octubre',
|
||
'十一月': 'noviembre',
|
||
'十二月': 'diciembre',
|
||
'去': 'ir',
|
||
'我去了': 'fui',
|
||
'我去': 'voy',
|
||
'我要': 'voy a',
|
||
'我想': 'quiero',
|
||
'我想要': 'quiero',
|
||
'我有': 'tengo',
|
||
'我学习': 'estudio',
|
||
'我学习了': 'estudié',
|
||
'我读书': 'leo',
|
||
'我读了一本书': 'leí un libro',
|
||
'我吃饭': 'como',
|
||
'我吃了': 'comí',
|
||
'我喝水': 'bebo agua',
|
||
'我喝了': 'bebí',
|
||
'我喜欢': 'me gusta',
|
||
'我爱': 'me encanta',
|
||
'我累了': 'Estoy cansado',
|
||
'我很累': 'Estoy muy cansado',
|
||
'我很开心': 'Estoy muy feliz',
|
||
'我生病了': 'Estoy enfermo',
|
||
'我正在学习': 'Estoy estudiando',
|
||
'我必须工作': 'Tengo que trabajar',
|
||
'我喜欢读书': 'Me gusta leer',
|
||
'我喜欢听音乐': 'Me gusta escuchar música',
|
||
'我想去旅行': 'Quiero viajar',
|
||
'我有一个朋友': 'Tengo un amigo',
|
||
'我没有钱': 'No tengo dinero',
|
||
'今天我去公园': 'Hoy fui al parque',
|
||
'今天我去学校': 'Hoy fui a la escuela',
|
||
'今天我去工作': 'Hoy fui al trabajo',
|
||
'昨天我去了公园': 'Ayer fui al parque',
|
||
'明天我要去公园': 'Mañana voy al parque',
|
||
'我和朋友去了公园': 'Fui al parque con mi amigo',
|
||
'今天我和朋友去了公园': 'Hoy fui al parque con mi amigo',
|
||
'今天天气很好': 'Hoy hace buen tiempo',
|
||
'今天天气热': 'Hoy hace calor',
|
||
'今天天气冷': 'Hoy hace frío',
|
||
'我学习西班牙语': 'Estudio español',
|
||
'我喜欢篮球': 'Me gusta el baloncesto',
|
||
'我喜欢足球': 'Me gusta el fútbol',
|
||
'我喜欢游泳': 'Me gusta nadar',
|
||
'我喜欢跑步': 'Me gusta correr',
|
||
'我喜欢打篮球': 'Me gusta jugar al baloncesto',
|
||
'我喜欢打足球': 'Me gusta jugar al fútbol',
|
||
'打篮球': 'jugar al baloncesto',
|
||
'打足球': 'jugar al fútbol',
|
||
'我喜欢篮球今天天气真好': 'Me gusta el baloncesto. Hoy hace muy buen tiempo.',
|
||
'我喜欢篮球今天天气很好': 'Me gusta el baloncesto. Hoy hace buen tiempo.',
|
||
'我要去打篮球': 'Voy a jugar al baloncesto',
|
||
'我要去打篮球了': 'Voy a jugar al baloncesto',
|
||
'我去打篮球': 'Voy a jugar al baloncesto',
|
||
'我去打篮球了': 'Fui a jugar al baloncesto',
|
||
'我要去踢足球': 'Voy a jugar al fútbol',
|
||
'我要去踢足球了': 'Voy a jugar al fútbol',
|
||
'我要去游泳': 'Voy a nadar',
|
||
'我要去游泳了': 'Voy a nadar',
|
||
'我去游泳了': 'Fui a nadar',
|
||
'我要去跑步': 'Voy a correr',
|
||
'我要去跑步了': 'Voy a correr',
|
||
'我去跑步了': 'Fui a correr',
|
||
'我要去图书馆': 'Voy a la biblioteca',
|
||
'我去图书馆了': 'Fui a la biblioteca',
|
||
'我要去学校': 'Voy a la escuela',
|
||
'我去学校了': 'Fui a la escuela',
|
||
'我要去工作': 'Voy al trabajo',
|
||
'我去工作了': 'Fui al trabajo',
|
||
'我想去公园': 'Quiero ir al parque',
|
||
'我想去学校': 'Quiero ir a la escuela',
|
||
'我想去图书馆': 'Quiero ir a la biblioteca',
|
||
'我想去工作': 'Quiero ir al trabajo',
|
||
'去公园': 'ir al parque',
|
||
'去学校': 'ir a la escuela',
|
||
'去图书馆': 'ir a la biblioteca',
|
||
'去工作': 'ir al trabajo',
|
||
'今天天气很好': 'Hoy hace buen tiempo',
|
||
'今天天气真好': 'Hoy hace muy buen tiempo',
|
||
'今天天气非常好': 'Hoy hace muy buen tiempo',
|
||
'天气很好': 'hace buen tiempo',
|
||
'天气真好': 'hace muy buen tiempo',
|
||
'真好': 'muy bien',
|
||
'很好': 'muy bien',
|
||
'今天我去公园和我的朋友': 'Hoy fui al parque con mi amigo',
|
||
'我去了公园和我的朋友': 'Fui al parque con mi amigo',
|
||
'公园和我的朋友': 'el parque con mi amigo',
|
||
'公园': 'el parque',
|
||
'我的朋友': 'mi amigo',
|
||
'妈妈': 'mamá',
|
||
'爸爸': 'papá',
|
||
'爷爷': 'abuelo',
|
||
'奶奶': 'abuela',
|
||
'外公': 'abuelo',
|
||
'外婆': 'abuela',
|
||
'哥哥': 'hermano mayor',
|
||
'姐姐': 'hermana mayor',
|
||
'弟弟': 'hermano menor',
|
||
'妹妹': 'hermana menor',
|
||
'儿子': 'hijo',
|
||
'女儿': 'hija',
|
||
'丈夫': 'marido',
|
||
'妻子': 'esposa',
|
||
'男朋友': 'novio',
|
||
'女朋友': 'novia',
|
||
'同事': 'colega',
|
||
'邻居': 'vecino',
|
||
'为什么': 'por qué',
|
||
'什么': 'qué',
|
||
'哪里': 'dónde',
|
||
'什么时候': 'cuándo',
|
||
'多少': 'cuánto',
|
||
'谁': 'quién',
|
||
'怎么': 'cómo',
|
||
'星期': 'semana',
|
||
};
|
||
|
||
var ZH_SORTED_KEYS = Object.keys(ZH_TO_ES).sort(function(a, b) {
|
||
return b.length - a.length;
|
||
});
|
||
|
||
function translateZhSegment(segment) {
|
||
if (!segment || !segment.trim()) return '';
|
||
var input = segment.replace(/[\s,。!?、,.!?;;::""''()()]/g, '');
|
||
var result = '';
|
||
var matched = false;
|
||
var i = 0;
|
||
while (i < input.length) {
|
||
var found = false;
|
||
for (var k = 0; k < ZH_SORTED_KEYS.length; k++) {
|
||
var key = ZH_SORTED_KEYS[k];
|
||
if (input.indexOf(key, i) === i) {
|
||
result += ZH_TO_ES[key] + ' ';
|
||
i += key.length;
|
||
matched = true;
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!found) i++;
|
||
}
|
||
return matched ? result.trim() : '';
|
||
}
|
||
|
||
function translateZhToEs(text) {
|
||
if (!text || !text.trim()) return '';
|
||
var clauses = [];
|
||
var seps = [];
|
||
var cur = '';
|
||
for (var i = 0; i < text.length; i++) {
|
||
var ch = text[i];
|
||
if (ch === '。' || ch === '!' || ch === '?' || ch === '!' || ch === '?' || ch === ';' || ch === ';') {
|
||
clauses.push(cur.trim());
|
||
seps.push('.');
|
||
cur = '';
|
||
} else if (ch === ',' || ch === ',') {
|
||
clauses.push(cur.trim());
|
||
seps.push(',');
|
||
cur = '';
|
||
} else {
|
||
cur += ch;
|
||
}
|
||
}
|
||
clauses.push(cur.trim());
|
||
seps.push('');
|
||
|
||
var parts = [];
|
||
for (var j = 0; j < clauses.length; j++) {
|
||
if (!clauses[j]) continue;
|
||
var translated = translateZhSegment(clauses[j]);
|
||
if (translated) {
|
||
parts.push(translated.replace(/[.。]+$/g, ''));
|
||
}
|
||
}
|
||
if (parts.length === 0) return '';
|
||
|
||
function capitalizeFirst(s) {
|
||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||
}
|
||
function lowercaseFirst(s) {
|
||
return s.charAt(0).toLowerCase() + s.slice(1);
|
||
}
|
||
|
||
var out = capitalizeFirst(parts[0]);
|
||
var k = 1;
|
||
for (var m = 0; m < seps.length && k < parts.length; m++) {
|
||
if (seps[m] && k < parts.length) {
|
||
out += (seps[m] === ',' ? ', ' + lowercaseFirst(parts[k]) : '. ' + capitalizeFirst(parts[k]));
|
||
k++;
|
||
}
|
||
}
|
||
while (k < parts.length) {
|
||
out += '. ' + capitalizeFirst(parts[k]);
|
||
k++;
|
||
}
|
||
if (!/[.!?]$/.test(out)) out += '.';
|
||
return out;
|
||
}
|
||
|
||
// Merge B1 vocabulary into translation dictionaries
|
||
if (typeof B1_VOCAB !== 'undefined') {
|
||
B1_VOCAB.forEach(function(item) {
|
||
var es = item[0].toLowerCase();
|
||
MOCK_TRANSLATIONS[es] = { en: item[1], zh: item[2] };
|
||
if (item[2]) ZH_TO_ES[item[2]] = item[0];
|
||
});
|
||
SORTED_KEYS = Object.keys(MOCK_TRANSLATIONS).sort(function(a, b) {
|
||
return b.length - a.length;
|
||
});
|
||
ZH_SORTED_KEYS = Object.keys(ZH_TO_ES).sort(function(a, b) {
|
||
return b.length - a.length;
|
||
});
|
||
}
|