Skip to content

Commit

Permalink
Merge pull request #16 from MiracleUFO/perf/translation-core-package
Browse files Browse the repository at this point in the history
perf(proxying): fix Buffer not found issue by using proxy
  • Loading branch information
MiracleUFO authored Oct 11, 2023
2 parents 04e3a66 + a6e0b06 commit bd8044c
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
NODE_ENV=development

TRANSLATE_API_PROXY=
TEST_TRANSLATE_API_PROXY=
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ A modern, *free*, *lightweight* npm package for translating react apps (pages an
- Allows for custom language list files. (Coming in v2.0.0)

## Install
```npm install react-g-translator```
```npm install @miracleufo/react-g-translator```

or with yarn

```yarn add react-g-translator```
```yarn add @miracleufo/react-g-translator```

## Usage

> DISCLAIMER!
To be 100% legal please use the official [Google Translate API](https://cloud.google.com/translate). This project is mainly for pet projects and prototyping 😉. Also, only use the most recent version of this package.

### To translate whole component:
```jsx
import Translator from 'react-g-translator';
import Translator from '@miracleufo/react-g-translator';

return (
<Translator from='en' to='es'>
Expand All @@ -34,7 +37,7 @@ return (

### To translate specific text inline:
```jsx
import { Translate } from 'react-g-translator';
import { Translate } from '@miracleufo/react-g-translator';

return (
<div>
Expand All @@ -48,7 +51,7 @@ return (

### To get translation of text directly:
```jsx
import { getTranslation } from 'react-g-translator';
import { getTranslation } from '@miracleufo/react-g-translator';

const helloInIgbo = await getTranslation('Hello', 'en', 'ig');

Expand Down
54 changes: 1 addition & 53 deletions package-lock.json

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

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.5.0",
"@vitalets/google-translate-api": "^9.0.0",
"crypto-js": "^4.1.1",
"env-cmd": "^10.1.0",
"https-proxy-agent": "^7.0.2",
Expand Down
1 change: 1 addition & 0 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const mainConfig = {
],
external: ['react', 'react-dom'],
plugins: [
// @ts-ignore
peerDepsExternal(),
nodeResolve(),
commonjs(),
Expand Down
10 changes: 7 additions & 3 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import language from '../types/language';

const { NODE_ENV, TRANSLATE_API_PROXY } = process.env;
const { NODE_ENV, TEST_TRANSLATE_API_PROXY } = process.env;

// NODE ENVIRONMENT
const NODE_DEVELOPMENT = 'development';
const NODE_TEST = 'test';
const IS_DEVELOPMENT_OR_TEST = NODE_ENV && [NODE_DEVELOPMENT, NODE_TEST].includes(NODE_ENV);

const PROXY = TRANSLATE_API_PROXY;
const PROXY_URL = 'https://react-g-translator-proxy.vercel.app/api';
const PROXY_URL_ALT = 'https://react-g-translator-proxy-express.onrender.com/translate';
const PROXY_URL_TEST = TEST_TRANSLATE_API_PROXY;

const DEFAULT_PROPS = {
from: 'en',
Expand Down Expand Up @@ -41,7 +43,9 @@ export {
NODE_DEVELOPMENT,
NODE_TEST,
IS_DEVELOPMENT_OR_TEST,
PROXY,
PROXY_URL,
PROXY_URL_ALT,
PROXY_URL_TEST,
DEFAULT_PROPS,
DEFAULT_QUERY_OPTIONS,
DEFAULT_LANGUAGE_FROM,
Expand Down
22 changes: 6 additions & 16 deletions src/utils/getTranslation.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
import { translate } from '@vitalets/google-translate-api';
import { HttpsProxyAgent } from 'https-proxy-agent';
import throttle from 'lodash/throttle';

import chunkRequest from './chunkRequest';
import {
PROXY,
CHARACTER_LIMIT,
DEBOUNCE_RATE,
IS_DEVELOPMENT_OR_TEST,
} from '../constants';
import translate from './translate';

import { CHARACTER_LIMIT, DEBOUNCE_RATE } from '../constants';
import language from '../types/language';

const getTranslation = async (
text: string | string[],
from?: language,
to?: language,
) : Promise<string | undefined> => {
// opts for development / testing
// in case `TooManyRequestsError` or Error Code `429`
const fetchOptions = IS_DEVELOPMENT_OR_TEST && PROXY && { agent: new HttpsProxyAgent(PROXY) };

// translating happens here. ✨ bing! ✨
const translateRequest = async (chunk: string | string[]) => {
const translation = await translate(chunk as string, { from, to, fetchOptions });
return translation.text;
// translating happens here. ✨ bing! ✨
const translation = await translate(chunk as string, from, to);
return JSON.parse(translation)?.text ?? '';
};

return throttle(
Expand Down
62 changes: 62 additions & 0 deletions src/utils/translate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { HttpsProxyAgent } from 'https-proxy-agent';
import getErrorInTranslationMessage from './getErrorInTranslationMessage';
import {
IS_DEVELOPMENT_OR_TEST,
PROXY_URL,
PROXY_URL_ALT,
PROXY_URL_TEST,
} from '../constants';
import language from '../types/language';

const translate = async (text: string, from?: language, to?: language) => {
// option for development / testing
// in case of `TooManyRequestsError` (Error Code `429`)
const fetchOptions = (
IS_DEVELOPMENT_OR_TEST && PROXY_URL_TEST && { agent: new HttpsProxyAgent(PROXY_URL_TEST) }
);

let response;
try {
response = await fetch(PROXY_URL, {
credentials: 'omit',
mode: 'cors',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(
{
text,
from,
to,
fetchOptions,
},
),
});
} catch (error) {
// If the first request failed, try with the second proxy
response = await fetch(PROXY_URL_ALT, {
credentials: 'omit',
mode: 'cors',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(
{
text,
from,
to,
fetchOptions,
},
),
});
}

if (response.status === 200) return response.json();

const error = new Error(`${response.status} - ${response.statusText}`);
throw getErrorInTranslationMessage(error);
};

export default translate;

0 comments on commit bd8044c

Please sign in to comment.