Coder Social home page Coder Social logo

cherry-projects / react-translate-maker Goto Github PK

View Code? Open in Web Editor NEW
35.0 3.0 7.0 137 KB

Universal internationalization (i18n) open source library for React

License: Apache License 2.0

JavaScript 100.00%
translate i18n internationalization intl react redux javascript api

react-translate-maker's Introduction

react-translate-maker

React translation module. Internationalize your great project. This library is part of translate-maker. Star this project on GitHub.

NPM version build status Test coverage

Installation

Install via npm.

npm install react-translate-maker

Versions

If you are using react >= 15.4.0 use version >= 0.3.0 otherwise use version < 0.3.0

Features

  • Build on standards (ICU Message syntax, Unicode CLDR), ES6 and Promises
  • Support for 190+ languages
  • Runs in the browser and Node.js
  • JSON Structure
  • Nested and reference translations
  • Variables
  • Conditioned translations (Plural, Gender etc...)
  • Filters capitalize, upperCase, lowerCase etc... and custom filters
  • Default translations
  • Integrates with React and Angular
  • Automatic extraction of translations from your project
  • For more details and examples click on translate-maker

Support us

Star this project on GitHub.

Usage

Basic example

import React from 'react';
import Translate, { LocaleProvider, TranslateMaker } from 'react-translate-maker';

const translate = new TranslateMaker({
  data: {
    en_US: {
      hello: 'Hello {$user.name}',
      followers: `{$user.name} has {$user.followers, plural,
        zero {no followers}
        one  {# follower}
             {# followers}
      }`
    }
  }
});

const user = {
  name: 'Zlatko',
  followers: 15,
};

React.render(
  <LocaleProvider translate={translate} locale="en_US">
    <div>
      <h1><Translate path="hello" user={user} /></h1>
      <Translate path="followers" user={user} />
    </div>
  </LocaleProvider>
);

The result will be

<div>
  <h1>Hello Zlatko</h1>
  Zlatko has 15 followers
</div>

File adapter

If you want to load localisation files automatically with the require function you can use File adapter.

File structure

project
│  component.jsx
└──locales
   │  en_US.js

en_US.js

export default {
  gender: `{$gender, select, male {boy} female {girl}}`,
  working: `{gender, $user1.gender as gender | capitalize} {$user1.name} is working with
    {gender, $user2.gender as gender} {$user2.name}`
};

component.jsx

import React from 'react';
import Translate { LocaleProvider, TranslateMaker, Gender, FileAdapter } from 'react-translate-maker';
import path from 'path';

const translate = new TranslateMaker({
  adapter: new FileAdapter({
    path: path.join(__dirname, '/locales'),
  });
});

const currentLocale = 'en_US';

const user1 = {
  gender: Gender.MALE,
  name: 'Zlatko',
};

const user1 = {
  gender: Gender.FEMALE,
  name: 'Livia',
};

React.render(
  <LocaleProvider translate={translate} locale={currentLocale}>
    <Translate path="working" user1={user1} user2={user2} />
  </LocaleProvider>
);

The result will be

Boy Zlatko is working with girl Livia

File adapter and webpack

If you want to use webpack with file adapter you need to use own function getFile. You need to use getFile instead of path because you need to change the webpack context.

component.jsx

import React from 'react';
import Translate { LocaleProvider, TranslateMaker, Gender, FileAdapter } from 'react-translate-maker';

const translate = new TranslateMaker({
  adapter: new FileAdapter({
    getFile: (locale, namespace) => require('./locale/' + locale),
  });
});

const currentLocale = 'en_US';

const user1 = {
  gender: Gender.MALE,
  name: 'Zlatko',
};

const user1 = {
  gender: Gender.FEMALE,
  name: 'Livia',
};

React.render(
  <LocaleProvider translate={translate} locale={currentLocale}>
    <Translate path="working" user1={user1} user2={user2} />
  </LocaleProvider>
);

Placeholder and direct translations

import React, { Component } from 'react';
import Translate, { LocaleProvider } from 'react-translate-maker';

const currentLocale = 'en_US';
const data = {
  en_US: {
    inputSearch: 'Search',
  },
};

React.render(
  <LocaleProvider adapter={data} locale={currentLocale}>
    <Translate path="inputSearch" defaultValue="Search...">
      {placeholder => (
        <input type="text" placeholder={placeholder} />
      )}
    </Translate>
  </LocaleProvider>
);

The result will be

<input type="text" placeholder="Search" />

Direct translations

import React, { Component } from 'react';
import { LocaleProvider, ProvideTranslate } from 'react-translate-maker';

class MyComponent extends Component {
  render() {
    const { translate } = this.props;

    return (
      <input type="text" placeholder={translate('inputSearch', 'Search...')} />
    );
  }
}

const currentLocale = 'en_US';
const data = {
  en_US: {
    inputSearch: 'Search',
  },
};

