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

ts-react-loc

v1.0.9

Published

Localizer for the React components (TypeScript).

Downloads

5

Readme

About

ts-react-loc was developed to allow developers to create localization in quick and easy way. The only manual work you have to perform: create language files and simple loaders. This module was tested within several big projects in AMAKids.Dev company and showed great results. We have formed some good practices in implementing localization using this module, and they will be described below.

Installation

npm i --save ts-react-loc

API

Localizer.tsx

|Property|Required|Type|Description| |-|-|-|-| |load|Yes|LangLoader|Function that loads language data (async).| |getLangCode|Yes|LangCodeGetter|Function that returns language code (async).| |lang|Not|Lang|Language data.| |shred|Not|string|Name of language data shred to use as language data. This is simply name of sub-object to use as language data.| |alias|Not|string|Language data will appear in resulting language object as sub-object with this name.|

PageLocalizer.tsx

|Property|Required|Type|Description| |-|-|-|-| |page|Yes|string|Page name.| |load|Yes|Loader|Function that loads language data (async).| |getLangCode|Yes|LangCodeGetter|Function that returns language code (async).| |shred|No|string|Name of language data shred to use as language data. This is simply name of sub-object to use as language data.|

Usage

Let's look at several usage variants that may be useful for you projects. Here are some notes you have to remember:

  • Language modules must be as independent as possible (i.e. 'isolated'). This means you have to create language modules that are appropriate to some components. Such components are reusable and can be used for creating your own multilanguage components library.
  • Sometimes it is useful to create language modules for pages. In this case one language module is bound with one page. This must be created for some non-reusable components. But isolated components with isolated language modules are preferable.

Isolated language modules

You have to prefer this method in most of cases because it allows you and your team to create isolated components that are easy to reuse. Imagine you have Header component and this folders structure:

.
├── index.ts
└── components
    └── header
        ├── Header.tsx
        ├── index.ts
        └── lang
            ├── en.json
            ├── fr.json
            └── ...

Simple code of Header component might look like:

// @components/header/Header.tsx

import * as React from 'react';
import {Localizer, Lang} from 'react-localizer';

import {getLangCode} from '@lib';

type Props = {
    lang?:Lang;
    user:{
        name:string;
    };
};

export const Header = (props:Props) =>
    <Loc>
        <Body {...props}/>
    </Loc>;
    
const Loc = () => {
    const load = async (langCode:string) => {
        try {
            return await import(`./lang/${langCode}`);
        } catch (e) {
            console.warn(e.message);
            
            return {};
        }
    };
    
    return (
        <Localizer load={load} getLangCode={getLangCode}>
            {props.children}
        </Localizer>
    );
};
    
const Body = (props:Props) =>
    <div className='Header'>
        <h1>{props.lang.header}</h1>
        <h2>{props.user.name}</h2>
    </div>;

Let's understand this code.

  • Body component is header you want to render.
  • Loc is component that provides localization. It will add lang property to Body's props.
  • Header is container component that combines Loc and Body.

Page language modules

If you need you can create language modules bound to pages. We highly recommend implement your own PageLoc component using react-localizer's PageLocalizer component. This is good practice. Let's look at simple example. Firstly you have to create assets directory with language files appropriate to pages.

.
└── assets
    └── lang
        └── pages
            ├── main
            |   ├── en.json
            |   ├── fr.json
            |   └── ...
            └── payments
                ├── en.json
                ├── fr.json
                └── ...

Next you have to implement PageLoc component.

// @components/PageLoc.tsx

import * as React from 'react';
import {PageLocalizer} from 'react-localizer';

import {getLangCode} from '@lib';

type Props = {
    page:string;
    shred?:string;
    children?:React.ReactNode;
};

export const PageLoc = (props:Props) =>
    <Localizer {...props} load={load} getLangCode={getLangCode}>
        {props.children}
    </Localizer>;

const load = async ({page, langCode}) => {
    try {
        return await import(`@assets/lang/pages/${page}/${langCode}`);
    } catch (e) {
        console.warn(e.message);
        
        return {};
    }
};

Now imagine you have Main.tsx component that is root component for the main page. You will have similar files structure:

.
├──components
|  ├── PageLoc.tsx
|  └── ...
└── pages
    ├── main
    |   ├── Main.tsx
    |   ├── Loc.tsx
    |   └── ...
    └── payments
        ├── Payments.tsx
        ├── Loc.tsx
        └── ...

Your next aim is to create localizer component for the main page.

// @pages/main/Loc.tsx

import * as React from 'react';

import {PageLoc} from '@components';

type Props = {
    children:React.ReactNode;
};

export const Loc = (props:Props) =>
    <PageLoc page='main'>
        {props.children}
    </PageLoc>;

Now we are ready to implement multilanguage Main.tsx component that is root component for the main page. Let's go.

// @pages/main/Main.tsx

import * as React from 'react';
import {Lang} from 'react-localizer';

import {Loc} from './Loc';

type Props = {
    lang?:Lang;
    user:{
        name:string;
    };
};

export const Main = (props:Props) =>
    <Loc>
        <Body {...props}/>
    </Loc>;
    
const Body = (props:Props) =>
    <div className='Main'>
        <h1>{props.lang.hello}</h1>
        <h2>{props.lang.user}: {props.user.name}</h2>
    </div>;

Language code getter

As you can see react-localizer requires getLangCode function that provides current language code of your application. Notice that this function must be async. It is easy to implement. Better place for this function is root lib directory. (We always create @lib alias for this one for quick access.)

.
└── lib
    ├── lang-code-getter.ts
    └── ...
// @lib/lang-code-getter.ts

export const getLangCode = async () =>
    window.localStorage.getItem('langCode')
        || 'en';

In some cases language code getter might be rather complicated. For example, there is one of our getLangCode function we use in NeuroClub project.

import {Config} from 'global-config';

import {store} from '@store';
import {Utils} from '@lib/page-router';

export const getLangCodeAsync = async () =>
    getLangCode();

export const getLangCode = () =>
    Utils.hasBaseData()
        ? getForPageWithBaseData()
        : getForPageWithNoBaseData();

const getForPageWithNoBaseData = () => {
    try {
        return window.localStorage.getItem(Config.LOCAL_LANG_CODE_NAME)
            || Config.DEF_LANG_CODE;
    } catch (e) {
        return Config.DEF_LANG_CODE;
    }
};

const getForPageWithBaseData = () => {
    try {
        const state = store.getState();
        const {langCode} = state.user.user;

        return langCode || Config.DEF_LANG_CODE;
    } catch (e) {
        return Config.DEF_LANG_CODE;
    }
};

export default getLangCode;

GitHub repository

https://github.com/balovbohdan/ts-react-loc

Contributing

Pull requests and forks are welcome. You can use this code freely for your own projects and/or experiments. If you have some questions or proposals feel free to write message.

License

MIT