GithubHelp home page GithubHelp logo

rmdort / react-redux-multilingual Goto Github PK

View Code? Open in Web Editor NEW
41.0 4.0 14.0 29 KB

A simple and slim multi-lingual component for React with Redux without react-intl or react-i18n

JavaScript 97.78% HTML 2.22%

react-redux-multilingual's Introduction

React Multilingual with redux

A simple and slim (Only 6KB) multi-lingual component for React with Redux without react-intl or react-i18n

Install

npm i react-redux-multilingual --save

Wiring it up

import translations from './translations'
import { IntlReducer as Intl, IntlProvider } from 'react-redux-multilingual'
import { createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'
import App from './App'

let reducers = combineReducers(Object.assign({}, { Intl }))
let store = createStore(reducers)

ReactDOM.render(
  <Provider store={store}>
    <IntlProvider translations={translations} locale='en'>
      <App />
    </IntlProvider>
  </Provider>
, document.getElementById('root'))

Translations format

The translations props accepts object in this format

{
  en: {
    locale: 'en-US',
    messages: {
      hello: 'how are you {name}'
    }
  },
  zh: {
    locale: 'zh',
    messages: {
      hello: '你好!你好吗 {name}'
    }
  }
}

Translate using hook

import { useTranslate } from 'react-redux-multilingual'

function App () {
  const t = useTranslate()

  return (
    <div>
      {t('hello', { name: 'Foo Bar'})}
    </div>
  )
}

Translate using higher-order component (HOC)

import { withTranslate } from 'react-redux-multilingual'

const App = ({ translate }) = {
  return (
    <div>
      {translate('hello', { name: 'John Doe' })}
    </div>
  )
}

module.exports = withTranslate(App)

Translate using Context

const App = (props, context) => {
  return (
    <div>
      {context.translate('hello', { name: 'John Doe' })}
    </div>
  )
}

App.contextTypes = {
  translate: React.propTypes.func
}

module.exports = App

Setting the initial locale

Option 1: Pass your locale to initial state of your reducer

let store = createStore(reducers, { Intl: { locale: 'zh'}})

Option 2: Dispatch an action to change locale

import { IntlActions } from 'react-redux-multilingual'
let store = createStore(reducers)
store.dispatch(IntlActions.setLocale('zh'))

react-redux-multilingual'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  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-redux-multilingual's Issues

Get current locale

How can we catch the current locale?
Can you add an example to the readme?

does not work well with connect

I have tried to use withTranslate with connect and now I am getting this error:

You must pass a component to the function returned by connect. Instead received {}

Also, in vscode, i get 3 dots below the line

import { withTranslate } from 'react-redux-multilingual';

which says

[ts]
Could not find a declaration file for module 'react-redux-multilingual'. '/Users/upforce/Workspace/talentx/talentx-cq/node_modules/react-redux-multilingual/lib/index.js' implicitly has an 'any' type.
  Try `npm install @types/react-redux-multilingual` if it exists or add a new declaration (.d.ts) file containing `declare module 'react-redux-multilingual';`
[ts]
Could not find a declaration file for module 'react-redux-multilingual'. '/Users/upforce/Workspace/talentx/talentx-cq/node_modules/react-redux-multilingual/lib/index.js' implicitly has an 'any' type.
  Try `npm install @types/react-redux-multilingual` if it exists or add a new declaration (.d.ts) file containing `declare module 'react-redux-multilingual';`
module "/Users/upforce/Workspace/talentx/talentx-cq/node_modules/react-redux-multilingual/lib/index"

Here is the full code of my Component (incase you want to see if I am doing everything right):

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withTranslate } from 'react-redux-multilingual';

import Login from './Login';
import { required } from '../../../../utils/validators';
import { userLogin } from '../../redux/actions';
import { noop } from '../../../../utils';

class LoginContainer extends Component {
  constructor(props) {
    super(props);
    this.validateLoginForm = this.validateLoginForm.bind(this);
    this.handleLogin = this.handleLogin.bind(this);
  }

  validateLoginForm(values) {
    const { translate } = this.props;
    const errors = {};

    errors.username = required(values.username) && translate('errors.required', { field: translate('auth.username') });
    errors.password = required(values.password) && translate('errors.required', { field: translate('auth.password') });

    return errors;
  }

