/react-g-translator

Free, lightweight, React Component Wrapper package for translating react apps on the fly.

Primary LanguageTypeScriptMIT LicenseMIT

react-g-translator

A modern, free, lightweight npm package for translating react apps (pages and components) on the fly. No API keys or language list files are required.

Features

  • Covers multiple use cases (see Usage)
  • Enables Web Internationalisation (i18n) and Accessibility (a11y)
  • Auto language detection
  • Spelling and Language correction
  • Supports Next.js ▲ and Vite ⚡️ (see Vite ⚡️ usage)
  • Support React Native (Beta)
  • Fast and reliable – it uses the same servers that translate.google.com uses
  • Allows to set default language and destination language in code
  • Translates entire pages and just text
  • Translates input and textarea element placeholder as well as img (image) alt text
  • Allows for custom language list files. (Coming in v2.0.0)

Install

npm install @miracleufo/react-g-translator

or with yarn

yarn add @miracleufo/react-g-translator

Usage

DISCLAIMER! To be 100% legal please use the official Google Translate API. This project is mainly for pet projects and prototyping 😉. The server is very limited, for use in production see PRODUCTION USAGE. Always only use the most recent version of this package.

To translate whole component:

import { Translator } from '@miracleufo/react-g-translator';

const Component = () => {
  ...
  return (
    <Translator from='en' to='es'>
      <div>
        ...
      </div>
    </Translator>
  );
}

For best use of <Translator />:

  • The <Translator /> wrapper will only translate React non-void elements and fragments that are not components themselves (i.e A parent component will not translate children components. It will only translate other React non-void elements or fragments inside it, this is for improved scoping of the wrapper's from and to props.)
  • Each non-void React element is translated like a paragraph, for best translation please avoid <br /> and use <p> instead, and always end sentences with fullstop.
  • If spacing is needed before or after an inline element, it should be written as {' '} (JSX) this is because translation removes all starting or ending spacing it deems unnecessary.
  • To opt out of translating a variable wrap it in either the <code> or <var> element. Variables of type number are not translated by default. Keyboard inputs you don't want translated should be wrapped in <kbd>.

To translate specific text inline:

import { Translate } from '@miracleufo/react-g-translator';

return (
  <>
    ...
    <Translate from='en' to='fr'>Hello in French.</Translate>
    {/* Can also be used within elements */}
    <p>
      <Translate from='en' to='de'>Welcome in German.</Translate>
      Happy to meet you.
    </p>
    ...
  </>
);

To get translation of text directly:

import { getTranslation } from '@miracleufo/react-g-translator';

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

return (
  <div>
    <p>{helloInIgbo}></p>
  </div>
)

API

Props

  • from: Language the text(s) is provided in. Optional.

  • to: Language to translate to. Optional.

    • Defaults to user's current browser language setting.
    • Type string. String provided must be found in supported languages.
    • Overriden by setLanguageTo hook. (Coming in V2)
  • shouldFallback: Determines error handling. Available in <Translate /> and <Translator />, when error, displays original text when shouldFallback is true, or empty string otherwise. Optional.

    • Defaults to true.
    • Type boolean. If not provided will default to true.
    • NOTE: Will always log exception when there is an error in translation.

Wrapper: <Translator />

Type: React functional component

Note: Directly wraps a valid jsx parent/element (not text and not another functional component.)

Props:

Wrapper: <Translate />

Type: React functional component

Note: Must directly wrap text.

Props:

Method getTranslation(text, from, to)

Translates text and returns translation. Best used if specific text(s) needs to be translated in-line without wrapping in provider. See Usage

Type: Function

Returns: string | Error

Params:

  • text: Type string, required
  • from optional
  • to optional

Caching

  • For every UNIQUE text, to, and from (props) combination the translation is fetched & cached for 24 hours (as long as QueryClient is not destroyed,) this is to prevent unnecessary requests.
  • QueryClient is destroyed in this case ONLY when the web page is reloaded.

Special Cases

  • from and to being the same will return original text (determined by google translation API.)
  • from and to being empty strings will be extrapolated from 'en' and user's current browser language setting respectively.
  • text is not in the from language and google translate API cannot detect language automatically, it will return the original text.

Vite ⚡ Usage

Vite does not have the process global, to polyfill this in Vite projects, in the vite.config.js or vite.config.ts file install and include vite-plugin-env-compatible package as shown to load env variables correctly, or error Uncaught ReferenceError: process is not defined will be thrown.

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react';
import envCompatible from 'vite-plugin-env-compatible';

// https://vitejs.dev/config/
export default defineConfig({
  ...
  plugins: [
    ...
    react(),
    // @ts-ignore
    envCompatible.default({ prefix: 'VITE', mountedPath: 'process.env'}),
    ...
  ],
  ...
});

Production Usage

The server for this package is very limited and may not meet your projects' needs, to aid package use in production:

  • FORK the server at this repo.
  • You will need a MONGODB ATLAS CLUSTER to run the server successfully for rate limiting. Create one for free, and assign the Atlas cluster's credentials to MONGOOSE_ATLAS_CONNECTION_STRING & MONGOOSE_ATLAS_PASSWORD in your server's environment file (keep this private.)
  • If you choose to remove rate limiting entirely then a MONGODB ATLAS CLUSTER will not be needed, to do this remove these lines and this line in your fork code. This is not recommended because IP will be banned more frequently by the translation service.
  • Host the forked server. In the environment file(s) (.env.*) of the React project assign the hosted server's URL/address to REACT_APP_TRANSLATE_SERVER_URL OR VITE_APP_TRANSLATE_SERVER_URL (if using Vite ⚡️) OR NEXT_PUBLIC_APP_TRANSLATE_SERVER_URL (if using Next.js ▲.)
  • To enable AUTHENTICATION, you can protect your server if you want by editing code in the server repo see this for help, once authorisation code is running on server assign the server's authentication token to REACT_APP_TRANSLATE_SERVER_TOKEN or VITE_APP_TRANSLATE_SERVER_TOKEN (if using Vite ⚡️) OR NEXT_PUBLIC_APP_TRANSLATE_SERVER_TOKEN (if using Next.js ▲) in the React projects' environment file(s) (.env.*)
  • Also, if delay between requests is too long, remove sleep and/or edit delay in your server.

Developer Testing

  • FORK package repo
  • Install node-modules: npm install or yarn install.
  • npm run test or yarn run test
  • Note
    • Some tests in src/tests may fail because google translate API might return synonyms when a string is translated multiple times.
    • If TooManyRequestsError or Error Code 429 is encountered, this issue is due to Google Translate APIs rate limiting per IP address (this limit seems variable, see discussion.) Switching internet providers may solve this (temporarily.)
    • Caching is OFF by default in testing, to turn ON, replace DEFAULT_QUERY_OPTIONS in tests/constants-test.ts with:
const ONE_DAY_IN_MS = 24 * (60 * 60 * 1000);
const DEFAULT_QUERY_OPTIONS = {
  defaultOptions: {
    queries: {
      retry: false,
      staleTime: ONE_DAY_IN_MS,
      cacheTime: ONE_DAY_IN_MS,
    },
  },
};