Adds I18n (Internationalization) string support to a Fusion.js app.
This plugin looks for translations in the ./translations
folder by default. Translations for each language are expected to be in a JSON file with a locale as a filename. For example, for U.S. English, translations should be in ./translations/en-US.json
. Language tags are dictated by your browser, and likely follow the RFC 5646 specification.
For date I18n, consider using date-fns.
yarn add fusion-plugin-i18n-react
If you are using React, we recommend using the supplied Translate
component.
import React from 'react';
import {Translate, withTranslations} from 'fusion-plugin-i18n-react';
export default () => {
return <Translate id="test" data={{name: 'world'}} />);
});
A higher order component is provided to allow passing translations to third-party or native components. If you are using the translate
function directly, be aware that you can only pass in a string literal to this function. This plugin uses a babel transform and non-string literals (e.g. variables) will break.
import React from 'react';
import {Translate, withTranslations} from 'fusion-plugin-i18n-react';
export default withTranslations(['test'])(({translate}) => {
return <input placeholder={translate('test', {name: 'world'})} />;
});
The default loader expects translation files to live in ./translations/{locale}
.
./translations/en-US.json
{
"HomeHeader": "Welcome!",
"Greeting": "Hello, ${name}"
}
./translations/pt-BR.json
{
"HomeHeader": "Bem-vindo!",
"Greeting": "Olá, ${name}"
}
Usage:
<Translate id="HomeHeader" />
<Translate id="Greeting" data={{name: user.name}} />
// src/main.js
import React from 'react';
import App from 'fusion-react';
import I18n, {
I18nToken,
I18nLoaderToken,
createI18nLoader,
} from 'fusion-plugin-i18n-react';
import {FetchToken} from 'fusion-tokens';
import fetch from 'unfetch';
export default () => {
const app = new App(<div />);
app.register(I18nToken, I18n);
__NODE__
? app.register(I18nLoaderToken, createI18nLoader())
: app.register(FetchToken, fetch);
return app;
};
import I18n from 'fusion-plugin-i18n-react';
The i18n plugin. Typically, it should be registered to I18nToken
. Provides the i18n service
import {I18nToken} from 'fusion-plugin-i18n-react';
The canonical token for the I18n plugin. Typically, it should be registered with the I18n
plugin.
import {I18nLoaderToken} from 'fusion-plugin-i18n-react';
A function that provides translations. Optional. Server-side only.
type I18nLoader = {
from: (ctx: Context) => {locale: string, translations: Object},
};
loader.from: (ctx) => ({locale, translations})
-ctx: FusionContext
- Required. A FusionJS context object.locale: Locale
- A Localetranslations: Object
- A object that maps translation keys to translated values for the given locale
If no loader is provided, the default loader will read translations from ./translations/{locale}.json
. See src/loader.js for more details.
import {HydrationStateToken} from 'fusion-plugin-i18n-react';
Sets the hydrated state in the client, and can be useful for testing purposes. Optional. Browser only.
type HydrationState = {
chunks: Array,
translations: Object,
};
If no hydration state is provided, this will be an empty object ({}
) and have no effect.
import {FetchToken} from 'fusion-tokens';
A fetch
implementation. Browser-only.
type Fetch = (url: string, options: Object) => Promise<Response>;
url: string
- Required. Path or URL to the resource you wish to fetch.options: Object
- Optional. You may optionally pass aninit
options object as the second argument. See Request for more details.[return]: Promise<Request>
- Return value from fetch. See [Response](A function that loads appropriate translations and locale information given an HTTP request context) for more details.
If no fetch implementation is provided, window.fetch
is used.
const translations: string = i18n.translate(
key: string,
interpolations: Object
);
key: string
- A translation key. When usingcreateI18nLoader
, it refers to a object key in a translation json file.interpolations: object
- A object that maps an interpolation key to a value. For example, given a translation file{"foo": "${bar} world"}
, the codei18n.translate('foo', {bar: 'hello'})
returns"hello world"
.translation: string
- A translation, orkey
if a matching translation could not be found.
If you are using React, we recommend using the supplied Translate
component.
import {Translate} from 'fusion-plugin-i18n-react';
<Translate id="key" data={interpolations} />;
key: string
- Required. Must be a hard-coded value. This plugin uses a babel transform, i.e you cannot pass a value via JSX interpolation.interpolations: Object
- Optional. Replaces${value}
interpolation placeholders in a translation string with the property of the specified name.
A higher order component is provided to allow passing translations to third-party or native components. If you are using the translate
function directly, be aware that you can only pass in a string literal to this function. This plugin uses a babel transform and non-string literals (e.g. variables) will break.
import {withTranslations} from 'fusion-plugin-i18n-react';
const TranslatedComponent = withTranslations(['key'])(Component);
Be aware that the withTranslations
function expects an array of string literals. This plugin uses a babel transform and the argument to this function must be an inline value, i.e. you cannot pass a variable.
The original Component
receives a prop called {translate}
.
Types
type TranslateProp = {
translate: (key: string, interpolations: Object) => string,
};
type WithTranslations = (
translationKeys: Array<string>
) => (React.Component<Props>) => React.Component<Props & TranslateProp>;
translationKeys: Array<string>
- list of keys with which to provide translations for.translate: (key: string, interpolations: Object) => string
- returns the translation for the given key, with the provided interpolations.
// src/main.js
import React from 'react';
import App from 'fusion-react';
import I18n, {I18nToken, I18nLoaderToken} from 'fusion-plugin-i18n-react';
import {FetchToken} from 'fusion-tokens';
import fetch from 'unfetch';
import Hello from './hello';
import I18nLoader from './translations';
export default () => {
const app = new App(<div></div>);
app.register(I18nToken, I18n);
__NODE__
? app.register(I18nLoaderToken, I18nLoader);
: app.register(FetchToken, fetch);
app.register(Hello);
return app;
}
// src/hello.js
import {withServices} from 'fusion-react';
import {I18nToken} from 'fusion-plugin-i18n-react';
export default withServices({I18n: I18nToken})(({I18n}) => {
return withMiddleware((ctx, next) => {
if (__NODE__ && ctx.path === '/hello') {
const i18n = I18n(ctx);
ctx.body = {
message: i18n.translate('test', {name: 'world'}), // hello world
}
}
return next();
});
});
// src/translation-loader.js
import {Locale} from 'locale';
const translationData = {
'en-US': {
test: "hello ${name}"
}
}
export default (ctx) => {
// locale could be determined in different ways,
// e.g. from ctx.headers['accept-language'] or from a /en-US/ URL
const locale = new Locale('en-US');
const translations = translationData[locale];
return {locale, translations};
}