  handleLogin(values) {
    const { userLoginAction, locale } = this.props;
    userLoginAction(values.username, values.password, locale);
  }

  render() {
    return (
      <Login
        validate={this.validateLoginForm}
        handleLogin={this.handleLogin}
      />
    );
  }
}

LoginContainer.propTypes = {
  translate: PropTypes.func.isRequired,
  locale: PropTypes.string.isRequired,
  userLoginAction: PropTypes.func,
};

LoginContainer.defaultProps = {
  userLoginAction: noop,
};

const mapStateToProps = state => ({
  locale: state.Intl.locale,
});

const mapDispatchToProps = dispatch => ({
  userLoginAction: (username, password, locale) => dispatch(userLogin(username, password, locale)),
});

export default connect(mapStateToProps, mapDispatchToProps)(withTranslate(LoginContainer));

I want to set default locale for module

image

In my code, line 16.
I set to props locale="zh" but it don't work because author don't handle this case, and author set initialState for locale is "en"
Can you help handle this case?
I come from Vietnam, my english is bad. hihi
Thanks.

ES6 - IntlActions.setLocale

When I read the README.md I noticed that there's a missing option on how to set which translation to be used.
Then later on I read some of the source code, and then noticed there's a redux action called setLocale which gets exported as IntlActions.setLocale

I'm currently using the script below, and by default the local language is set to en, but whenever I try to set the local to let's say zh it's still hasn't changed.

translations.js

import { IntlActions } from 'react-redux-multilingual'

import Preferences from '../preferences'
import HTTP from './utils/http'
import {APP} from '../config'

export default function (callback: Function) {
  Preferences.get('language', (iso) => {
    IntlActions.setLocale(iso)
    HTTP.get(`${APP.API}/translations`, callback)
  })
}

index.js

