k2-react-translate

A react translation library with optional routing

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
k2-react-translate
0.8.119 months ago4 years agoMinified + gzip package size for k2-react-translate in KB

Readme

k2-react-translate
npm
npm npm
GitHub issues GitHub pull requests
GitHub
GitHub stars GitHub stars GitHub stars
A simple, easy-to-use translation library based on React's Context API, with optional localized react-router routing.
See demo on CodeSandbox.
image

Table of Contents

Problem Statement

TBD

Setup

This ES5 module is distributed via npm and should be installed as a production dependency.
Note: TypeScript syntax is used throughout the docs, but the library should run without issue on a babel/react setup.
Using yarn (preferred)
yarn add -E k2-react-translate

or via npm
npm i -S -E k2-react-translate

peerDependencies

-   `react@^16.8.0` would have to be installed to use the `useTranslate` hook.


Typescirpt type definitions come bundled in.

Project Setup

If using TypeScript in VS Code, add the following configuration to your tsconfig.json to allow for importing json files into your modules:
// tsconfig.json
{
	"compilerOptions": {
		// other config options ...
		"resolveJsonModule": true
	}
}

Setup your translations:
If using VS Code, the richie5um2's Sort JSON objects marketplace extension may help to keep your translations file organized.
// translations.json
{
	"HELLO": {
		"en": "Hello",
		"fr": "Bonjour"
	},
	"HELLO_NAME": {
		"en": "Hello, {firstName}",
		"fr": "Bonjour, {firstName}"
	},
	"AVAILABLE_IN_COUNTRY": {
		"en": "Available in {countryName}",
		"fr": "Disponsible en {countryName}"
	},
	"PRIVACY_POLICY": {
		"en": "<a href='{link}'>Privacy Policy</a>",
		"fr": "<a href='{link}'>Politique de Confidentialité</a>"
	}
}

Entry point:
// index.tsx
import * as React from 'react'; // standard TypeScript syntax
import * as ReactDOM from 'react-dom'; // standard TypeScript syntax
import { LocaleProvider } from 'k2-react-translate';
import { App } from './App';
import translations from './translations.json';

ReactDOM.render(
	<LocaleProvider translations={translations} languages={['en', 'fr']} localizeUrls={false}>
		<App />
	</LocaleProvider>,
	document.getElementById('app')
);

Documentation (Translation)

k2-react-translate barrels (re-exports) the following sub-modules as named exports:

<LocaleProvider/> - source

A Context API wrapper to <LocaleContext.Provider/>. This wrapper is required to apply k2-react-translate translations.
| Props | Type | Description | | ----------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | translations | Object (required) | See translations under Project Setup | | languages | Array (required) | An array of language codes. Used as params to react-router if you choose to incorporate localized routing into your app. | | defaultLanguage | string (optional) | Default language, Must be included in the languages array above | | localizedUrls | boolean (optional), default={false} | Option to localize URLs with every route change, page reload or language change. Additionally, add a <Router/> wrapper from react-router, meaning this need not be done in your RouterConfig |

Usage

See Project Setup above.

useTranslate - source

A custom hook for use in Function Components.
Dependencies: react@^16.8.0, react-dom@^16.8.0

Usage

// MyComponent.tsx
import * as React from 'react'; // standard TypeScript syntax
import { useTranslate } from 'k2-react-translate';

const links = {
	en: '/en/privacy-policy',
	fr: '/fr/privacy-policy',
};

const MyComponent: React.FunctionComponent<{}> = () => {
	const { translate, translateAndParse, language, changeLanguage } = useTranslate<string>();

	const handleClick = (): void => {
		// change language to French
		changeLanguage('fr');
	};

	return (
		<div>
			{translate('HELLO')}
			// "Hello" (en) - string // "Bonjour" (fr) - string
			{translate('HELLO_NAME', { firstName: 'Jaqen' })}
			// "Hello, Jaqen" (en) - string // "Bonjour, Jaqen" (fr) - string
			{translateAndParse('PRIVACY_POLICY', { link: links[language] })}
			// <a href="/en/privacy-policy">Privacy Policy</a> (en) - ReactElement // <a href="/fr/privacy-policy">
				Politique de Confidentialité
			</a> (fr) - ReactElement
			<button onClick={handleClick}>Change Language</button>
		</div>
	);
};

<Translator/> - source

A React component that wraps <LocaleContext.Consumer/> that performs translations, given translation keys as prop arguments.
If using react v16.8.0+, I'd strongly recommend using the useTranslate hook above instead. useTranslate works in the same way but provides for cleaner and less verbose use.
| Props | Type | Description | | ----------- | ----------------------------------- | ---------------------------------------------------------------------------- | | id | string (optional) | translation key | | vars | object (optional) | dynamic translation variables, set outside the translations.json | | render | function (optional) | render prop, returning (language:string)=>ReactNode | | parseHtml | boolean (optional), default=false | option to sanitize and parse stringified HTML set in the translations.json |

Usage

// MyComponent.tsx
import * as React from 'react'; // standard TypeScript syntax
import { Translator } from 'k2-react-translate';

const links = {
	en: '/en/privacy-policy',
	fr: '/fr/privacy-policy',
};

const MyComponent: React.StatelessComponent<{}> = () => {
	return (
		<div>
			<Translator id="HELLO" />
			// "Hello" (en) - string // "Bonjour" (fr) - string
			<Translator id="HELLO_NAME" vars={{ firstName: 'Jaqen' }} />
			// "Hello, Jaqen" (en) - string // "Bonjour, Jaqen" (fr) - string
			<Translator id="PRIVACY_POLICY" vars={{ link: links[language] }} />
			// <a href="/en/privacy-policy">Privacy Policy</a> (en) - ReactElement // <a href="/fr/privacy-policy">
				Politique de Confidentialité
			</a> (fr) - ReactElement
		</div>
	);
};

