npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ackee/jerome

v5.0.3

Published

Equipment for localizations at React-Redux-ReduxSaga stack

Downloads

109

Readme

ackee|Jerome

GitHub license CI Status PRs Welcome Dependency StatusKnown Vulnerabilities

Jerome

Localization module useful mainly for frontend development in Ackee.

Name of package refers to Saint Jerome the patron of all translators.

Table of contents

Installation

Using yarn:

yarn add @ackee/jerome

Using npm:

npm i -s @ackee/jerome

Usage

All parts are independent, but best works all together. Don't forget that for correct usage of selectors your reducer have to be stored with translate key (as in example).

Used APIs

Jerome uses react-intl@3 which relies on some native browser APIs so if you're going to use components for plurals or relative time format, be sure that your minimal supported browsers implement those APIs or use polyfills as described bellow

For polyfilling plurals, use intl-pluralrules package.

if (!Intl.PluralRules) {
  require('intl-pluralrules');
}

For polyfilling plurals, use intl-relativetimeformat package.

if (!Intl.RelativeTimeFormat) {
  require('@formatjs/intl-relativetimeformat/polyfill');
  require('@formatjs/intl-relativetimeformat/dist/locale-data/de'); // Add locale data for de
}

API

Components

Translatable

  • It wraps children with IntlProvider from react-intl. The IntlProvider receives current locale from redux store.
  • It dispatches SET_INTL action everytime the locale changes. This is required to make [getIntl] saga work. See createIntlContext for more info.

⚠️ To make it work smoothly, you must have react-intl installed just once! So be sure your dependencies structure is flat.

import { Translatable } from '@ackee/jerome';

const messages = {
    cs: {
        hello: 'Dobry den',
        ...
    },
    en: {
        hello: 'Hello',
        ...
    },
};

export function Localizations({ children }) {
    return <Translatable intlMessages={messages}>{children}</Translatable>
}

HOC

Important To make HOCs works properly, you must have react-intl installed just once! So be sure your dependencies structure is flat.

[Deprecated]translatableFactory(intlLocaleData): (ContentComponent) => TranslatableContentComponent

It provides reac-intl localization context, so you first have to provide localization messages to the factory that will return the actual HOC.

intlLocaleData - object with messages keyed by locale name, eg.

const messages = {
    cs: {
        hello: 'Dobry den',
        ...
    },
    en: {
        hello: 'Hello',
        ...
    },
}

The factory returns function that receives ContentComponent and return it wrapped with IntlProvider which receives locale from the store.translate.locale store path.

Example

import { FormattedMessage, addLocaleData } from 'react-intl';
import { translatableFactory } from '@ackee/jerome';

const ContentComponent = () => (
    <div id="app">
        <h1><FormattedMessage id="hello" /></h1>
        <h2><FormattedMessage id="bye.instant" /></h2>
        <h3><FormattedMessage id="bye.forever" /></h3>
    </div>
);

const messages = {
    cs: {
        hello: 'Cau',
        'bye.instant': 'Nashledanou',
        'bye.forever': 'Sbohem',
    },
    en: {
        hello: 'Hello',
        'bye.instant': 'See you later',
        'bye.forever': 'Goodbye',
    },
};

const store = createStore((state = initialState) => ({
    translate: { locale: 'cs' },
}));

TranslatableComponent = translatableFactory(messages)(ContentComponent);

ReactDOM.render(<TranslatableComponent store={store} />, document.getElementById('app'));

translatableFactory(intlLocaleData, antdLocaleData): (ContentComponent) => TranslatableContentComponent

There is an overload of translatableFactory for usage with Ant design components library. It extends standard translatableFactory with adding antd localization context, but you have to provide the antLocaleData as a second argument to the factory.

intlLocaleData - object with antd locales keyed by locale name. eg.

import cs_CZ from 'antd/lib/locale-provider/cs_CZ';
import en_US from 'antd/lib/locale-provider/en_US';

const messages = {
    cs: cs_CZ,
    en: en_US,
}