React.render(
  <LocaleProvider adapter={data} locale={currentLocale}>
    <ProvideTranslate>
      {translate => (
        <MyComponent translate={translate} />
      )}
    </T>
  </LocaleProvider>
);

The result will be

<input type="text" placeholder="Search" />

Namespaces

Sometimes when you are using dot notation you can stack with long paths. For example: header.navigation.button.login. You can use component named Namespace which will help you to simplify your jsx file.

import React from 'react';
import Translate { LocaleProvider, Namespace } from 'react-translate-maker';

const currentLocale = 'en_US';
const data = {
  en_US: {
    header: {
      navigation: {
        title: 'MyProject',
        button: {
          login: 'Log In',
          signup: 'Sign Up',
        },
      },
    },
  },
};

React.render(
  <LocaleProvider adapter={data} locale={currentLocale}>
    <Namespace path="header.navigation">
      <nav>
        <ul>
          <li><Translate path="button.login" /></li>
          <li><Translate path="button.signup" /></li>
        </ul>
      </nav>
    </Namespace>
  </LocaleProvider>
);

Namespace with compose component

import React from 'react';
import Translate { LocaleProvider, Namespace } from 'react-translate-maker';

const currentLocale = 'en_US';
const data = {
  en_US: {
    header: {
      navigation: {
        title: 'MyProject',
        button: {
          login: 'Log In',
          signup: 'Sign Up',
        },
      },
    },
  },
};

React.render(
  <LocaleProvider adapter={data} locale={currentLocale}>
    <Namespace path="header.navigation">
      <h1><Translate path="title" /></h1>
      <nav>
        <Namespace path="button" compose>
        <ul>
          <li><Translate path="login" /></li>
          <li><Translate path="signup" /></li>
        </ul>
        </Namespace>
      </nav>
    </Namespace>
  </LocaleProvider>
);

HTML content

Sometimes you need to provide HTML content.

import React from 'react';
import { LocaleProvider, Translate } from 'react-translate-maker';

const currentLocale = 'en_US';
const data = {
  en_US: {
    welcome: 'Welcome back {$user}. How is it going?',
  },
};

const user = {
  name: 'Zlatko',
};

React.render(
  <LocaleProvider adapter={data} locale={currentLocale}>
    <Translate 
      path="welcome" 
      params={{ 
        user: <b>{user.name}</b>
      }} />
  </LocaleProvider>
);

The result will be

<span>Welcome back <b>Zlatko</b>. How is it going?</span>

Locale switch

We are providing a component for the locale switch. It is a select with everything what do you need. You can use it in two ways. Here is first example.

import React, { Component } from 'react';
import Translate { LocaleProvider, LocaleSwitch } from 'react-translate-maker';

const data = {
  en_US: {
    language: 'Language',
    button: {
      login: 'Log In',
      signup: 'Sign Up',
    },
  },
  sk_SK: {
    language: 'Jazyk',
    button: {
      login: 'Prihlasit sa',
      signup: 'Odhlasit sa',
    },
  },
};

const locales = [{
  label: 'English',
  value: 'en_US',
}, {
  label: 'Slovenčina',
  value: 'sk_SK',
}];

const DEFAULT_LOCALE = 'en_US';

class App extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      locale: DEFAULT_LOCALE,
    };
  }

  handleLocaleChange(locale) {
    this.setState({
      locale: locale,
    });
  }

  render() {
    const { data, locales } = this.props;
    const currentLocale = this.state.locale;

    return (
      <LocaleProvider adapter={data} locale={currentLocale}>
        <nav>
          <ul>
            <li><Translate path="button.login" /></li>
            <li><Translate path="button.signup" /></li>
            <li>
              <Translate path="language" />
              <LocaleSwitch locales={locales} onChange={this.handleLocaleChange.bind(this)}/>
            </li>
          </ul>
        </nav>
      </LocaleProvider>
    );
  }
}

React.render(<App data={data} locales={locales}/>);

As you can see in previous example. We are using onChange event. The main reason for that is that LocaleProvider is a controlled component. That means if you wanted to change property named locale of the LocaleProvider you need to change it directly in the render function.

If you want to use LocaleProvider as uncontrolled component you can do that. But all properties of the LocaleProvider will be used only as initialisation properties. Here is a second example (please take a loon on the property named controlled of the LocaleProvider).

import React, { Component } from 'react';
import Translate { LocaleProvider, LocaleSwitch } from 'react-translate-maker';

const data = {
  en_US: {
    language: 'Language',
    button: {
      login: 'Log In',
      signup: 'Sign Up',
    },
  },
  sk_SK: {
    language: 'Jazyk',
    button: {
      login: 'Prihlasit sa',
      signup: 'Odhlasit sa',
    },
  },
};

const locales = [{
  label: 'English',
  value: 'en_US',
}, {
  label: 'Slovenčina',
  value: 'sk_SK',
}];

const DEFAULT_LOCALE = 'en_US';

