Skip to content

Commit c79233a

Browse files
authored
Release v1.5 (#1)
* Optimized youtube to not translate all words on each new caption * move tokes to env file * Optimize netflix to not translate everything unless user ask for a word or a whole caption. * version 1.2 * [ Task ] Add proxy service, all request will be done associated with an alternative URL which is the proxy version of each URL. * [ Task ] Add dedicated api_host for Mixpanel * [ Task ] Add loading state when a hovered phrase is waiting to beeing translated. * Add Sorani lang, and fix manifext violation. * [ Bugfix ] change event of select element. * v1.5
1 parent 2bc069a commit c79233a

File tree

20 files changed

+238
-51
lines changed

20 files changed

+238
-51
lines changed

.env.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
MIXPANEL_TRACKING_ID=
1+
MIXPANEL_TRACKING_ID=
2+
MIXPANEL_API_HOST=
3+
GOOGLE_TRANSLATE_KEY=
4+
GOOGLE_TRANSLATE_PROXY_URL=

learn-by-subtitle.code-workspace

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"folders": [
3+
{
4+
"path": "."
5+
}
6+
],
7+
"settings": {}
8+
}

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
2-
"version": "1.1.0",
2+
"version": "1.3.0",
33
"scripts": {
44
"serve": "webpack --watch",
5-
"build": "webpack --mode=production"
5+
"build": "webpack --mode=production",
6+
"zip": "cd dist && zip -r subturtle.zip . && mv subturtle.zip ../subturtle.zip"
67
},
78
"devDependencies": {
89
"@types/chrome": "^0.0.193",
@@ -27,6 +28,7 @@
2728
"webpack-cli": "^4.10.0"
2829
},
2930
"dependencies": {
31+
"axios": "^1.3.4",
3032
"mixpanel-browser": "^2.45.0",
3133
"text-cleaner": "^1.2.1",
3234
"tiny-emitter": "^2.1.0",
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Dictionary } from "../types/general.type";
2+
3+
type requestMode = 'no-cors' | 'same-origin'
4+
5+
export function postData(url = '', data = {}, header = {}, mode?:requestMode) {
6+
return fetch(url, {
7+
method: 'POST',
8+
headers: {
9+
'Content-Type': 'application/json',
10+
...header
11+
},
12+
mode,
13+
body: JSON.stringify(data)
14+
})
15+
.then((res) => {
16+
if (res.status == 200) return res.json() as Promise<Dictionary>;
17+
else throw res as Dictionary;
18+
});
19+
}
20+
21+
export function getData(url = '', header = {}, mode?:requestMode) {
22+
return fetch(url, {
23+
method: 'GET',
24+
headers: {
25+
'Content-Type': 'application/json',
26+
...header
27+
},
28+
mode,
29+
})
30+
.then((res) => {
31+
if (res.status == 200) return res.json() as Promise<Dictionary>;
32+
else throw res as Dictionary;
33+
})
34+
}
35+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Dictionary } from "../types/general.type";
2+
import { getData, postData } from "./http.service";
3+
4+
type UrlAndProxy = {
5+
url: string,
6+
proxyUrl?: string | null,
7+
proxyHeader?: Dictionary | null,
8+
}
9+
10+
const urlsNeedToBeProxied: { [key: string]: boolean } = {}
11+
12+
function getURLHash(method: string, url: string) {
13+
return window.btoa(method + url);
14+
}
15+
16+
function post({ url = '', proxyUrl, proxyHeader }: UrlAndProxy, data = {}) {
17+
18+
const urlHash = getURLHash('post', url);
19+
const needToBeProxied = urlsNeedToBeProxied[urlHash] || false;
20+
21+
if (!needToBeProxied) {
22+
return postData(url, data)
23+
.catch(_ => {
24+
if (proxyUrl) {
25+
urlsNeedToBeProxied[urlHash] = true;
26+
return post({ url, proxyUrl, proxyHeader }, data);
27+
}
28+
else throw _ as Dictionary;
29+
})
30+
} else {
31+
return postData(proxyUrl as string, data, proxyHeader || {})
32+
}
33+
}
34+
35+
function get({ url = '', proxyUrl, proxyHeader }: UrlAndProxy) {
36+
37+
const urlHash = getURLHash('get', url);
38+
const needToBeProxied = urlsNeedToBeProxied[urlHash] || false;
39+
40+
if (!needToBeProxied) {
41+
return getData(url)
42+
.catch(_ => {
43+
if (proxyUrl) {
44+
urlsNeedToBeProxied[urlHash] = true;
45+
return get({ url, proxyUrl, proxyHeader });
46+
}
47+
else throw _ as Dictionary;
48+
})
49+
} else {
50+
return getData(proxyUrl as string, proxyHeader || {})
51+
}
52+
}
53+
54+
export default {
55+
post, get,
56+
}
57+

