├── images
├── moon.png
└── sun.png
├── index.html
├── languages.js
├── script.js
└── style.css
/images/moon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opensource-coding/Javascript-Language-Translater/9c15ae7daf11f0a1c1339e1576f554b7769d18cf/images/moon.png
--------------------------------------------------------------------------------
/images/sun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opensource-coding/Javascript-Language-Translater/9c15ae7daf11f0a1c1339e1576f554b7769d18cf/images/sun.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
15 |
16 | Language Translater
17 |
18 |
19 |
20 |
28 |
29 |
30 |
63 |
64 |
69 |
70 |
71 |
72 |
To :
73 |
74 |
75 |
76 | Englsih
77 |
78 |
79 |
83 |
84 |
85 |
92 |
93 |
Download as a document!
94 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/languages.js:
--------------------------------------------------------------------------------
1 | const languages = [
2 | {
3 | no: "0",
4 | name: "Auto",
5 | native: "Detect",
6 | code: "auto",
7 | },
8 | {
9 | no: "1",
10 | name: "Afrikaans",
11 | native: "Afrikaans",
12 | code: "af",
13 | },
14 | {
15 | no: "2",
16 | name: "Albanian",
17 | native: "Shqip",
18 | code: "sq",
19 | },
20 | {
21 | no: "3",
22 | name: "Arabic",
23 | native: "عربي",
24 | code: "ar",
25 | },
26 | {
27 | no: "4",
28 | name: "Armenian",
29 | native: "Հայերէն",
30 | code: "hy",
31 | },
32 | {
33 | no: "5",
34 | name: "Azerbaijani",
35 | native: "آذربایجان دیلی",
36 | code: "az",
37 | },
38 | {
39 | no: "6",
40 | name: "Basque",
41 | native: "Euskara",
42 | code: "eu",
43 | },
44 | {
45 | no: "7",
46 | name: "Belarusian",
47 | native: "Беларуская",
48 | code: "be",
49 | },
50 | {
51 | no: "8",
52 | name: "Bulgarian",
53 | native: "Български",
54 | code: "bg",
55 | },
56 | {
57 | no: "9",
58 | name: "Catalan",
59 | native: "Català",
60 | code: "ca",
61 | },
62 | {
63 | no: "10",
64 | name: "Chinese (Simplified)",
65 | native: "中文简体",
66 | code: "zh-CN",
67 | },
68 | {
69 | no: "11",
70 | name: "Chinese (Traditional)",
71 | native: "中文繁體",
72 | code: "zh-TW",
73 | },
74 | {
75 | no: "12",
76 | name: "Croatian",
77 | native: "Hrvatski",
78 | code: "hr",
79 | },
80 | {
81 | no: "13",
82 | name: "Czech",
83 | native: "Čeština",
84 | code: "cs",
85 | },
86 | {
87 | no: "14",
88 | name: "Danish",
89 | native: "Dansk",
90 | code: "da",
91 | },
92 | {
93 | no: "15",
94 | name: "Dutch",
95 | native: "Nederlands",
96 | code: "nl",
97 | },
98 | {
99 | no: "16",
100 | name: "English",
101 | native: "English",
102 | code: "en",
103 | },
104 | {
105 | no: "17",
106 | name: "Estonian",
107 | native: "Eesti keel",
108 | code: "et",
109 | },
110 | {
111 | no: "18",
112 | name: "Filipino",
113 | native: "Filipino",
114 | code: "tl",
115 | },
116 | {
117 | no: "19",
118 | name: "Finnish",
119 | native: "Suomi",
120 | code: "fi",
121 | },
122 | {
123 | no: "20",
124 | name: "French",
125 | native: "Français",
126 | code: "fr",
127 | },
128 | {
129 | no: "21",
130 | name: "Galician",
131 | native: "Galego",
132 | code: "gl",
133 | },
134 | {
135 | no: "22",
136 | name: "Georgian",
137 | native: "ქართული",
138 | code: "ka",
139 | },
140 | {
141 | no: "23",
142 | name: "German",
143 | native: "Deutsch",
144 | code: "de",
145 | },
146 | {
147 | no: "24",
148 | name: "Greek",
149 | native: "Ελληνικά",
150 | code: "el",
151 | },
152 | {
153 | no: "25",
154 | name: "Haitian Creole",
155 | native: "Kreyòl ayisyen",
156 | code: "ht",
157 | },
158 | {
159 | no: "26",
160 | name: "Hebrew",
161 | native: "עברית",
162 | code: "iw",
163 | },
164 | {
165 | no: "27",
166 | name: "Hindi",
167 | native: "हिन्दी",
168 | code: "hi",
169 | },
170 | {
171 | no: "28",
172 | name: "Hungarian",
173 | native: "Magyar",
174 | code: "hu",
175 | },
176 | {
177 | no: "29",
178 | name: "Icelandic",
179 | native: "Íslenska",
180 | code: "is",
181 | },
182 | {
183 | no: "30",
184 | name: "Indonesian",
185 | native: "Bahasa Indonesia",
186 | code: "id",
187 | },
188 | {
189 | no: "31",
190 | name: "Irish",
191 | native: "Gaeilge",
192 | code: "ga",
193 | },
194 | {
195 | no: "32",
196 | name: "Italian",
197 | native: "Italiano",
198 | code: "it",
199 | },
200 | {
201 | no: "33",
202 | name: "Japanese",
203 | native: "日本語",
204 | code: "ja",
205 | },
206 | {
207 | no: "34",
208 | name: "Korean",
209 | native: "한국어",
210 | code: "ko",
211 | },
212 | {
213 | no: "35",
214 | name: "Latvian",
215 | native: "Latviešu",
216 | code: "lv",
217 | },
218 | {
219 | no: "36",
220 | name: "Lithuanian",
221 | native: "Lietuvių kalba",
222 | code: "lt",
223 | },
224 | {
225 | no: "37",
226 | name: "Macedonian",
227 | native: "Македонски",
228 | code: "mk",
229 | },
230 | {
231 | no: "38",
232 | name: "Malay",
233 | native: "Malay",
234 | code: "ms",
235 | },
236 | {
237 | no: "39",
238 | name: "Maltese",
239 | native: "Malti",
240 | code: "mt",
241 | },
242 | {
243 | no: "40",
244 | name: "Norwegian",
245 | native: "Norsk",
246 | code: "no",
247 | },
248 | {
249 | no: "41",
250 | name: "Persian",
251 | native: "فارسی",
252 | code: "fa",
253 | },
254 | {
255 | no: "42",
256 | name: "Polish",
257 | native: "Polski",
258 | code: "pl",
259 | },
260 | {
261 | no: "43",
262 | name: "Portuguese",
263 | native: "Português",
264 | code: "pt",
265 | },
266 | {
267 | no: "44",
268 | name: "Romanian",
269 | native: "Română",
270 | code: "ro",
271 | },
272 | {
273 | no: "45",
274 | name: "Russian",
275 | native: "Русский",
276 | code: "ru",
277 | },
278 | {
279 | no: "46",
280 | name: "Serbian",
281 | native: "Српски",
282 | code: "sr",
283 | },
284 | {
285 | no: "47",
286 | name: "Slovak",
287 | native: "Slovenčina",
288 | code: "sk",
289 | },
290 | {
291 | no: "48",
292 | name: "Slovenian",
293 | native: "Slovensko",
294 | code: "sl",
295 | },
296 | {
297 | no: "49",
298 | name: "Spanish",
299 | native: "Español",
300 | code: "es",
301 | },
302 | {
303 | no: "50",
304 | name: "Swahili",
305 | native: "Kiswahili",
306 | code: "sw",
307 | },
308 | {
309 | no: "51",
310 | name: "Swedish",
311 | native: "Svenska",
312 | code: "sv",
313 | },
314 | {
315 | no: "52",
316 | name: "Thai",
317 | native: "ไทย",
318 | code: "th",
319 | },
320 | {
321 | no: "53",
322 | name: "Turkish",
323 | native: "Türkçe",
324 | code: "tr",
325 | },
326 | {
327 | no: "54",
328 | name: "Ukrainian",
329 | native: "Українська",
330 | code: "uk",
331 | },
332 | {
333 | no: "55",
334 | name: "Urdu",
335 | native: "اردو",
336 | code: "ur",
337 | },
338 | {
339 | no: "56",
340 | name: "Vietnamese",
341 | native: "Tiếng Việt",
342 | code: "vi",
343 | },
344 | {
345 | no: "57",
346 | name: "Welsh",
347 | native: "Cymraeg",
348 | code: "cy",
349 | },
350 | {
351 | no: "58",
352 | name: "Yiddish",
353 | native: "ייִדיש",
354 | code: "yi",
355 | },
356 | ];
357 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | const dropdowns = document.querySelectorAll(".dropdown-container"),
2 | inputLanguageDropdown = document.querySelector("#input-language"),
3 | outputLanguageDropdown = document.querySelector("#output-language");
4 |
5 | function populateDropdown(dropdown, options) {
6 | dropdown.querySelector("ul").innerHTML = "";
7 | options.forEach((option) => {
8 | const li = document.createElement("li");
9 | const title = option.name + " (" + option.native + ")";
10 | li.innerHTML = title;
11 | li.dataset.value = option.code;
12 | li.classList.add("option");
13 | dropdown.querySelector("ul").appendChild(li);
14 | });
15 | }
16 |
17 | populateDropdown(inputLanguageDropdown, languages);
18 | populateDropdown(outputLanguageDropdown, languages);
19 |
20 | dropdowns.forEach((dropdown) => {
21 | dropdown.addEventListener("click", (e) => {
22 | dropdown.classList.toggle("active");
23 | });
24 |
25 | dropdown.querySelectorAll(".option").forEach((item) => {
26 | item.addEventListener("click", (e) => {
27 | //remove active class from current dropdowns
28 | dropdown.querySelectorAll(".option").forEach((item) => {
29 | item.classList.remove("active");
30 | });
31 | item.classList.add("active");
32 | const selected = dropdown.querySelector(".selected");
33 | selected.innerHTML = item.innerHTML;
34 | selected.dataset.value = item.dataset.value;
35 | translate();
36 | });
37 | });
38 | });
39 | document.addEventListener("click", (e) => {
40 | dropdowns.forEach((dropdown) => {
41 | if (!dropdown.contains(e.target)) {
42 | dropdown.classList.remove("active");
43 | }
44 | });
45 | });
46 |
47 | const swapBtn = document.querySelector(".swap-position"),
48 | inputLanguage = inputLanguageDropdown.querySelector(".selected"),
49 | outputLanguage = outputLanguageDropdown.querySelector(".selected"),
50 | inputTextElem = document.querySelector("#input-text"),
51 | outputTextElem = document.querySelector("#output-text");
52 |
53 | swapBtn.addEventListener("click", (e) => {
54 | const temp = inputLanguage.innerHTML;
55 | inputLanguage.innerHTML = outputLanguage.innerHTML;
56 | outputLanguage.innerHTML = temp;
57 |
58 | const tempValue = inputLanguage.dataset.value;
59 | inputLanguage.dataset.value = outputLanguage.dataset.value;
60 | outputLanguage.dataset.value = tempValue;
61 |
62 | //swap text
63 | const tempInputText = inputTextElem.value;
64 | inputTextElem.value = outputTextElem.value;
65 | outputTextElem.value = tempInputText;
66 |
67 | translate();
68 | });
69 |
70 | function translate() {
71 | const inputText = inputTextElem.value;
72 | const inputLanguage =
73 | inputLanguageDropdown.querySelector(".selected").dataset.value;
74 | const outputLanguage =
75 | outputLanguageDropdown.querySelector(".selected").dataset.value;
76 | const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${inputLanguage}&tl=${outputLanguage}&dt=t&q=${encodeURI(
77 | inputText
78 | )}`;
79 | fetch(url)
80 | .then((response) => response.json())
81 | .then((json) => {
82 | console.log(json);
83 | outputTextElem.value = json[0].map((item) => item[0]).join("");
84 | })
85 | .catch((error) => {
86 | console.log(error);
87 | });
88 | }
89 | inputTextElem.addEventListener("input", (e) => {
90 | //limit input to 5000 characters
91 | if (inputTextElem.value.length > 5000) {
92 | inputTextElem.value = inputTextElem.value.slice(0, 5000);
93 | }
94 | translate();
95 | });
96 |
97 | const uploadDocument = document.querySelector("#upload-document"),
98 | uploadTitle = document.querySelector("#upload-title");
99 |
100 | uploadDocument.addEventListener("change", (e) => {
101 | const file = e.target.files[0];
102 | if (
103 | file.type === "application/pdf" ||
104 | file.type === "text/plain" ||
105 | file.type === "application/msword" ||
106 | file.type ===
107 | "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
108 | ) {
109 | uploadTitle.innerHTML = file.name;
110 | const reader = new FileReader();
111 | reader.readAsText(file);
112 | reader.onload = (e) => {
113 | inputTextElem.value = e.target.result;
114 | translate();
115 | };
116 | } else {
117 | alert("Please upload a valid file");
118 | }
119 | });
120 |
121 | const downloadBtn = document.querySelector("#download-btn");
122 |
123 | downloadBtn.addEventListener("click", (e) => {
124 | const outputText = outputTextElem.value;
125 | const outputLanguage =
126 | outputLanguageDropdown.querySelector(".selected").dataset.value;
127 | if (outputText) {
128 | const blob = new Blob([outputText], { type: "text/plain" });
129 | const url = URL.createObjectURL(blob);
130 | const a = document.createElement("a");
131 | a.download = `translated-to-${outputLanguage}.txt`;
132 | a.href = url;
133 | a.click();
134 | }
135 | });
136 |
137 | const darkModeCheckbox = document.getElementById("dark-mode-btn");
138 |
139 | darkModeCheckbox.addEventListener("change", () => {
140 | document.body.classList.toggle("dark");
141 | });
142 |
143 | const inputChars = document.querySelector("#input-chars");
144 |
145 | inputTextElem.addEventListener("input", (e) => {
146 | inputChars.innerHTML = inputTextElem.value.length;
147 | });
148 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --primary-color: #356aff;
3 | --bg-color: #f5f5f5;
4 | --light-bg-color: #fff;
5 | --text-color: #111116;
6 | --light-text-color: #cdccd1;
7 | --primary-text-color: #fff;
8 | }
9 | ::-webkit-scrollbar {
10 | width: 5px;
11 | }
12 | ::-webkit-scrollbar-track {
13 | border-radius: 30px;
14 | background: #f1f1f1;
15 | }
16 | ::-webkit-scrollbar-thumb {
17 | border-radius: 30px;
18 | background: var(--primary-color);
19 | }
20 | ::-webkit-scrollbar-thumb:hover {
21 | background: var(--bg-color);
22 | }
23 |
24 | * {
25 | margin: 0;
26 | padding: 0;
27 | box-sizing: border-box;
28 | font-family: "Poppins", sans-serif;
29 | }
30 | body {
31 | min-height: 100vh;
32 | display: flex;
33 | align-items: center;
34 | justify-content: center;
35 | color: var(--text-color);
36 | background-color: var(--bg-color);
37 | }
38 | body.dark {
39 | --bg-color: #111116;
40 | --light-bg-color: #1c1b20;
41 | --text-color: #fff;
42 | --light-text-color: #58575c;
43 | }
44 | .container {
45 | position: relative;
46 | width: 1200px;
47 | padding: 0 20px;
48 | display: flex;
49 | gap: 10px;
50 | }
51 | .container .card {
52 | flex: 1;
53 | padding: 30px;
54 | border-radius: 20px;
55 | background-color: var(--light-bg-color);
56 | }
57 | .container .card .from,
58 | .container .card .to {
59 | display: flex;
60 | align-items: center;
61 | gap: 20px;
62 | }
63 | .container .card .from {
64 | margin-right: 20px;
65 | }
66 | .container .card .to {
67 | margin-left: 20px;
68 | }
69 | .container .card .heading {
70 | font-size: 0.8rem;
71 | font-weight: 600;
72 | color: var(--light-text-color);
73 | white-space: nowrap;
74 | }
75 | .dropdown-container {
76 | position: relative;
77 | margin-bottom: 10px;
78 | width: 100%;
79 | }
80 | .dropdown-container .dropdown-toggle {
81 | display: flex;
82 | align-items: center;
83 | padding: 15px 20px;
84 | border-radius: 30px;
85 | background-color: var(--bg-color);
86 | cursor: pointer;
87 | transition: all 0.3s;
88 | }
89 | .dropdown-container .dropdown-toggle span {
90 | flex: 1;
91 | margin-left: 10px;
92 | }
93 | .dropdown-container .dropdown-toggle ion-icon {
94 | font-size: 20px;
95 | transition: transform 0.3s ease;
96 | }
97 | .dropdown-container.active .dropdown-toggle {
98 | border-radius: 20px 20px 0 0;
99 | }
100 | .dropdown-container.active .dropdown-toggle ion-icon:last-child {
101 | transform: rotate(180deg);
102 | }
103 | .dropdown-container .dropdown-menu {
104 | position: absolute;
105 | top: 100%;
106 | left: 0;
107 | width: 100%;
108 | height: 300px;
109 | overflow: auto;
110 | display: none;
111 | padding: 20px;
112 | z-index: 1;
113 | list-style: none;
114 | flex-direction: column;
115 | background-color: var(--bg-color);
116 | transition: all 1s;
117 | border-radius: 0 0 20px 20px;
118 | }
119 | .dropdown-container .dropdown-menu::-webkit-scrollbar {
120 | display: none;
121 | }
122 | .dropdown-container.active .dropdown-menu {
123 | display: flex;
124 | }
125 |
126 | .dropdown-container .dropdown-menu li {
127 | padding: 10px 20px;
128 | border-radius: 20px;
129 | cursor: pointer;
130 | margin-bottom: 5px;
131 | border-bottom: 1px solid var(--light-bg-color);
132 | transition: all 0.3s ease;
133 | }
134 | .dropdown-container .dropdown-menu li:hover {
135 | background-color: var(--light-bg-color);
136 | }
137 | .dropdown-container .dropdown-menu li.active {
138 | color: var(--primary-text-color);
139 | background-color: var(--primary-color);
140 | }
141 | .container .text-area {
142 | position: relative;
143 | }
144 | .container textarea {
145 | width: 100%;
146 | padding: 20px;
147 | margin: 10px 0;
148 | background-color: transparent;
149 | resize: none;
150 | outline: none;
151 | border: none;
152 | color: var(--text-color);
153 | font-size: 18px;
154 | font-family: "Poppins", sans-serif;
155 | }
156 | .container .text-area .chars {
157 | position: absolute;
158 | bottom: 0;
159 | right: 0;
160 | padding: 10px;
161 | font-size: 0.8rem;
162 | color: var(--light-text-color);
163 | }
164 | .container .center {
165 | position: relative;
166 | }
167 | .swap-position {
168 | display: flex;
169 | align-items: center;
170 | justify-content: center;
171 | position: absolute;
172 | top: 30px;
173 | left: 50%;
174 | transform: translateX(-50%);
175 | width: 50px;
176 | height: 50px;
177 | border-radius: 50%;
178 | cursor: pointer;
179 | border: 5px solid var(--bg-color);
180 | transition: all 0.3s ease;
181 | color: var(--primary-text-color);
182 | background-color: var(--primary-color);
183 | }
184 | .swap-position ion-icon {
185 | font-size: 25px;
186 | }
187 | .swap-position:hover {
188 | transform: translateX(-50%) scale(1.1);
189 | }
190 | .card-bottom {
191 | display: flex;
192 | align-items: center;
193 | flex-direction: column;
194 | justify-content: center;
195 | padding-top: 20px;
196 | border-top: 2px solid var(--bg-color);
197 | }
198 | .card-bottom p {
199 | margin-bottom: 20px;
200 | }
201 | .card-bottom label {
202 | height: 50px;
203 | display: flex;
204 | align-items: center;
205 | gap: 20px;
206 | padding: 0 20px;
207 | cursor: pointer;
208 | border-radius: 30px;
209 | background-color: var(--bg-color);
210 | }
211 | .card-bottom label:hover {
212 | color: var(--primary-text-color);
213 | background-color: var(--primary-color);
214 | }
215 | .card-bottom span {
216 | font-size: 12px;
217 | pointer-events: none;
218 | }
219 | .card-bottom ion-icon {
220 | font-size: 20px;
221 | }
222 |
223 | .card-bottom button {
224 | height: 50px;
225 | display: flex;
226 | align-items: center;
227 | gap: 20px;
228 | padding: 0 20px;
229 | border-radius: 30px;
230 | border: none;
231 | outline: none;
232 | color: var(--text-color);
233 | cursor: pointer;
234 | background-color: var(--bg-color);
235 | }
236 | .card-bottom button:hover {
237 | color: var(--primary-text-color);
238 | background-color: var(--primary-color);
239 | }
240 |
241 | .mode {
242 | position: fixed;
243 | bottom: 20px;
244 | right: 20px;
245 | z-index: 1;
246 | }
247 | .toggle {
248 | position: relative;
249 | cursor: pointer;
250 | }
251 | .toggle-track {
252 | width: 24px;
253 | height: 50px;
254 | border-radius: 30px;
255 | display: flex;
256 | align-items: center;
257 | flex-direction: column;
258 | padding: 3px 0;
259 | justify-content: space-between;
260 | border: 1px solid var(--light-text-color);
261 | background-color: var(--light-bg-color);
262 | transition: all 0.2s ease;
263 | }
264 | .toggle-checkbox {
265 | display: none;
266 | }
267 | .toggle-thumb {
268 | position: absolute;
269 | top: 2px;
270 | left: 2px;
271 | width: 20px;
272 | height: 20px;
273 | border-radius: 50%;
274 | background-color: var(--primary-color);
275 | transition: all 0.5s;
276 | }
277 | .toggle input:checked ~ .toggle-thumb {
278 | transform: translateY(25px);
279 | }
280 | .toggle img {
281 | width: 20px;
282 | height: 20px;
283 | }
284 |
285 | /* media quiries */
286 | @media (max-width: 800px) {
287 | .container {
288 | width: 100%;
289 | margin-top: 20px;
290 | flex-direction: column;
291 | }
292 | .container .card {
293 | width: 100%;
294 | }
295 | .container .card .from {
296 | margin-right: 0;
297 | }
298 | .container .card .to {
299 | margin-left: 0;
300 | }
301 | .container .card .from,
302 | .container .card .to {
303 | flex-direction: column;
304 | }
305 |
306 | .swap-position {
307 | top: 50%;
308 | left: 50%;
309 | transform: translate(-50%, -50%);
310 | }
311 | .swap-position:hover {
312 | transform: translate(-50%, -50%) scale(1.1);
313 | }
314 | .swap-position ion-icon {
315 | transform: rotate(90deg);
316 | }
317 | }
318 |
--------------------------------------------------------------------------------