Skip to content

Commit 8ce70ac

Browse files
committed
v0.2
Official v0.1Alpha Release
1 parent 695eb0b commit 8ce70ac

9 files changed

Lines changed: 311 additions & 32 deletions

File tree

content.js

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,57 @@
11
let enabled = true;
2-
let targetLanguage = 'es';
2+
let targetLanguages = ['es']; // Default to Spanish
3+
let lastWord = '';
4+
let translationTimeout = null;
35

4-
chrome.storage.sync.get(['enabled', 'language'], function(result) {
6+
chrome.storage.sync.get(['enabled', 'languages'], function(result) {
57
enabled = result.enabled !== undefined ? result.enabled : true;
6-
targetLanguage = result.language || 'es';
8+
targetLanguages = result.languages || ['es'];
79
});
810

911
chrome.storage.onChanged.addListener(function(changes, namespace) {
1012
if (changes.enabled) {
1113
enabled = changes.enabled.newValue;
1214
}
13-
if (changes.language) {
14-
targetLanguage = changes.language.newValue;
15+
if (changes.languages) {
16+
targetLanguages = changes.languages.newValue;
1517
}
1618
});
1719

18-
function translateWord(word) {
19-
return new Promise((resolve, reject) => {
20-
chrome.runtime.sendMessage({action: 'translate', word, targetLanguage}, response => {
21-
if (response.error) {
22-
reject(new Error(response.error));
23-
} else {
24-
resolve(response.translation);
25-
}
26-
});
27-
});
20+
function translateWord(word, languages) {
21+
return Promise.all(languages.map(lang =>
22+
new Promise((resolve, reject) => {
23+
chrome.runtime.sendMessage({action: 'translate', word, targetLanguage: lang}, response => {
24+
if (response.error) {
25+
reject(new Error(response.error));
26+
} else {
27+
resolve(response.translation);
28+
}
29+
});
30+
})
31+
));
32+
}
33+
34+
function updateWordDisplay(wordElement, originalWord) {
35+
if (originalWord !== lastWord) {
36+
lastWord = originalWord;
37+
clearTimeout(translationTimeout);
38+
39+
translationTimeout = setTimeout(() => {
40+
translateWord(originalWord, targetLanguages).then(translations => {
41+
const allWords = [originalWord, ...translations];
42+
const displayText = allWords.join(' - ');
43+
44+
// Adjust font size if the text is too long
45+
if (displayText.length > 30) {
46+
wordElement.style.fontSize = '52px';
47+
} else {
48+
wordElement.style.fontSize = '72px';
49+
}
50+
51+
wordElement.textContent = displayText;
52+
}).catch(error => console.error('Translation error:', error));
53+
}, 500); // Wait for 500ms before translating
54+
}
2855
}
2956

3057
const observer = new MutationObserver(mutations => {
@@ -34,10 +61,8 @@ const observer = new MutationObserver(mutations => {
3461
if (mutation.type === 'childList') {
3562
const wordElement = document.querySelector('#rs-word span');
3663
if (wordElement) {
37-
const originalWord = wordElement.textContent;
38-
translateWord(originalWord).then(translatedWord => {
39-
wordElement.textContent = translatedWord;
40-
}).catch(error => console.error('Translation error:', error));
64+
const originalWord = wordElement.textContent.split(' - ')[0]; // Get only the first word
65+
updateWordDisplay(wordElement, originalWord);
4166
}
4267
}
4368
});

popup.html

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,34 @@
22
<html>
33
<head>
44
<style>
5-
body { width: 250px; padding: 10px; }
5+
body { width: 300px; padding: 10px; }
66
#languageSearch { width: 100%; margin-top: 10px; }
7-
#languageList { max-height: 200px; overflow-y: auto; margin-top: 10px; }
7+
#languageList { max-height: 200px; overflow-y: auto; margin-top: 10px; box-shadow: 0 -2px 0 0 black; border-bottom: 2px solid black;}
8+
.selected { background-color: #e0e0e0; }
9+
#openWordsPage {
10+
display: block;
11+
width: 72.5%;
12+
margin-top: 10px;
13+
padding: 5px;
14+
text-align: center;
15+
background-color: #4CAF50;
16+
color: white;
17+
text-decoration: none;
18+
border-radius: 4px;
19+
}
20+
#openWordsPage:hover {
21+
background-color: #45a049;
22+
}
823
</style>
924
</head>
1025
<body>
1126
<label>
1227
<input type="checkbox" id="enableTranslation"> Enable Translation
1328
</label>
29+
<p>Select up to 2 languages (in addition to English):</p>
1430
<input type="text" id="languageSearch" placeholder="Search language...">
1531
<div id="languageList"></div>
32+
<a id="openWordsPage" href="https://rapscript.net/words/" target="_blank">Go to RapScript Words</a>
1633
<script src="popup.js"></script>
1734
</body>
1835
</html>

popup.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ document.addEventListener('DOMContentLoaded', function() {
44
const languageList = document.getElementById('languageList');
55

66
let languages = [];
7-
let selectedLanguage = 'es';
7+
let selectedLanguages = ['es'];
88

99
// Fetch languages from Google Translate
1010
fetch('https://translate.googleapis.com/translate_a/l?client=gtx&dt=t')
@@ -15,9 +15,9 @@ document.addEventListener('DOMContentLoaded', function() {
1515
})
1616
.catch(error => console.error('Error fetching languages:', error));
1717

18-
chrome.storage.sync.get(['enabled', 'language'], function(result) {
18+
chrome.storage.sync.get(['enabled', 'languages'], function(result) {
1919
enableCheckbox.checked = result.enabled !== undefined ? result.enabled : true;
20-
selectedLanguage = result.language || 'es';
20+
selectedLanguages = result.languages || ['es'];
2121
updateLanguageList();
2222
});
2323

@@ -33,18 +33,33 @@ document.addEventListener('DOMContentLoaded', function() {
3333
lang.name.toLowerCase().includes(searchTerm) || lang.code.toLowerCase().includes(searchTerm)
3434
);
3535

36-
languageList.innerHTML = filteredLanguages.map(lang =>
37-
`<div>
38-
<input type="radio" name="language" id="${lang.code}" value="${lang.code}" ${lang.code === selectedLanguage ? 'checked' : ''}>
36+
// Separate selected and unselected languages
37+
const selected = filteredLanguages.filter(lang => selectedLanguages.includes(lang.code));
38+
const unselected = filteredLanguages.filter(lang => !selectedLanguages.includes(lang.code));
39+
40+
// Combine selected and unselected languages
41+
const sortedLanguages = [...selected, ...unselected];
42+
43+
languageList.innerHTML = sortedLanguages.map(lang =>
44+
`<div class="${selectedLanguages.includes(lang.code) ? 'selected' : ''}">
45+
<input type="checkbox" id="${lang.code}" value="${lang.code}" ${selectedLanguages.includes(lang.code) ? 'checked' : ''}>
3946
<label for="${lang.code}">${lang.name} (${lang.code})</label>
4047
</div>`
4148
).join('');
4249

43-
languageList.addEventListener('change', function(e) {
44-
if (e.target.type === 'radio') {
45-
selectedLanguage = e.target.value;
46-
chrome.storage.sync.set({language: selectedLanguage});
47-
}
50+
languageList.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
51+
checkbox.addEventListener('change', function() {
52+
if (this.checked && selectedLanguages.length < 2) {
53+
selectedLanguages.push(this.value);
54+
} else if (!this.checked) {
55+
selectedLanguages = selectedLanguages.filter(lang => lang !== this.value);
56+
} else {
57+
this.checked = false;
58+
}
59+
chrome.storage.sync.set({languages: selectedLanguages}, function() {
60+
updateLanguageList();
61+
});
62+
});
4863
});
4964
}
5065
});

v0.1.rar

3.32 KB
Binary file not shown.

v0.1/background.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2+
if (request.action === 'translate') {
3+
translateWord(request.word, request.targetLanguage)
4+
.then(translation => sendResponse({translation}))
5+
.catch(error => sendResponse({error: error.toString()}));
6+
return true;
7+
}
8+
});
9+
10+
async function translateWord(word, targetLanguage) {
11+
const translateUrl = `https://translate.google.com/translate_a/single?client=gtx&sl=auto&tl=${targetLanguage}&dt=t&q=${encodeURIComponent(word)}`;
12+
13+
try {
14+
const response = await fetch(translateUrl);
15+
const data = await response.json();
16+
return data[0][0][0];
17+
} catch (error) {
18+
console.error('Translation error:', error);
19+
throw error;
20+
}
21+
}

v0.1/content.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
let enabled = true;
2+
let targetLanguages = ['es']; // Default to Spanish
3+
let lastWord = '';
4+
let translationTimeout = null;
5+
6+
chrome.storage.sync.get(['enabled', 'languages'], function(result) {
7+
enabled = result.enabled !== undefined ? result.enabled : true;
8+
targetLanguages = result.languages || ['es'];
9+
});
10+
11+
chrome.storage.onChanged.addListener(function(changes, namespace) {
12+
if (changes.enabled) {
13+
enabled = changes.enabled.newValue;
14+
}
15+
if (changes.languages) {
16+
targetLanguages = changes.languages.newValue;
17+
}
18+
});
19+
20+
function translateWord(word, languages) {
21+
return Promise.all(languages.map(lang =>
22+
new Promise((resolve, reject) => {
23+
chrome.runtime.sendMessage({action: 'translate', word, targetLanguage: lang}, response => {
24+
if (response.error) {
25+
reject(new Error(response.error));
26+
} else {
27+
resolve(response.translation);
28+
}
29+
});
30+
})
31+
));
32+
}
33+
34+
function updateWordDisplay(wordElement, originalWord) {
35+
if (originalWord !== lastWord) {
36+
lastWord = originalWord;
37+
clearTimeout(translationTimeout);
38+
39+
translationTimeout = setTimeout(() => {
40+
translateWord(originalWord, targetLanguages).then(translations => {
41+
const allWords = [originalWord, ...translations];
42+
const displayText = allWords.join(' - ');
43+
44+
// Adjust font size if the text is too long
45+
if (displayText.length > 30) {
46+
wordElement.style.fontSize = '52px';
47+
} else {
48+
wordElement.style.fontSize = '72px';
49+
}
50+
51+
wordElement.textContent = displayText;
52+
}).catch(error => console.error('Translation error:', error));
53+
}, 500); // Wait for 500ms before translating
54+
}
55+
}
56+
57+
const observer = new MutationObserver(mutations => {
58+
if (!enabled) return;
59+
60+
mutations.forEach(mutation => {
61+
if (mutation.type === 'childList') {
62+
const wordElement = document.querySelector('#rs-word span');
63+
if (wordElement) {
64+
const originalWord = wordElement.textContent.split(' - ')[0]; // Get only the first word
65+
updateWordDisplay(wordElement, originalWord);
66+
}
67+
}
68+
});
69+
});
70+
71+
observer.observe(document.body, {
72+
childList: true,
73+
subtree: true
74+
});

v0.1/manifest.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"manifest_version": 3,
3+
"name": "RapScript Translator",
4+
"version": "0.1.0",
5+
"description": "Translates words on RapScript in real-time",
6+
"permissions": [
7+
"activeTab",
8+
"storage",
9+
"scripting"
10+
],
11+
"host_permissions": [
12+
"https://rapscript.net/*",
13+
"https://translate.google.com/*"
14+
],
15+
"action": {
16+
"default_popup": "popup.html"
17+
},
18+
"content_scripts": [
19+
{
20+
"matches": ["https://rapscript.net/*"],
21+
"js": ["content.js"]
22+
}
23+
],
24+
"background": {
25+
"service_worker": "background.js"
26+
}
27+
}

v0.1/popup.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<style>
5+
body { width: 300px; padding: 10px; }
6+
#languageSearch { width: 100%; margin-top: 10px; }
7+
#languageList { max-height: 200px; overflow-y: auto; margin-top: 10px; box-shadow: 0 -2px 0 0 black; border-bottom: 2px solid black;}
8+
.selected { background-color: #e0e0e0; }
9+
#openWordsPage {
10+
display: block;
11+
width: 72.5%;
12+
margin-top: 10px;
13+
padding: 5px;
14+
text-align: center;
15+
background-color: #4CAF50;
16+
color: white;
17+
text-decoration: none;
18+
border-radius: 4px;
19+
}
20+
#openWordsPage:hover {
21+
background-color: #45a049;
22+
}
23+
</style>
24+
</head>
25+
<body>
26+
<label>
27+
<input type="checkbox" id="enableTranslation"> Enable Translation
28+
</label>
29+
<p>Select up to 2 languages (in addition to English):</p>
30+
<input type="text" id="languageSearch" placeholder="Search language...">
31+
<div id="languageList"></div>
32+
<a id="openWordsPage" href="https://rapscript.net/words/" target="_blank">Go to RapScript Words</a>
33+
<script src="popup.js"></script>
34+
</body>
35+
</html>

0 commit comments

Comments
 (0)