src/common/services/translate.service.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import { TinyEmitter } from "tiny-emitter";
88
import { SUPPORTED_LANGUES } from "../static/langueges.static";
99
import { analytic } from "../../plugins/mixpanel";
1010
import { log } from "../helper/log";
11+
import proxy from "./proxy.service";
1112

1213
export class TranslateService {
1314
static instance = new TranslateService();
14-
1515
_eventBus = new TinyEmitter();
16+
targetLanguage = "fa";
1617

1718
constructor() {
1819
// Load target language
@@ -43,7 +44,6 @@ export class TranslateService {
4344
});
4445
}
4546

46-
targetLanguage = "fa";
4747

4848
get targetLanguageTitle() {
4949
return (
@@ -52,25 +52,22 @@ export class TranslateService {
5252
}
5353

5454
async translateByGoogle(text: string | string[]) {
55-
let key = "AIzaSyCzR9jH7EGCHgvfHXJxM0997UmuwiSRkH0";
56-
let url = `https://translation.googleapis.com/language/translate/v2?key=${key}`;
55+
let key = process.env.GOOGLE_TRANSLATE_KEY;
56+
let url = {
57+
url: `https://translation.googleapis.com/language/translate/v2?key=${key}`,
58+
proxyUrl: process.env.GOOGLE_TRANSLATE_PROXY_URL,
59+
}
5760

5861
let body = {
5962
q: text,
6063
target: this.targetLanguage,
6164
};
6265

63-
return fetch(url, {
64-
body: JSON.stringify(body),
65-
method: "POST",
66-
})
67-
.then((res) => {
68-
if (res.status == 200) return res.json() as Promise<Dictionary>;
69-
else throw res;
70-
})
66+
return proxy.post(url, body)
7167
.then((body: Dictionary) => body.data.translations)
7268
.then((list) => {
7369
let lang = "en";
70+
7471
let newList = list.map(
7572
(item: { translatedText: string; detectedSourceLanguage: string }) =>
7673
item.translatedText
@@ -84,11 +81,12 @@ export class TranslateService {
8481
}
8582

8683
async translateByDictionaryapi(word: string) {
87-
let url = "https://api.dictionaryapi.dev/api/v2/entries/en/";
88-
url += encodeURI(word);
84+
let url = {
85+
url: "https://api.dictionaryapi.dev/api/v2/entries/en/" + encodeURI(word),
86+
proxyUrl: null,
87+
}
8988

90-
return fetch(url)
91-
.then((res) => res.json())
89+
return proxy.get(url)
9290
.then((body) => {
9391
if (body.title) throw body;
9492
else return body as WordFromDictionaryApi[];

src/common/static/base64Images.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
WORD_LOADING: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBkaXNwbGF5OiBibG9jazsiIHdpZHRoPSIyMDBweCIgaGVpZ2h0PSIyMDBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxOCkiPgogIDxwYXRoIGZpbGw9IiM4NWEyYjYiIGQ9Ik01My4yLDMwLjNjMC40LTEuMywwLjYtMi43LDAuNi00LjJjMC0xLjItMC4xLTIuMy0wLjQtMy40Yy0xLjUtNi03LTEwLjUtMTMuNS0xMC41IGMtNS4zLDAtOS45LDMtMTIuMyw3LjRjLTAuOS0wLjMtMS44LTAuNC0yLjgtMC40Yy01LjEsMC05LjMsNC4xLTkuMyw5LjNjMCwwLjYsMC4xLDEuMywwLjIsMS45Yy00LjcsMC43LTguMyw0LjgtOC4zLDkuNyBjMCw1LjQsNC40LDkuOCw5LjgsOS44aDM0LjJjMy44LDAsNy4xLTIuMiw4LjgtNS40YzAuNy0xLjMsMS4xLTIuOSwxLjEtNC41QzYxLjQsMzUuMiw1Ny44LDMxLjEsNTMuMiwzMC4zeiI+CiAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InRyYW5zbGF0ZSIgdmFsdWVzPSItMyAwOzMgMDstMyAwIiBrZXlUaW1lcz0iMDswLjU7MSIgZHVyPSIyIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgY2FsY01vZGU9InNwbGluZSIga2V5U3BsaW5lcz0iMC41IDAgMC41IDE7MC41IDAgMC41IDEiPjwvYW5pbWF0ZVRyYW5zZm9ybT4KICA8L3BhdGg+CiAgPGRlZnM+CiAgICA8cGF0aCBpZD0ibGRpby15bTByeTh0ZjM3LXBhdGgiIGQ9Ik0wLDB2MTAwaDEwMFYwSDB6IE02Mi45LDQ0LjRjLTEuNywzLjQtNS4zLDUuOC05LjQsNS44SDE3Yy01LjgsMC0xMC41LTQuNy0xMC41LTEwLjUgYzAtNS4yLDMuOC05LjYsOC45LTEwLjRjLTAuMS0wLjYtMC4yLTEuMy0wLjItMmMwLTUuNSw0LjQtOS45LDkuOS05LjljMSwwLDIsMC4yLDMsMC41YzIuNS00LjcsNy40LTcuOSwxMy4xLTcuOSBjNi45LDAsMTIuOCw0LjgsMTQuNCwxMS4yYzAuMywxLjIsMC40LDIuNCwwLjQsMy42YzAsMS42LTAuMiwzLjEtMC43LDQuNWM1LDAuOCw4LjcsNS4yLDguNywxMC4zQzY0LDQxLjMsNjMuNiw0Myw2Mi45LDQ0LjR6Ij4KICAgICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiB0eXBlPSJ0cmFuc2xhdGUiIHZhbHVlcz0iLTMgMDszIDA7LTMgMCIga2V5VGltZXM9IjA7MC41OzEiIGR1cj0iMiIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGNhbGNNb2RlPSJzcGxpbmUiIGtleVNwbGluZXM9IjAuNSAwIDAuNSAxOzAuNSAwIDAuNSAxIj48L2FuaW1hdGVUcmFuc2Zvcm0+CiAgICA8L3BhdGg+CiAgICA8Y2xpcFBhdGggaWQ9ImxkaW8teW0wcnk4dGYzNy1jcCI+PHVzZSB4bGluazpocmVmPSIjbGRpby15bTByeTh0ZjM3LXBhdGgiPjwvdXNlPjwvY2xpcFBhdGg+CiAgPC9kZWZzPgogIDxnIGNsaXAtcGF0aD0idXJsKGxkaW8teW0wcnk4dGYzNy1jcCkiPgogICAgPHBhdGggZmlsbD0iI2JiY2VkZCIgZD0iTTg0LjksMjguOWMwLjQtMS4xLDAuNi0yLjMsMC42LTMuNWMwLTEtMC4xLTEuOS0wLjQtMi44IGMtMS4zLTUtNi4xLTguNy0xMS44LTguN2MtNC42LDAtOC43LDIuNS0xMC43LDYuMWMtMC44LTAuMi0xLjYtMC40LTIuNC0wLjRjLTQuNSwwLTguMSwzLjQtOC4xLDcuNmMwLDAuNSwwLjEsMSwwLjIsMS41IGMtNC4xLDAuNi03LjIsNC03LjIsOGMwLDQuNSwzLjgsOC4xLDguNiw4LjFoMjkuOGMzLjMsMCw2LjItMS44LDcuNy00LjRjMC42LTEuMSwwLjktMi4zLDAuOS0zLjdDOTIsMzIuOSw4OC45LDI5LjYsODQuOSwyOC45eiI+CiAgICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0idHJhbnNsYXRlIiB2YWx1ZXM9Ii0zIDA7MyAwOy0zIDAiIGtleVRpbWVzPSIwOzAuNTsxIiBkdXI9IjEuMzIiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlTcGxpbmVzPSIwLjUgMCAwLjUgMTswLjUgMCAwLjUgMSI+PC9hbmltYXRlVHJhbnNmb3JtPgogICAgPC9wYXRoPgogIDwvZz4KPC9nPgo8L3N2Zz4=",
3+
}

src/common/static/langueges.static.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const SUPPORTED_LANGUES = [
5050
{ title: "Kinyarwanda", code: "rw" },
5151
{ title: "Korean", code: "ko" },
5252
{ title: "Kurdish", code: "ku" },
53+
{ title: "Kurdish (Sorani)", code: "ckb" },
5354
{ title: "Kyrgyz", code: "ky" },
5455
{ title: "Lao", code: "lo" },
5556
{ title: "Latin", code: "la" },

src/main.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { netflix } from "./module/subtitle/netflix/initializer";
1010
import { youtube } from "./module/subtitle/youtube/initializer";
1111
import { AppInitializer } from "./common/types/general.type";
1212
import { cleanText } from "./common/helper/text";
13-
import "./plugins/mixpanel";
1413
import { analytic } from "./plugins/mixpanel";
1514
import { VERSION } from "./common/static/global";
1615
import { log } from "./common/helper/log";

src/module/popup/App.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
</form>
1212

1313
<div class="text-gray-300 mt-12 w-64">
14-
<h3 class="text-lg">How it works?</h3>
15-
<p>Try to open a video on one of the suported websites, then activate subtitle and try to hover or click a word.</p>
14+
<h3 class="text-lg">How does it work?</h3>
15+
<p>Try to open a video on one of the supported websites, then activate subtitle on a video and try to hover or click a word.</p>
1616
</div>
1717

1818
<div class="mt-12 flex flex-col items-center">

0 commit comments

Comments
 (0)