<LanguageSwitcher /> - source

A button wrapped React component that provides the ability to set languages.
Switching languages can alternatively be performed under an exposed function in the useTranslate hook documented here.
| Props | Type | Description | | --------- | -------- | ---------------- | | onClick | Function | Synthentic event |

Usage

// MyComponent.tsx
import * as React from 'react'; // standard TypeScript syntax
import { LanguageSwitcher } from 'k2-react-translate';

const MyComponent: React.FunctionComponent<{}>=()=>{

    const handleClick:(changeLanguage: (language:string)=> void ): void=>{
        // change language to French
        changeLanguage('fr');
    }

    return <div>
        <LanguageSwitcher onClick={handleClick} />
    </div>;
}

Documentation (Localized Routing)

Localized routing is optional. If used, react-router-dom would need to be installed as a production dependency.

<LocalizedRoutes/> - source

Provides a simple, non-intrusive way of setting up localized routes. Returns localized <Route/>s or <Redirect/>s components given the routes prop config.
If <LocalizedRoutes/> is used, you need not wrap your RouterConfig with <Router/> or <BrowserRouter/> as this is done within <LocaleProvider/>.
<LocalizedRoutes/> is not recursive.
| Props | Type | Description | | ------------- | ----------------------------------- | -------------------------------------------------------------------------- | | routes | Array (required) | Based on react-router-dom's props | | localize | Boolean (optional), default=true | Option to localize URLs (prepend the language code in the URL) | | applySwitch | Boolean (optional), default=false | Wrap the Route config with <Switch/> components. Required in most cases. |

Usage

// RouteConfig.tsx
import * as React from 'react'; // standard TypeScript syntax
import { LocalizedRoutes, Route } from 'k2-react-translate';

const RouteConfig: React.FunctionComponent<{}> = () => {
	const routes: Route[] = [
		{
			path: '/', // resolves to /:language/, unless localize={false}
			exact: true,
			component: Home,
		},
		{
			path: '/about', // resolves to /:language/about, unless localize={false}
			component: About,
			localize: true, // should override <LocalizedRoutes localize={[true|false]} />
		},
		{
			// Redirect props
			to: '/page-not-found', // resolves to /:language/page-not-found, unless localize={false}
		},
	];

	return (
		<div>
			<LocalizedRoutes applySwitch={true} routes={routes} />
		</div>
	);
};

<LocalizedRoute/> - source

A localized wrapper to react-router-dom's Route.
You wouldn't need to use <LocalizedRoute/> if <LocalizedRoutes/> is configured.
| Props | Type | Description | | ---------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | | ...props | Object | Standard <Route/> component props | | localize | Boolean (optional), default=true | Option to localize URLs (prepend the language code in the URL) |

Usage

// MyComponent.tsx
import * as React from 'react'; // standard TypeScript syntax
import { LocalizedRoute } from 'k2-react-translate';
import { Home } from './Home';
import { About } from './About';

const MyComponent: React.FunctionComponent<{}> = () => {
	return (
		<div>
			// automatically resolves to the "/:language" // if "en" is active, then "/en"
			<LocalizedRoute path="/" exact component={Home} />
			// automatically resolves to the "/:language/about-us" // if "en" is active, then
			"/en/about-us"
			<LocalizedRoute path="/about" component={About} />
		</div>
	);
};

<LocalizedLink/> - source

A localized wrapper to react-router-dom's <Link/>.
| Props | Type | Description | | ---------- | ---------------------------------- | ----------------------------------------------------------------------------------------- | | ...props | Object | Standard <Link/> component props | | localize | Boolean (optional), default=true | Option to localize URLs (prepend the language code in the URL) |

Usage

// MyComponent.tsx
import * as React from 'react'; // standard TypeScript syntax
import { LocalizedLink } from 'k2-react-translate';

const MyComponent: React.FunctionComponent<{}> = () => {
	return (
		<div>
			// automatically resolves to the "/:language/about-us" // if "en" is active, then
			"/en/about-us"
			<LocalizedLink to="/about-us">About Us</LocalizedLink>
		</div>
	);
};

<LocalizedRedirect/> - source

A localized wrapper to react-router-dom's <Redirect/>.
| Props | Type | Description | | ---------- | ---------------------------------- | ------------------------------------------------------------------------------------------------- | | ...props | Object | Standard <Redirect/> component props | | localize | Boolean (optional), default=true | Option to localize URLs (prepend the language code in the URL) |

Usage

// MyComponent.tsx
import * as React from 'react'; // standard TypeScript syntax
import { LocalizedRedirect } from 'k2-react-translate';

const MyComponent: React.FunctionComponent<{}> = () => {
	// automatically resolves to the "/:language/page-not-found"
	// if "en" is active, then "/en/page-not-found"
	if (someCondition) {
		return <LocalizedRedirect to="/page-not-found">About Us</LocalizedRedirect>;
	}

	// alternatively, `props.history.push` would also resolve URLs by current langauge

	return <div />;
};

Development

  • Run yarn on the root of the repository.
  • Run yarn start to start the project.
  • Run yarn test:watch to ammend tests.

Known Issues

  • Routing works with <BrowserRouter/> for now
  • <LocalizedNavLink/> is yet to be adapted from <NavLink/>. <LocalizedLink> works equally as
well, with the exception of the `activeClassName` prop.