import React from 'react'
import createBrowserHistory from 'history/createBrowserHistory'
import { MemoryRouter as Router } from 'react-router-dom'
import { IntlReducer as Intl, IntlProvider } from 'react-redux-multilingual'
import { createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'

import App from './utils/app'
import Routes from './routes'
import getTranslations from './translations'

const history = createBrowserHistory()

const reducers = combineReducers(Object.assign({}, { Intl }))
const store = createStore(reducers)

getTranslations(translations => {
  App.init(
    <Provider store={store}>
      <IntlProvider translations={translations}>
        <Router history={history}>
          <Routes />
        </Router>
      </IntlProvider>
    </Provider>,
    '#content-wrapper'
  )
})

Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`

index.js:2178 Warning: Failed prop type: Invalid prop component of type object supplied to Route, expected function.
in Route (at App.jsx:37)
in App (created by Route)
in Route (created by withRouter(App))
in withRouter(App) (at index.js:20)
in Router (created by BrowserRouter)
in BrowserRouter (at index.js:19)
in IntlProvider (created by Connect(IntlProvider))
in Connect(IntlProvider) (at index.js:18)
in Provider (at index.js:17)
So I got this warning error.
Here is my index
ReactDOM.render( <Provider store={store}> <IntlProvider translations={translations}> <Router> <App /> </Router> </IntlProvider> </Provider> , document.getElementById("root"));
Here is my App component
const App = ({ location }) => { const currentKey = location.pathname.split('/')[1] || '/' return ( <Switch location={location}> <Route exact path="/" component={Homepage} /> </Switch> ); } export default withRouter(App);

Transform withTranslate() method as a decorator

Hi again,

It could be useful to transform the method withTranslate() to permit its use as a decorator.

import { withTranslate } from 'react-redux-multilingual'

// ----------------------------------
// Old version
const App = ({ translate }) = {
  return (
    <div>
      {translate('hello', { name: 'John Doe' })}
    </div>
  )
}
export default withTranslate(App)

// ----------------------------------
// To that
@withTranslate()
const App = ({ translate }) = {
  return (
    <div>
      {translate('hello', { name: 'John Doe' })}
    </div>
  )
}
export default App

It improve the usage into workflow with decorators (or typescript projets) without break the syntax.

Transform the current method into decorator is pretty easy.
You can see the patch I made into my project :

import { withTranslate } from 'react-redux-multilingual'
export default () => (WrapperComponent) => withTranslate(WrapperComponent);

A little update who does not add a big breaking change and can be more user friendly into some projets.
Decorators can also be written traditionally: withTranslate()(App).

Access translate function in a file where we don't have a react-component

I have a file which has only some helper functions. I want to use translate in that file. I don't want to pass translate as a parameter to the function as I have to make changes to many files. Is there any way that I can have access to translate function in any file which does not use react?

By the way I don't have any problem to use react in such files. I mean I can import React if translate needs it.

[error] 'classProperties' isn't currently enabled

image

index.js

ReactDOM.render(   
    <Provider store={store}>   
        <IntlProvider translations={translations}>   
            <Router>   
                <App/>   
            </Router>   
        </IntlProvider>   
    </Provider>,   
    document.getElementById('root')
);  

RootReducer.js

import {combineReducers} from "redux";
import exampleReducer from "redux/reducers/example/example.reducer";
import {IntlReducer as Intl} from 'react-redux-multilingual'

export const reducer = combineReducers({
    example: exampleReducer.reducer,
    Intl
});

export const initialState = {
    example: exampleReducer.INITIAL_STATE,
    Intl   : {locale: 'zh'}
};

export default {reducer, initialState};

Store.js

import rootReducer from 'redux/reducers/root-reducer.js'
import {applyMiddleware, createStore} from "redux";
import logger from "redux-logger";

const middlewares = [logger];

const store = createStore(rootReducer.reducer, rootReducer.initialState, applyMiddleware(...middlewares));

export default store;

App.js

import React from 'react';
import {connect} from "react-redux";
import {withTranslate} from "react-redux-multilingual/src";

const App = ({translate}) => {
    return (
        <div className="App">
            {translate('hello', {name: 'John Doe'})}
        </div>
    );
};

export default connect()(withTranslate(App))

Package.json

{
  "name": "shuttle-ui",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "bootstrap": "^4.3.1",
    "node-sass": "^4.13.0",
    "prop-types": "^15.7.2",
    "react": "^16.12.0",
    "react-bootstrap": "^1.0.0-beta.14",
    "react-dom": "^16.12.0",
    "react-redux": "^7.1.3",
    "react-redux-multilingual": "^2.0.2",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.2.0",
    "redux": "^4.0.4",
    "redux-logger": "^3.0.6"
  },
  "devDependencies": {
    "@babel/plugin-proposal-class-properties": "^7.7.0",
    "@babel/preset-env": "^7.7.1",
    "@babel/preset-react": "^7.7.0"
  },
  "babel": {
    "presets": [
      "@babel/preset-env",
      "@babel/preset-react"
    ],
    "plugins": [
      "@babel/plugin-proposal-class-properties"
    ]
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Here is the projectFiles.zip

[Question] Providing translate() to all children through react-router or one component

I'm curious if it is possible to provide translate() to all the components through react-router. So basically it would be provided to all children of the home route? I'm trying to find a way to limit how many times I am importing in the same libraries and modules for better performance. I'm going to keep playing around with it; but if you have any ideas I'd greatly appreciate it! Great package by the way really easy to use 👍

index.js

import React from 'react';
import { render } from 'react-dom';
import { IntlActions } from 'react-redux-multilingual';
import { store } from './redux/store';
import Root from './Root';
import '../public/styles.css';

const DEFAULT_LANGUAGE = 'ru';
store.dispatch(IntlActions.setLocale(DEFAULT_LANGUAGE));

render(<Root />, document.getElementById('root'));

Root.jsx

import React from 'react';
import { Provider } from 'react-redux/es';
import { IntlProvider } from 'react-redux-multilingual';
import { Router } from 'react-router/es';
import ReduxToastr from 'react-redux-toastr';
import { history, store } from './redux/store';
import componentRoutes from './dynamicRouting';
import { translations } from './modules';

const Root = () => (
  <Provider store={store}>
    <IntlProvider translations={translations}>
      <div className='provider'>
        <Router history={history} routes={componentRoutes} />
        <ReduxToastr
          timeOut={1500}
          newestOnTop={false}
          preventDuplicates
          position="top-right"
          transitionIn="bounceIn"
          transitionOut="bounceOut"
          progressBar
        />
      </div>
    </IntlProvider>
  </Provider>
);

export default Root;

dynamicRouting.js

import AppContainer from './modules/entry/AppContainer';
import HomePage from './modules/layout/HomePage';

const componentRoutes = {
  component: AppContainer,
  path: '/',
  indexRoute: { component: HomePage }
};

export default componentRoutes;

AppContainer.jsx

import { connect } from 'react-redux/es';
import App from './App';

export default connect()(App);

App.jsx

import React, { Component, PropTypes } from 'react';

class App extends Component {
  render() {
    const { children } = this.props;
    return (
      <div className="application">
        { children }
      </div>
    );
  }
}

App.propTypes = {
  children: PropTypes.element.isRequired,
};

export default App;

HomePage.jsx

import React, { PropTypes } from 'react';

const HomePage = ({ translate }) => (
  <div className='homepage'>
    <h1>{translate('hello')}</h1>
  </div>
);

HomePage.propTypes = {
  translate: PropTypes.func
};

export default HomePage;

Can i modify translation object??

use like this and if possible how can get string:
{
en: {
locale: 'en-US',
messages: {
sub1:{
hello: 'how are you {name}',
sub2:{
hello: 'how are you {name}'
}
}
}
},
zh: {
locale: 'zh',
messages: {
hello: '你好!你好吗 {name}'
}
}
}

Unnecessary base language messages

{
  en: {
    locale: 'en-US',
    messages: {
      'Some english string': 'Some english string'                 //**ablle to miss this?**
    }
  },
  de: {
    locale: 'de-DE',
    messages: {
      'Some english string': 'Some translated to de string'
    }
  }
}

translate is undefined

Hi, i use the second example "Translate using Context" but i dont have the method translate in my context object of my low order component:

My index

import React from 'react'
import ReactDOM from 'react-dom'
import { Router, hashHistory } from 'react-router'
import { Provider } from 'react-redux'
import { IntlProvider } from 'react-redux-multilingual'
import configureStore from './store/configureStore'

const store = configureStore()

const translation = {
    en: {
      locale: 'en-US',
      messages: {
        hello: 'how are you {name}'
      }
    },
    zh: {
      locale: 'zh',
      messages: {
        hello: '你好!你好吗 {name}'
      }
    }
 }

  ReactDOM.render(
    <Provider store={store}>
      <IntlProvider translations={translation}>
        <Router history={hashHistory}>
          {routes}
        </Router>
      </IntlProvider>
    </Provider>,
    document.getElementById('root')
  )

My reducers index

import { combineReducers } from 'redux'
import { IntlReducer as Intl } from 'react-redux-multilingual'

const rootReducer = combineReducers({
  Intl,
  ...
})

export default rootReducer

Could not find translations or locale on this.props

Im using select from material IU when i select empty option appears this message

Could not find translations or locale on this.props
at new IntlProvider (provider.js:59)
at constructClassInstance (react-dom.development.js:13308)
at updateClassComponent (react-dom.development.js:16985)
at beginWork$1 (react-dom.development.js:18505)
at HTMLUnknownElement.callCallback (react-dom.development.js:347)
at Object.invokeGuardedCallbackDev (react-dom.development.js:397)
at invokeGuardedCallback (react-dom.development.js:454)
at beginWork$$1 (react-dom.development.js:23217)
at performUnitOfWork (react-dom.development.js:22211)
at workLoopSync (react-dom.development.js:22185)

Form resets when language is changed.

I have a simple login form which have 2 inputs.
The placeholder for both of them is set through this library using withTranslate.

Everything works fine. But now when I type something inside any of the input, and then when I change the language, all the fields are emptied out.

I don't know why this thing is happening but I guess this is due to rerender. How can I overcome this problem?

Please Note: I am using redux-form

is it impossible to make static method for translate?

for example, in my react component, I want to use a custom class to handle Http errors, And I can't pass the translate method to this class.

class ForgetPassword extends Component {
	handleSubmitForm = async event => {
		event.preventDefault();

		await Http.post('v1/reset-password', getToken())
			.catch(response => {
				new HttpErrors(response);
			})
	};

	render() { Lab lab lab . }
}

export default ForgetPassword;

and here is my class

import _ from "lodash";
import NativeToast from "components/Toast/NativeToast";

class HttpErrors {
	constructor({response}) {
		this.error = '';
		this.response = response;
	}

	handleError = () => {
		switch (this.response.status) {
			case 404:
				this.error = translate('errors.404');
				break;
		}

		this.makeNativeToast();
	};

	makeNativeToast() {
		NativeToast({message: this.error, type: 'error'});
	}
}

export default HttpErrors;

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.