Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,4 @@ async function translateAllText(progressText, progressFill) {
}

return translatedCount;
}
}
72 changes: 32 additions & 40 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,43 +1,35 @@
{
"manifest_version": 3,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"default_locale": "en",
"version": "1.0",
"icons": {
"manifest_version": 3,
"name": "Hinglish Translator",
"version": "1.0",
"description": "Translate English text to Hinglish/Hindi using Groq API",
"permissions": ["storage", "contextMenus", "scripting", "tabs", "activeTab"],
"host_permissions": ["https://api.groq.com/*"],
"default_locale": "en",
"icons": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"background": {
"service_worker": "background.js",
"type": "module"
},
"action": {
"default_popup": "popup/welcome.html",
"default_icon": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"permissions": [
"storage",
"activeTab",
"contextMenus",
"scripting",
"tabs"
],
"host_permissions": [
"https://api.groq.com/*"
],
"background": {
"service_worker": "background.js",
"type": "module"
},
"action": {
"default_popup": "popup/welcome.html",
"default_icon": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png"
}
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["styles/content.css"],
"run_at": "document_idle"
}
]
}
"48": "icons/icon48.png"
}
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["styles/content.css"],
"run_at": "document_idle"
}
]
}
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "hinglish-ai-translator",
"version": "1.0.0",
"description": "A powerful and intuitive Chrome extension that brings seamless translation and AI-powered explanations to your browsing experience. Transform any English text into Hinglish (Hindi written in English letters) or Hindi with just a right-click!",
"main": "background.js",
"scripts": {
"start": "node background.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
92 changes: 5 additions & 87 deletions popup/welcome.html
Original file line number Diff line number Diff line change
@@ -1,69 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta charset="UTF-8" />
<title>Hinglish Translator - Welcome</title>
<link rel="stylesheet" href="popup.css">
<style>
.dark-mode {
background-color: #222;
color: #f1f1f1;
}

.light-mode {
background-color: #fffbea;
color: #222;
}

.theme-toggle {
position: absolute;
top: 10px;
right: 10px;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
}

.setup {
max-width: 400px;
margin: 100px auto;
padding: 20px;
border-radius: 10px;
background-color: inherit;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.setup input {
width: 100%;
padding: 10px;
margin-top: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 1rem;
}

.setup button {
margin-top: 15px;
padding: 10px 20px;
font-size: 1rem;
cursor: pointer;
border: none;
border-radius: 5px;
background-color: #4CAF50;
color: white;
}

.setup p {
margin-top: 20px;
font-size: 0.95rem;
}

.setup a {
color: inherit;
text-decoration: underline;
}
</style>
<link rel="stylesheet" href="popup.css" />
</head>
<body class="light-mode">
<button class="theme-toggle" id="themeToggle">🌙</button>
Expand All @@ -72,36 +12,14 @@
<h2>Welcome to Hinglish Translator</h2>
<p>Please enter your Groq API key to enable translations:</p>

<input type="password" id="apiKeyInput" placeholder="Enter your Groq API key">
<input type="password" id="apiKeyInput" placeholder="Enter your Groq API key" />
<button id="saveApiKey">Save Key</button>

<p>Your key will be stored locally in Chrome and only used for translation requests.</p>
<p>Don't have a key? <a href="https://console.groq.com/keys" target="_blank">Get one from Groq</a></p>
</div>

<script>
const themeToggle = document.getElementById('themeToggle');
const body = document.body;

// Load saved theme from localStorage
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
body.className = savedTheme;
themeToggle.textContent = savedTheme === 'dark-mode' ? '☀️' : '🌙';
}

themeToggle.addEventListener('click', () => {
if (body.classList.contains('dark-mode')) {
body.classList.replace('dark-mode', 'light-mode');
themeToggle.textContent = '🌙';
localStorage.setItem('theme', 'light-mode');
} else {
body.classList.replace('light-mode', 'dark-mode');
themeToggle.textContent = '☀️';
localStorage.setItem('theme', 'dark-mode');
}
});
</script>
<script src="welcome.js"></script>
<!-- ✅ Load external JS with type="module" -->
<script src="welcome.js" type="module"></script>
</body>
</html>
113 changes: 32 additions & 81 deletions popup/welcome.js
Original file line number Diff line number Diff line change
@@ -1,85 +1,36 @@
document.addEventListener('DOMContentLoaded', async () => {
// Check if API key exists
const { groqApiKey } = await chrome.storage.local.get(['groqApiKey']);
if (groqApiKey) {
window.location.href = 'popup.html';
return;
}

const apiKeyInput = document.getElementById('apiKeyInput');
const saveButton = document.getElementById('saveApiKey');
const errorMessage = document.createElement('div');
errorMessage.style.color = '#d93025';
errorMessage.style.marginTop = '10px';
document.querySelector('.setup').appendChild(errorMessage);

saveButton.addEventListener('click', async () => {
const apiKey = apiKeyInput.value.trim();
if (!apiKey) {
errorMessage.textContent = 'Please enter your API key';
return;
}

try {
// Save API key first
await chrome.storage.local.set({ groqApiKey: apiKey });

// Test the API key with a simple request
const response = await fetch('https://api.groq.com/openai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
messages: [{
role: "user",
content: "Hello"
}],
model: "meta-llama/llama-4-scout-17b-16e-instruct",
temperature: 0.7,
max_tokens: 10
})
});

if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error?.message || `API error: ${response.status}`);
}
const themeToggle = document.getElementById('themeToggle');
const body = document.body;

// If we get here, the API key is valid
window.location.href = 'popup.html';
} catch (error) {
console.error('API Key validation error:', error);
// Remove invalid key
await chrome.storage.local.remove(['groqApiKey']);
errorMessage.textContent = error.message || 'Invalid API key. Please try again.';
}
});

// === Theme Toggle Setup ===
const themeToggle = document.getElementById('themeToggle');
const body = document.body;

let savedTheme = localStorage.getItem('theme');
if (!savedTheme) {
savedTheme = 'light-mode';
localStorage.setItem('theme', savedTheme);
}
body.classList.add(savedTheme);
// Load saved theme from localStorage
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
body.className = savedTheme;
themeToggle.textContent = savedTheme === 'dark-mode' ? '☀️' : '🌙';
}

themeToggle.addEventListener('click', () => {
if (body.classList.contains('dark-mode')) {
body.classList.replace('dark-mode', 'light-mode');
themeToggle.textContent = '🌙';
localStorage.setItem('theme', 'light-mode');
} else {
body.classList.replace('light-mode', 'dark-mode');
themeToggle.textContent = '☀️';
localStorage.setItem('theme', 'dark-mode');
}
});

themeToggle.addEventListener('click', () => {
if (body.classList.contains('dark-mode')) {
body.classList.remove('dark-mode');
body.classList.add('light-mode');
localStorage.setItem('theme', 'light-mode');
themeToggle.textContent = '🌙';
} else {
body.classList.remove('light-mode');
body.classList.add('dark-mode');
localStorage.setItem('theme', 'dark-mode');
themeToggle.textContent = '☀️';
}
});
// Save API key
const saveBtn = document.getElementById('saveApiKey');
const input = document.getElementById('apiKeyInput');

saveBtn.addEventListener('click', () => {
const key = input.value.trim();
if (key) {
chrome.storage.local.set({ groqApiKey: key }, () => {
alert('API key saved!');
});
} else {
alert('Please enter a valid API key.');
}
});