class App extends Component {
  render() {
    const { data, locales } = this.props;
    const currentLocale = this.state.locale;

    return (
      <LocaleProvider adapter={data} locale={DEFAULT_LOCALE} controlled={false}>
        <nav>
          <ul>
            <li><Translate path="button.login" /></li>
            <li><Translate path="button.signup" /></li>
            <li>
              <Translate path="language" />
              <LocaleSwitch locales={locales}/>
            </li>
          </ul>
        </nav>
      </LocaleProvider>
    );
  }
}

React.render(<App data={data} locales={locales}/>);

The main difference is that you are not able to change locale of the LocaleProvider with property named locale after first render.

Properties of the LocaleSwitch

  • onChange (function): Callback witch a new locale (immediate change)
  • onLocaleChange (function): Callback witch a new locale (after success change)
  • setLocale (Boolean): It will set locale automatically in the translate-maker after change (default: true)
  • locales (array): Array of the available locales. [{ label: 'English', value: 'en_US' }]
  • all properties of the standard select component

Filters

Sometimes you need to provide HTML content.

import React from 'react';
import Translate, { LocaleProvider } from 'react-translate-maker';

const currentLocale = 'en_US';
const data = {
  en_US: {
    welcome: 'Welcome {$user.name | star}',
  },
};

const filters = {
  star: function star(value) {
    return '*** ' + value + ' ***';
  },
};

const user = {
  name: 'Zlatko',
};

React.render(
  <LocaleProvider adapter={data} locale={currentLocale} filters={filters}>
    <Translate path="welcome" user={user} />
  </LocaleProvider>
);

The result will be

<span>Welcome *** Zlatko ***</span>

Options of Locale Provider

  • locale (String): Current locale ID (default null)
  • locales (Array): List of available locales IDs (default null)
  • cache (Instance of Cache): Cache of the translations (default MemoryCache)
  • adapter (Instance of Adapter | data): Adapter provides translations (default see option defaultAdapter)
  • defaultAdapter (Class of Adapter): Default adapter (default MemoryAdapter)
  • dotNotation (Boolean): You can turn of dot notation. This is useful if you are using PO translation files (default true)
  • mode (Enum): You can use full compatible ICU version with Mode.ICU. After that you can use external variables witout dolar character (Default Mode.MAIN)
  • references (Boolean): You can turn on/off references. (Default true)
  • variables (Boolean): You can turn on/off variables. (Default true)
  • combinations (Boolean): You can turn on/off combinations. (Default true)
  • defaultValue (Function): What you will see for missing translations (Default (path, attrs) => Missing default translation for: ${path})
  • filters (Object): Object with custom filters
  • controlled (Boolean): You can set component as uncontrolled (default true). More information.

More examples

Please take a look on translate-maker

Roadmap

  • Locales property of the LocaleSwitch can be an object
  • Locales property of the LocaleSwitch can be autopopulated from the adapter
  • Locales property of the LocaleSwitch can be translated automatically by translate-maker

Support us

Star this project on GitHub.

Running Tests

To run the test suite, first invoke the following command within the repo, installing the development dependencies:

npm install

Then run the tests:

npm test

react-translate-maker's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-translate-maker's Issues

Possible to translate string and pass as prop?

Hi,

I was wondering how you would go about passing a translated string to a placeholder attribute on an input.

I could use translate-maker to get the translated string and pass it as a prop. Is it possible to do this without requiring translate-maker in my project?

Thanks

LocaleSwitch documentation

I'm trying to use the LocaleSwitch component.

It renders correctly and updates the new language at this.context.translate, but the component renders with the first select option selected, no matter which option is chosen.

The strings do not update until navigating back to the page or a refresh is forced. I can make this happen by using an onChange handler and calling this.forceUpdate()

Is this the recommended way to handle a locale change?

Loading multiple namespaces at the same time causes all but the last resolved to be cleared.

So, I have narrowed my problem down to LocaleProvider

On initialization, If the namespace changes, then only the last successfully loaded namespace locale will be saved.

Same issue if the locale changes once, and namespace changes multiple times.
componentWillReceiveProps calls translate.setLocale when namespace changes, but locale hasn't.

This happens because there is a load of the "global" namespace and a component namespace immediately after.
Serializing the load of these items would solve this issue. (although slow down the rendering of the page)

Missing dependancy

After installing webpack complains Error: Cannot resolve module 'react-addons-test-utils'.
Should react-addons-test-utils be moved into dependancies?

Nested components?

Hey,
I'm looking for a way to insert React components into the translated string.

Use-case:
In your example https://github.com/CherryProjects/react-translate-maker#en_usjs I want to have user names clickable.

The dirty workaround would be inserting <a> into the text and use TranslateHTML. But it doesn't work if I want links to be handled by react-router's <Link> component.

I've tried passing the components to properties as it is in react-intl (Rich Text Formatting), but it just results in [object Object]
Am I missing something or this feature is not supported?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.