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.
If you're using React, you should use fusion-plugin-i18n-react instead of this package.
yarn add fusion-plugin-i18nThe plugin provides a programmatic interface which exposes translate. See Service API for more details.
// src/some-middleware-plugin.js
import {createPlugin} from 'fusion-core';
export default createPlugin({
deps: {I18n: I18nToken},
middleware: ({I18n}) => {
return (ctx, next) => {
if (__NODE__ && ctx.path === '/some-path') {
const i18n = I18n.from(ctx);
ctx.body = {
message: i18n.translate('test', {name: 'world'}), // hello world
};
}
return next();
};
},
});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}"
}// src/main.js
import App from 'fusion-core';
import I18n, {
I18nToken,
I18nLoaderToken,
createI18nLoader,
} from 'fusion-plugin-i18n';
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;
};I18nimport I18n from 'fusion-plugin-i18n-react';The i18n plugin. Typically, it should be registered to I18nToken. Provides the i18n service
I18nTokenimport {I18nToken} from 'fusion-plugin-i18n-react';The canonical token for the I18n plugin. Typically, it should be registered with the I18n plugin.
I18nLoaderTokenimport {I18nLoaderToken} from 'fusion-plugin-i18n';A function that provides translations. Optional. Server-side only.
type I18nLoader = {
from: (ctx: Context) => {locale: string | Locale, translations: {[string]: string},
};loader.from: (ctx) => ({locale, translations}) -
ctx: FusionContext - Required. A Fusion.JS context object.locale: string | Locale - The default i18n loader returns the Locale class here, but strings are also supported if you write your own loader.translations: {[string]: string} - A object that maps translation keys to translated values for the given localeIf no loader is provided, the default loader will read translations from ./translations/{locale}.json. See src/loader.js for more details.
HydrationStateTokenimport {HydrationStateToken} from 'fusion-plugin-i18n';Sets the hydrated state in the client, and can be useful for testing purposes. Optional. Browser only.
type HydrationState = {
chunks: Array<string | number>,
translations: {[string]: string},
};If no hydration state is provided, this will be an empty object ({}) and have no effect.
FetchTokenimport {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 an init 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 translation: string = i18n.translate(
key: string,
interpolations: {[string]: string}
);key: string - A translation key. When using createI18nLoader, 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 code i18n.translate('foo', {bar: 'hello'}) returns "hello world".translation: string - A translation, or key if a matching translation could not be found.// src/main.js
import App from 'fusion-core';
import I18n, {I18nToken, I18nLoaderToken} from 'fusion-plugin-i18n';
import {FetchToken} from 'fusion-tokens';
import fetch from 'unfetch';
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);
// ....
return app;
}
// 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};
}If you want to use the default loader, but want to provide a custom locale resolver, you can pass it into createI18nLoader
// src/main.js
import App from 'fusion-core';
import I18n, {createI18nLoader, I18nToken, I18nLoaderToken} from 'fusion-plugin-i18n';
import {FetchToken} from 'fusion-tokens';
import fetch from 'unfetch';
// use custom locale header instead of default
const myLocaleResolver = (ctx) => ctx.headers['my-locale-header'];
export default () => {
const app = new App(<div></div>);
app.register(I18nToken, I18n);
__NODE__
? app.register(I18nLoaderToken, createI18nLoader(myLocaleResolver));
: app.register(FetchToken, fetch);
// ....
return app;
}