diff --git a/README.md b/README.md
index 204d0b2..b729d1a 100644
--- a/README.md
+++ b/README.md
@@ -70,10 +70,10 @@ return (
- *Type string*. If string provided is not found in [supported languages](https://cloud.google.com/translate/docs/languages) will default to *user's current browser langauge setting*.
- Overriden by [`setLanguageTo`](#hook-setlanguageto) hook. (Coming in V2)
- - `shouldFallback`: Should translation return original text if error in translation (fallback) or return empty string. Optional.
+ - `shouldFallback`: Determines error handling. In displays original text when true, or empty string otherwise (when error). Optional.
- Defaults to `true`.
- *Type boolean*. If not provided will default to true.
- - **NOTE:** Returns exception when there is an error in translation if set to `false`.
+ - **NOTE:** Will always log exception when there is an error in translation.
### Wrapper: `` ###
*Type:* React functional component
@@ -103,10 +103,16 @@ See [Usage](#to-get-translation-of-text-directly)
*Type:* Function
-*Returns*: string
+*Returns*: string | Error
*Params:*
- `text`: *Type string*, *required*
- [`from`](#props) *optional*
- [`to`](#props) *optional*
-- [`shouldFallback`](#props) *optional*
\ No newline at end of file
+
+
+## SPECIAL CASES
+
+- [`from`](#props) and [`to`](#props) being the same will return original text (determined by google translation API.)
+- [`from`](#props) and [`to`](#props) being empty strings will be extrapolated from 'en' and *user's current browser langauge setting* respectively.
+- `text` is not in `from` language and google translate API cannot detect language automatically will return the original text.
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 1a75d79..08439bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.5.0",
"@vitalets/google-translate-api": "^9.0.0",
+ "https-proxy-agent": "^7.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-query": "^3.39.2",
@@ -4287,19 +4288,6 @@
"node": ">= 14"
}
},
- "node_modules/@semantic-release/github/node_modules/https-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.0.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/@semantic-release/github/node_modules/slash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
@@ -12147,15 +12135,26 @@
}
},
"node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
"dependencies": {
- "agent-base": "6",
+ "agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
- "node": ">= 6"
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
+ "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
}
},
"node_modules/human-signals": {
@@ -14340,6 +14339,18 @@
"node": ">= 6"
}
},
+ "node_modules/jest-environment-jsdom/node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/jest-environment-jsdom/node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -17040,6 +17051,19 @@
"jsdom": ">=10.0.0"
}
},
+ "node_modules/jsdom/node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
diff --git a/package.json b/package.json
index 9d3208b..f91be08 100644
--- a/package.json
+++ b/package.json
@@ -97,6 +97,7 @@
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.5.0",
"@vitalets/google-translate-api": "^9.0.0",
+ "https-proxy-agent": "^7.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-query": "^3.39.2",
diff --git a/src/components/Translate.tsx b/src/components/Translate.tsx
index cb67718..93e7e6b 100644
--- a/src/components/Translate.tsx
+++ b/src/components/Translate.tsx
@@ -1,12 +1,9 @@
-import { useEffect } from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { LanguageProvider } from '../context/languageContext';
import useTranslation from '../queries/useTranslation';
-import getErrorInTranslationMessage from '../utils/getErrorInTranslationMessage';
import determineRenderedText from '../utils/determineRenderedText';
-
import { DEFAULT_PROPS } from '../constants';
import language from '../types/language';
@@ -25,20 +22,10 @@ const Translate = ({
}) => {
const {
data,
- error,
isError,
isLoading,
} = useTranslation(children, from, to);
- useEffect(() => {
- // if shouldFallback prop is set to `false` and there's an error:
- // throw error
- if (
- isError
- && (typeof shouldFallback !== 'undefined' && !shouldFallback)
- ) throw getErrorInTranslationMessage(error);
- }, [isError, error, shouldFallback]);
-
return (
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 83db585..ae3c661 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -10,18 +10,27 @@ const DEFAULT_PROPS = {
shouldFallback: true,
};
+const DEFAULT_QUERY_OPTIONS = {
+ defaultOptions: {
+ queries: {
+ retry: false,
+ },
+ },
+};
+
const DEFAULT_LANGUAGE_FROM: language = 'en';
const DEFAULT_BROWSER_LANGUAGE : language = window?.navigator?.language.startsWith('zh')
? window?.navigator?.language as language
: window?.navigator?.language.split('-')[0] as language;
-const TRANSLATION_NOT_FOUND_MESSAGE = 'Err 404: No translation found. Check `to` & `from` props.';
+const TRANSLATION_NOT_FOUND_MESSAGE = 'react-g-translator: Err 404: No translation found. Check `to` & `from` props.';
export {
HELLO_IN_ENGLISH,
HELLO_IN_FRENCH,
HELLO_IN_SPANISH,
DEFAULT_PROPS,
+ DEFAULT_QUERY_OPTIONS,
DEFAULT_LANGUAGE_FROM,
DEFAULT_BROWSER_LANGUAGE,
TRANSLATION_NOT_FOUND_MESSAGE,
diff --git a/src/queries/useTranslation.ts b/src/queries/useTranslation.ts
index 723edcd..e7c29e8 100644
--- a/src/queries/useTranslation.ts
+++ b/src/queries/useTranslation.ts
@@ -1,6 +1,8 @@
import { useQuery } from 'react-query';
import { useLanguageContext } from '../context/languageContext';
+
import getTranslation from '../utils/getTranslation';
+import getErrorInTranslationMessage from '../utils/getErrorInTranslationMessage';
import language from '../types/language';
const useTranslation = (
@@ -14,7 +16,16 @@ const useTranslation = (
error,
isError,
isLoading,
- } = useQuery('translation', () => getTranslation(text, from || languageFrom, to || languageTo));
+ } = useQuery(
+ 'translation',
+ () => getTranslation(text, from || languageFrom, to || languageTo),
+ {
+ // more descriptive error than react-query error
+ onError: (err: unknown) => {
+ console.error(getErrorInTranslationMessage(err));
+ },
+ },
+ );
return {
data,
diff --git a/src/scripts/getTranslation.ts b/src/scripts/getTranslation.ts
index c64dbc3..e706c61 100644
--- a/src/scripts/getTranslation.ts
+++ b/src/scripts/getTranslation.ts
@@ -12,24 +12,12 @@ const getTranslation = async (
text: string,
from = DEFAULT_LANGUAGE_FROM,
to = DEFAULT_BROWSER_LANGUAGE,
- shouldFallback = true,
) : Promise => {
- // loading state
- let translation: string | undefined = text;
-
try {
- translation = await getTranslationUtil(text, from, to);
-
- if (
- !translation
- && (typeof shouldFallback !== 'undefined' && !shouldFallback)
- ) throw new Error(TRANSLATION_NOT_FOUND_MESSAGE);
+ const translation = await getTranslationUtil(text, from, to);
- return (
- translation
- || (shouldFallback && text)
- || ''
- );
+ if (translation) return translation;
+ throw new Error(TRANSLATION_NOT_FOUND_MESSAGE);
} catch (error) {
throw getErrorInTranslationMessage(error);
}
diff --git a/src/tests/utils-test.tsx b/src/tests/utils-test.tsx
index ec1254b..938eed2 100644
--- a/src/tests/utils-test.tsx
+++ b/src/tests/utils-test.tsx
@@ -2,8 +2,10 @@ import { ReactElement, ReactNode } from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { QueryClientProvider, QueryClient } from 'react-query';
import { LanguageProvider } from '../context/languageContext';
+import { DEFAULT_QUERY_OPTIONS } from '../constants';
-const queryClient = new QueryClient();
+const queryClient = new QueryClient(DEFAULT_QUERY_OPTIONS);
+queryClient.clear();
const Providers = ({ children }: {children: ReactNode}) => (
@@ -18,14 +20,5 @@ const customRender = (
options?: Omit,
) => render(ui, { wrapper: Providers, ...options });
-const HELLO_IN_ENGLISH = 'Hello World';
-const HELLO_IN_SPANISH = 'Hola Mundo';
-const HELLO_IN_FRENCH = 'Bonjour Monde';
-
export * from '@testing-library/react';
export { customRender as render };
-export {
- HELLO_IN_ENGLISH,
- HELLO_IN_SPANISH,
- HELLO_IN_FRENCH,
-};
diff --git a/src/utils/determineRenderedText.ts b/src/utils/determineRenderedText.ts
index dee6f92..0ad7519 100644
--- a/src/utils/determineRenderedText.ts
+++ b/src/utils/determineRenderedText.ts
@@ -5,10 +5,10 @@ const determineRenderedText = (
isError: boolean,
isLoading: boolean,
) => {
+ if (translatedText) return translatedText;
if (shouldFallback && (isError || isLoading)) return text;
if (isLoading) return text;
if (isError) return '';
- if (translatedText) return translatedText;
return '';
};
diff --git a/src/utils/getErrorInTranslationMessage.ts b/src/utils/getErrorInTranslationMessage.ts
index ffd0529..5318131 100644
--- a/src/utils/getErrorInTranslationMessage.ts
+++ b/src/utils/getErrorInTranslationMessage.ts
@@ -1,3 +1,3 @@
-const getErrorInTranslationMessage = ((error: unknown) => new Error(`Error in translation: ${String(error)}`));
+const getErrorInTranslationMessage = ((error: unknown) => new Error(`react-g-translator: Error in translation: ${String(error)}`));
export default getErrorInTranslationMessage;
diff --git a/src/utils/getTranslation.ts b/src/utils/getTranslation.ts
index 8a8a7bc..21f55c8 100644
--- a/src/utils/getTranslation.ts
+++ b/src/utils/getTranslation.ts
@@ -1,6 +1,5 @@
import { translate } from '@vitalets/google-translate-api';
import enableCors from './enableCorsAndLimitRate';
-import getErrorInTranslationMessage from './getErrorInTranslationMessage';
import language from '../types/language';
const getTranslation = async (
@@ -8,17 +7,12 @@ const getTranslation = async (
from?: language,
to?: language,
) : Promise => {
- try {
- // rate limit (1 request per second) and CORS policy overriding (if any)
- enableCors(1);
+ // rate limit (1 request per second) and CORS policy overriding (if any)
+ enableCors(1);
- // translating happens here. ✨ bing! ✨
- const translation = await translate(text as string, { from, to });
- return translation.text;
- } catch (error) {
- console.error(getErrorInTranslationMessage(error));
- return undefined;
- }
+ // translating happens here. ✨ bing! ✨
+ const translation = await translate(text as string, { from, to });
+ return translation.text;
};
export default getTranslation;