Usage is almost same as for the translatableFactory, you only need to import it from @ackee/jerome/antd instead of @ackee/jerome.

import { FormattedMessage, addLocaleData } from 'react-intl';

import { Pagination } from 'antd';
import cs_CZ from 'antd/lib/locale-provider/cs_CZ';
import en_US from 'antd/lib/locale-provider/en_US';

import { translatableFactory } from '@ackee/jerome/antd'; // notice the import path

const ContentComponent = () => (
    <div id="app">
        <h1><FormattedMessage id="hello" /></h1>
        <Pagination defaultCurrent={1} total={50} showSizeChanger />
    </div>
);

const messages = {
    cs: {
        hello: 'Cau',
    },
    en: {
        hello: 'Hello',
    },
};

const antdMessages = {
    cs: cs_CZ,
    en: en_US,
}

const store = createStore((state = initialState) => ({
    translate: { locale: 'cs' },
}));

// provide antd messages as a second argument
TranslatableComponent = translatableWithAntdFactory(messages, antdMessages)(ContentComponent);

ReactDOM.render(<TranslatableComponent store={store} />, document.getElementById('app'));

Actions

setLocale(locale: string)

Example

import { setLocale } from '@ackee/jerome';

dispatch(setLocale('cs'));

getLocale

Example

import { getLocale } from '@ackee/jerome';

dispatch(getLocale());

Action types

import { actionTypes } from '@ackee/jerome'

Reducer

Reducer is actually reducer factory since you must provide default locale first.

reducer(locale: string): TranslateReducer

Example

import { reducer as translateFactory } from '@ackee/jerome';

const translate = translateFactory('cs');

const appReducers = combineReducers({
    translate,
    ...
});

Selectors

translateSelector(state: State): { locale: string }

Select translate part of store.

Example

import { translateSelector } from '@ackee/jerome';

translateSelector(state); // { locale: 'cs' }

Sagas

saga()

The saga has two purposes, both related to handling persistent storing of locale.

  • It saves locale on every SET_LOCALE action into the persistent storage.
  • It loads locale from persistent storage when app load and set it up.

Example

import { saga as localization } from '@ackee/jerome';

const rootSaga = function* () {
    yield all([
        localization(), // plug it into root saga
        ...
    ]);
};

function configureStore(initialState) {
    const sagaMiddleware = createSagaMiddleware();
    const middlewares = [sagaMiddleware];

    const middleware = applyMiddleware(...middlewares);

    const store = createStore(reducer, initialState, enhancer);
    sagaMiddleware.run(rootSaga);

    return store;
}

createIntlContext

The createIntlContext is a helper function to create a specific context shape used by getIntl saga. Due to limitations of the redux-saga context, this context has to be set by a user of this library in the most top saga of the application:

import { setContext, all } from 'redux-saga/effects';
import { createIntlContext } from '@ackee/jerome';

function * rootSaga() {
    yield setContext(createIntlContext());

    yield all([
        .... sagas using getIntl()
    ])
}

sagaMiddleware.run(rootSaga);

Without having the context set, getIntl saga would return null even though the rest of the library is used properly.

getIntl(): IntlShape

The getIntl saga returns an intl object that exactly corresponds to the intlShape. The saga relies on proper usage of createIntlContext

Example

import { getIntl } from '@ackee/jerome';

function* mySaga() {
    const intl = yield getIntl();

    const translatedMessage = intl.formatMessage({
        id: 'hello'
    });
}

Utilities

saveLocale(locale: string)

Used for persistent store of locale setting.

Example

import { saveLocale } from '@ackee/jerome';

saveLocale('cs');

loadLocale(): string

Used for getting locale setting from persistent storage.

Example

import { loadLocale } from '@ackee/jerome';

loadLocale(); // 'cs'

localStorageHandlers

Covers both utilities mentioned above.

Example

import { localStorageHandlers } from '@ackee/jerome';

localStorageHandlers.saveLocale('en');
localStorageHandlers.loadLocale(); // 'en'