| |
| |
| |
| |
| |
| |
| |
| |
|
|
| const CACHE_PREFIX = 'echo_t3_'; |
|
|
| const SCRIPT = { |
| si: /[-]/, |
| ta: /[-]/, |
| }; |
|
|
| |
| |
| |
| |
| |
| const FUNCTION_WORDS = { |
| a: { si: 'එක', ta: 'ஒரு' }, |
| i: { si: 'මම', ta: 'நான்' }, |
| an: { si: 'එක', ta: 'ஒரு' }, |
| the: { si: 'එම', ta: 'அந்த' }, |
| at: { si: 'හි', ta: 'இல்' }, |
| in: { si: 'තුළ', ta: 'உள்ளே' }, |
| on: { si: 'මත', ta: 'மீது' }, |
| of: { si: 'හි', ta: 'இன்' }, |
| to: { si: 'කරා', ta: 'க்கு' }, |
| by: { si: 'විසින්', ta: 'மூலம்' }, |
| for: { si: 'සඳහා', ta: 'க்காக' }, |
| from: { si: 'වෙතින්', ta: 'இருந்து' }, |
| up: { si: 'ඉහළ', ta: 'மேலே' }, |
| us: { si: 'අපට', ta: 'எங்களை' }, |
| we: { si: 'අපි', ta: 'நாம்' }, |
| he: { si: 'ඔහු', ta: 'அவன்' }, |
| she: { si: 'ඇය', ta: 'அவள்' }, |
| it: { si: 'එය', ta: 'அது' }, |
| me: { si: 'මට', ta: 'என்னை' }, |
| my: { si: 'මගේ', ta: 'என்' }, |
| no: { si: 'නැහැ', ta: 'இல்லை' }, |
| or: { si: 'හෝ', ta: 'அல்லது' }, |
| so: { si: 'එසේ', ta: 'அப்படி' }, |
| if: { si: 'නම්', ta: 'என்றால்' }, |
| is: { si: 'වේ', ta: 'உள்ளது' }, |
| am: { si: 'වෙමි', ta: 'இருக்கிறேன்' }, |
| are: { si: 'වෙති', ta: 'உள்ளனர்' }, |
| was: { si: 'විය', ta: 'இருந்தது' }, |
| be: { si: 'වෙන්න', ta: 'இரு' }, |
| do: { si: 'කරන්න', ta: 'செய்' }, |
| go: { si: 'යන්න', ta: 'போ' }, |
| and: { si: 'සහ', ta: 'மற்றும்' }, |
| but: { si: 'නමුත්', ta: 'ஆனால்' }, |
| not: { si: 'නැත', ta: 'இல்லை' }, |
| yes: { si: 'ඔව්', ta: 'ஆம்' }, |
| you: { si: 'ඔබ', ta: 'நீ' }, |
| who: { si: 'කවුද', ta: 'யார்' }, |
| why: { si: 'ඇයි', ta: 'ஏன்' }, |
| how: { si: 'කෙසේද', ta: 'எப்படி' }, |
| what: { si: 'මොකක්ද', ta: 'என்ன' }, |
| when: { si: 'කවදද', ta: 'எப்போது' }, |
| where:{ si: 'කොහෙද', ta: 'எங்கே' }, |
| this: { si: 'මේ', ta: 'இந்த' }, |
| that: { si: 'එම', ta: 'அந்த' }, |
| these:{ si: 'මේවා', ta: 'இவை' }, |
| those:{ si: 'ඒවා', ta: 'அவை' }, |
| with: { si: 'සමඟ', ta: 'உடன்' }, |
| out: { si: 'පිටත', ta: 'வெளியே' }, |
| off: { si: 'ඉවත්', ta: 'விலகி' }, |
| one: { si: 'එක', ta: 'ஒன்று' }, |
| two: { si: 'දෙක', ta: 'இரண்டு' }, |
| ten: { si: 'දහය', ta: 'பத்து' }, |
| yes: { si: 'ඔව්', ta: 'ஆம்' }, |
| ok: { si: 'හරි', ta: 'சரி' }, |
| hi: { si: 'හායි', ta: 'வணக்கம்' }, |
| oh: { si: 'ඕ', ta: 'ஓ' }, |
| as: { si: 'ලෙස', ta: 'ஆக' }, |
| all: { si: 'සියල්ල', ta: 'அனைத்தும்' }, |
| any: { si: 'ඕනෑම', ta: 'எதேனும்' }, |
| can: { si: 'හැකි', ta: 'முடியும்' }, |
| will: { si: 'කරයි', ta: 'செய்யும்' }, |
| may: { si: 'පුළුවන්', ta: 'இருக்கலாம்' }, |
| her: { si: 'ඇගේ', ta: 'அவளுடைய' }, |
| him: { si: 'ඔහුට', ta: 'அவனை' }, |
| his: { si: 'ඔහුගේ', ta: 'அவனது' }, |
| our: { si: 'අපේ', ta: 'எங்கள்' }, |
| your: { si: 'ඔබේ', ta: 'உங்கள்' }, |
| its: { si: 'එහි', ta: 'அதன்' }, |
| }; |
|
|
| export function validateTranslation(text, lang, sourceWord) { |
| if (!text) return false; |
| const t = String(text).trim(); |
| if (!t) return false; |
| if (t.toLowerCase() === sourceWord.toLowerCase()) return false; |
| if (t.length > Math.max(40, sourceWord.length * 6)) return false; |
| const re = SCRIPT[lang]; |
| if (!re) return true; |
| const scriptChars = (t.match(new RegExp(re.source, 'g')) || []).length; |
| const latinChars = (t.match(/[a-zA-Z]/g) || []).length; |
| if (scriptChars < 1) return false; |
| if (latinChars > scriptChars) return false; |
| const garbage = (t.match(/[;>\/\\\[\]{}|`~]/g) || []).length; |
| if (garbage > 1 && scriptChars < 3) return false; |
| return true; |
| } |
|
|
| async function tryGoogle(word, lang) { |
| try { |
| const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${lang}&dt=t&q=${encodeURIComponent(word)}`; |
| const r = await fetch(url); |
| if (!r.ok) return null; |
| const j = await r.json(); |
| if (j?.[0]?.[0]?.[0]) { |
| const t = String(j[0][0][0]).trim(); |
| if (validateTranslation(t, lang, word)) return t; |
| } |
| } catch (e) {} |
| return null; |
| } |
|
|
| async function tryMyMemory(word, lang) { |
| try { |
| const url = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(word)}&langpair=en|${lang}`; |
| const r = await fetch(url); |
| if (!r.ok) return null; |
| const j = await r.json(); |
| if (j?.responseData?.translatedText) { |
| const t = String(j.responseData.translatedText).trim(); |
| if (validateTranslation(t, lang, word)) return t; |
| } |
| } catch (e) {} |
| return null; |
| } |
|
|
| async function translateOne(word, lang) { |
| return (await tryGoogle(word, lang)) || (await tryMyMemory(word, lang)); |
| } |
|
|
| export async function getMeaning(word) { |
| |
| if (FUNCTION_WORDS[word]) { |
| return { si: FUNCTION_WORDS[word].si, ta: FUNCTION_WORDS[word].ta }; |
| } |
|
|
| |
| try { |
| const cached = JSON.parse(localStorage.getItem(CACHE_PREFIX + word) || 'null'); |
| if (cached) { |
| const siOK = cached.si === '—' || validateTranslation(cached.si, 'si', word); |
| const taOK = cached.ta === '—' || validateTranslation(cached.ta, 'ta', word); |
| if (siOK && taOK) return cached; |
| } |
| } catch (e) {} |
|
|
| |
| const [si, ta] = await Promise.all([translateOne(word, 'si'), translateOne(word, 'ta')]); |
| const out = { si: si || '—', ta: ta || '—' }; |
| try { localStorage.setItem(CACHE_PREFIX + word, JSON.stringify(out)); } catch (e) {} |
| return out; |
| } |
|
|