Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n support #363

Open
zintaen opened this issue Dec 2, 2017 · 8 comments
Open

i18n support #363

zintaen opened this issue Dec 2, 2017 · 8 comments

Comments

@zintaen
Copy link

zintaen commented Dec 2, 2017

Would you kindy advice me how to support i18n in your boilerplate @bertho-zero, i'm new to redux/duck and trying to adapt them :) I tried to follow some guides from erikas project

erikras/react-redux-universal-hot-example#140

but stuck at Locale switcher part, hope u can help me out

@firdausious
Copy link

@cambeme Well. i'm using this lib https://react.i18next.com/ , and works perfectly. Even with switcher

@zintaen
Copy link
Author

zintaen commented Dec 3, 2017

Did you appied i18next into bertho's boilerplate @firdausious? Can you guide me what i should modify? I'm still struggling the whole last week :(

@vermotr
Copy link

vermotr commented Jul 25, 2018

@firdausious Can you help me with this?

@vermotr
Copy link

vermotr commented Jul 31, 2018

So, based on the fork of @simpleblack, I have this:

packagage.json:

  "dependencies": {
    
    "i18next": "^11.5.0",
    "i18next-express-middleware": "^1.2.0",
    "i18next-node-fs-backend": "^1.2.1",
    
    "react-i18next": "^7.10.1",
    
}

src/i18n-server.js:

import i18n from 'i18next';
import Backend from 'i18next-node-fs-backend';
import { LanguageDetector } from 'i18next-express-middleware';

i18n
	.use(Backend)
	.use(LanguageDetector)
	.init({
		fallbackLng: 'fr',

		// have a common namespace used around the full app
		ns: ['common'],
		defaultNS: 'common',

		debug: true,

		interpolation: {
			escapeValue: false // not needed for react!!
		},

		backend: {
			loadPath: 'src/locales/{{lng}}/{{ns}}.json',
			jsonIndent: 2
		}
	})
	.loadLanguages(['fr', 'en']);

export default i18n;

src/i18n-client.js:

import i18n from 'i18next';

i18n
	.init({
		whitelist: ['fr', 'en'],
		fallbackLng: 'fr',

		// have a common namespace used around the full app
		ns: ['common'],
		defaultNS: 'common',

		debug: true,

		interpolation: {
			escapeValue: false, // not needed for react!!
		}
	});

export default i18n;

src/server.js:

import { I18nextProvider } from 'react-i18next';
import i18nMiddleware from 'i18next-express-middleware';
import i18n from './i18n-server';

app
	.use()
	
	.use(i18nMiddleware.handle(i18n));

app.use(async (req, res) => {
	
	const locale = req.language;
	const resources = i18n.getResourceBundle(locale, 'common');
	const i18nClient = { locale, resources };

	const i18nServer = i18n.cloneInstance();
	i18nServer.changeLanguage(locale);

	function hydrate() {
		res.write('<!doctype html>');
		ReactDOM.renderToNodeStream(<Html
			assets={webpackIsomorphicTools.assets()}
			store={store}
			i18n={i18nClient} // Here
		/>).pipe(res);
	}

	const component = (
		
			<I18nextProvider i18n={i18nServer}>
				
			</I18nextProvider>
		
	)

	

	const html = (
		<Html
			assets={webpackIsomorphicTools.assets()}
			bundles={bundles}
			content={content}
			store={store}
			i18n={i18nClient} // Here
		/>
	);
}

src/client.js:

import { I18nextProvider } from 'react-i18next';
import i18n from './i18n-client';

const hydrate = async _routes => {
	i18n.changeLanguage(window.__i18n.locale);
	i18n.addResourceBundle(window.__i18n.locale, 'common', window.__i18n.resources, true);
	
	ReactDOM.hydrate(
		<HotEnabler>
			<I18nextProvider i18n={i18n} ></I18nextProvider>

helpers/Html.js:

<script dangerouslySetInnerHTML={{__html: `window.__i18n=${serialize(i18n)};`}} charSet="UTF-8" />

And the locales files:

src
├── locales
│   ├── en
│   │   └── common.json
│   └── fr
│       └── common.json

With this configuration, everything works well, but I would like to add the language parameter in the route path. Currently, we can change the language by adding this parameter: /?lng=en or /?lng=fr, but I prefer something like this: /en/ or /fr/.

Can you help me with this?

@bertho-zero
Copy link
Owner

bertho-zero commented Jul 31, 2018

I would rather have used https://github.com/yahoo/react-intl.
But in any case I have not yet studied the subject.

For your problem you should edit routes and use the react-router params (https://reacttraining.com/react-router/web/example/url-params):

Example (pseudo-code):

const routes = [
  {
    component: App,
    routes: [
      { path: '/(:lang/)', exact: true, component: Home },
      { path: '/(:lang/)about', component: About },
      { path: '/(:lang/)chat', component: Chat },
      { path: '/(:lang/)login', component: Login },
      { path: '/(:lang/)login-success', component: isAuthenticated(LoginSuccess) },
      { path: '/(:lang/)register', component: isNotAuthenticated(Register) },
      { component: NotFound }
    ]
  }
];

then use params.lang from:

const { components, match, params } = await asyncMatchRoutes(routes, nextProps.location.pathname);

const { components, match, params } = await asyncMatchRoutes(routes, req.path);

@vermotr
Copy link

vermotr commented Aug 1, 2018

Thanks and I solved my problem by adding theses lines in src/i18n-client.js:

i18n
	.use(Backend)
	.use(LanguageDetector)
	.init({
		

		detection: {
			// order and from where user language should be detected
			order: ['path'],

			// keys or params to lookup language from
			lookupPath: 'lng',
			lookupFromPathIndex: 0
		}
	});

And here the routes.js file:

const routes = [
  {
    component: App,
    routes: [
      { path: '/:lng(fr|en)?/', exact: true, component: Home },
      { path: '/:lng?/about', component: About },
      { path: '/:lng?/chat', component: Chat },
      { path: '/:lng?/login', component: Login },
      { path: '/:lng?/login-success', component: isAuthenticated(LoginSuccess) },
      { path: '/:lng?/register', component: isNotAuthenticated(Register) },
      { component: NotFound }
    ]
  }
];

@bertho-zero do you want a PR to add this feature or do you prefer to use https://github.com/yahoo/react-intl?

@bertho-zero
Copy link
Owner

If it is not too much work you can do a PR, I would do one with react-intl and I could then choose. And then those who want to change libraries will only have to look at your PR.

@hendrik-h-dev
Copy link

@vermotr Thank you for your work, I actually try to implement i18next but with your changes, but it's not working. I read the react-i18n documentation but wasn't able to solve the issue. Would it be possible to guide me little bit through the integration or make a pull PR of you changes, that I can try to figure out what are the differences in my code or possible issues.
Thanks in advance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants