Kselax.ru

Hacker Kselax – the best hacker in the world

Menu
  • Blog
  • Contacts
  • wp plugin generator
  • English
    • Русский
Menu

How to use react-router with a few languages

Posted on 13 May, 201913 May, 2019 by admin

It is frequently need to create a site that will support a few languages, for example I’m going to create multilingual site which will support 3 languages for a while. Then I’m going to add a few more.

So, I want to build with 3 ua, ru, en. And in this article I’ll explain to you how to implement it

How does react-router works with multilingual sites

Short description and understanding what is being built. Our site will have links:

site.com – it will redirect to site.com/[locale]/

site.com/en/ – an English version
site.com/ru/ – a Russian version
site.com/ua/ – a Ukrainian version

site.com should redirect users to en or ru or ua

it redirect to ru if locale in the window.localStorage.getItem(‘locale’). If it is not initialized it will be initialized to ‘en‘ window.localStorage.setItem(‘locale’, ‘en’)

all the rest urls such as site.com/de/, site.com/sdf/, site.com/adfsdf… etc. will be redirected to 404 page.

when urls starts from site.com/ru and locale is set up to en it will take locale from the url and change saved local to the local of the url

So let’s get started!

We have to install react-router-dom 

1
npm i react-router-dom

 

and import components

1
2
3
4
5
6
import { BrowserRouter as Router,
         Route,
         Link,
         Redirect,
         Switch,
         withRouter } from 'react-router-dom'

Then create 4 components:

Home, About, Contacts and NoFound for a 404 error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const Home = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>Home</h1>
  </div>
}
 
const About = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>About</h1>
  </div>
}
 
const Contacts = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>Contacts</h1>
  </div>
}
 
const NoFound = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>404</h1>
  </div>
}

<LangButtons> is a component that renders three buttons en, ru, ua, which will change the language.

then we create LangRouter where put 3 routes to each language with regular expression /en/* /ru/* and /ua/*.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class LangRouter extends React.Component {
  constructor(props) {
    super(props)
 
    let locale = window.localStorage.getItem('locale')
    if (locale === null) {
      window.localStorage.setItem('locale', 'en')
      locale = 'ru'
    }
    this.state = {
      locale: locale
    }
  }
 
  setLocale = (newLocale) => {
    console.log('newLocale = ', newLocale);
    window.localStorage.setItem('locale', newLocale)
    this.setState({ locale: newLocale })
  }
 
  render() {
    const { locale } = this.state
    return (
      <Switch>
        <Route path="/" exact render={propRouter => {
          return <Redirect to={locale + "/"} />
        }} />
        <Route path="/en/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        }/>
        <Route path="/ru/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
        <Route path="/ua/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
        <Route path="*" render={
          propsRouter =>
            <NoFound
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
      </Switch>
    )
  }
}

It is a root component which stores locale of our app for all child’s components. In the constructor we check the window.localStorage on ‘local’ and if it is set up then we’ll initialize this.state.locale with its value and pass down. The function setLocal is used to pass downfall as it calls for two way binding. This function will be passed to buttons which will change this.state.locale.

in Route we use render because we have to pass setLocal and this.state.locale to children, so we can’t use component.

Now, let’s create App

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const App = (props) => {
  let { locale } = props
  let urlLocale = props.location.pathname.substring(1, 3)
  if ( locale !== urlLocale ) {
    props.setLocale(urlLocale)
    locale = urlLocale
  }
  return (
    <div>
      <Link to={"/" + locale + "/"}>Home</Link> |{' '}
      <Link to={"/" + locale + "/about"}>About</Link> |{' '}
      <Link to={"/" + locale + "/contacts"}>Contacts</Link>
      <Switch>
        <Route path={"/" + locale + "/"} exact render={propRouter =>
          <Home {...propRouter} {...props} />
        } />
        <Route path={"/" + locale + "/about"} render={propRouter =>
          <About {...propRouter} {...props} />
        } />
        <Route path={"/" + locale + "/contacts"} render={propRouter =>
          <Contacts {...propRouter} {...props} />
        } />
        <Route path="*" render={propRouter =>
          <NoFound {...propRouter} {...props} />
        } />
      </Switch>
    </div>
  )
}

It is accept props and check locale from the url if they different than the url value will be set up to locale from the parent component by calling function props.setLocale(urlLocale)

Then we see a few <Link> elements and Route where dynamically generated paths. Again we use render because we have to pass data to the children.

 

The last element is LangButtons.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class LangButtons extends React.Component {
  setLocale = (newLocale) => {
    const { locale } = this.props
    let url = '/' + newLocale + this.props.location.pathname.substring(3)
    this.props.history.push(url)
    this.props.setLocale(newLocale)
  }
 
  render() {
    return (
      <div>
        <button
          onClick={() => this.setLocale('ru')}
        >ru</button> | <button
          onClick={() => this.setLocale('en')}
        >en</button> | <button
          onClick={() => this.setLocale('ua')}
        >ua</button>
      </div>
    )
  }
}

Each button has it’s own event – handler, which call the props function setLocale and change locale

And here is all the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router,
         Route,
         Link,
         Redirect,
         Switch,
         withRouter } from 'react-router-dom'
 
class LangButtons extends React.Component {
  setLocale = (newLocale) => {
    const { locale } = this.props
    let url = '/' + newLocale + this.props.location.pathname.substring(3)
    this.props.history.push(url)
    this.props.setLocale(newLocale)
  }
 
  render() {
    return (
      <div>
        <button
          onClick={() => this.setLocale('ru')}
        >ru</button> | <button
          onClick={() => this.setLocale('en')}
        >en</button> | <button
          onClick={() => this.setLocale('ua')}
        >ua</button>
      </div>
    )
  }
}
 
const Home = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>Home</h1>
  </div>
}
 
const About = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>About</h1>
  </div>
}
 
const Contacts = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>Contacts</h1>
  </div>
}
 
const NoFound = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>404</h1>
  </div>
}
 
 
 
const App = (props) => {
  let { locale } = props
  let urlLocale = props.location.pathname.substring(1, 3)
  if ( locale !== urlLocale ) {
    props.setLocale(urlLocale)
    locale = urlLocale
  }
  return (
    <div>
      <Link to={"/" + locale + "/"}>Home</Link> |{' '}
      <Link to={"/" + locale + "/about"}>About</Link> |{' '}
      <Link to={"/" + locale + "/contacts"}>Contacts</Link>
      <Switch>
        <Route path={"/" + locale + "/"} exact render={propRouter =>
          <Home {...propRouter} {...props} />
        } />
        <Route path={"/" + locale + "/about"} render={propRouter =>
          <About {...propRouter} {...props} />
        } />
        <Route path={"/" + locale + "/contacts"} render={propRouter =>
          <Contacts {...propRouter} {...props} />
        } />
        <Route path="*" render={propRouter =>
          <NoFound {...propRouter} {...props} />
        } />
      </Switch>
    </div>
  )
}
 
 
 
class LangRouter extends React.Component {
  constructor(props) {
    super(props)
 
    let locale = window.localStorage.getItem('locale')
    if (locale === null) {
      window.localStorage.setItem('locale', 'en')
      locale = 'ru'
    }
    this.state = {
      locale: locale
    }
  }
 
  setLocale = (newLocale) => {
    console.log('newLocale = ', newLocale);
    window.localStorage.setItem('locale', newLocale)
    this.setState({ locale: newLocale })
  }
 
  render() {
    const { locale } = this.state
    return (
      <Switch>
        <Route path="/" exact render={propRouter => {
          return <Redirect to={locale + "/"} />
        }} />
        <Route path="/en/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        }/>
        <Route path="/ru/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
        <Route path="/ua/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
        <Route path="*" render={
          propsRouter =>
            <NoFound
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
      </Switch>
    )
  }
}
 
ReactDOM.render(
  <Router>
    <LangRouter />
  </Router>,
  document.getElementById('root')
)

 

The result is next

a bit refactored variant:

Показать »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router,
         Route,
         Link,
         Redirect,
         Switch,
         withRouter } from 'react-router-dom'
 
const LangButtons = ({ setLocale }) => {
  return (
    <div>
      <button
        onClick={() => setLocale('ru')}
      >ru</button> | <button
        onClick={() => setLocale('en')}
      >en</button> | <button
        onClick={() => setLocale('ua')}
      >ua</button>
    </div>
  )
}
 
const Home = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>Home</h1>
  </div>
}
 
const About = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>About</h1>
  </div>
}
 
const Contacts = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>Contacts</h1>
  </div>
}
 
const NoFound = (props) => {
  return <div>
    <LangButtons {...props} />
    <h1>404</h1>
  </div>
}
 
 
 
const App = (props) => {
  let { locale } = props
  let urlLocale = props.location.pathname.substring(1, 3)
  if ( locale !== urlLocale ) {
    props.setLocale(urlLocale)
    locale = urlLocale
  }
  return (
    <div>
      <Link to={"/" + locale + "/"}>Home</Link> |{' '}
      <Link to={"/" + locale + "/about"}>About</Link> |{' '}
      <Link to={"/" + locale + "/contacts"}>Contacts</Link>
      <Switch>
        <Route path={"/" + locale + "/"} exact render={propRouter =>
          <Home {...propRouter} {...props} />
        } />
        <Route path={"/" + locale + "/about"} render={propRouter =>
          <About {...propRouter} {...props} />
        } />
        <Route path={"/" + locale + "/contacts"} render={propRouter =>
          <Contacts {...propRouter} {...props} />
        } />
        <Route path="*" render={propRouter =>
          <NoFound {...propRouter} {...props} />
        } />
      </Switch>
    </div>
  )
}
 
 
 
class LangRouter extends React.Component {
  constructor(props) {
    super(props)
 
    let locale = window.localStorage.getItem('locale')
    if (locale === null) {
      window.localStorage.setItem('locale', 'en')
      locale = 'ru'
    }
    this.state = {
      locale: locale
    }
  }
 
  setLocale = (newLocale) => {
    const { locale } = this.state
    let url = '/' + newLocale + this.props.location.pathname.substring(3)
    this.props.history.push(url)
    console.log('newLocale = ', newLocale);
    window.localStorage.setItem('locale', newLocale)
    this.setState({ locale: newLocale })
  }
 
  render() {
    console.log('this = ', this);
    const { locale } = this.state
    return (
      <Switch>
        <Route path="/" exact render={propRouter => {
          return <Redirect to={locale + "/"} />
        }} />
        <Route path="/en/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        }/>
        <Route path="/ru/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
        <Route path="/ua/*" render={
          propsRouter =>
            <App
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
        <Route path="*" render={
          propsRouter =>
            <NoFound
              {...propsRouter}
              locale={locale}
              setLocale={this.setLocale}
            />
        } />
      </Switch>
    )
  }
}
 
LangRouter = withRouter(LangRouter)
 
ReactDOM.render(
  <Router>
    <LangRouter />
  </Router>,
  document.getElementById('root')
)

 

the end

2 thoughts on “How to use react-router with a few languages”

  1. Narek says:
    8 April, 2020 at 20:14

    how to render different components according to selected language? thanks in advance

    Reply
    1. admin says:
      28 May, 2020 at 16:12

      You have to store somewhere in a global variable locale the current selected language. The main source of truth should be an url. When the page is loaded you get the language from the url and initialize the global variable. Usually, I put the language into the redux store and from there make it available into all the components

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Categories

  • bash (1)
  • English (9)
  • JavaScript (4)
  • node.js (22)
  • photoshop (1)
  • php (3)
  • React (9)
  • sclerotic (6)
  • Ubuntu (10)
  • Uncategorized (13)
  • Wordpress (1)

Tags

Ajax apache2 automation bash chrome-extension command line editor ejs email English English-grammar framework functions git graphql handlebars hybrid app installation javascript js linux newbie node.js node.js javascript nodemailer npm objects Performance php phpmyadmin playonlinux promise rabbitmq React react-router redis reverse-proxy session shell socket.io sublime text 3 time zones ubuntu unity webpack

Recent Comments

  • damien on How to install npm and nodejs the latest versions on ubuntu
  • Cam on How to install npm and nodejs the latest versions on ubuntu
  • Pierre on socket.io with apache as a reverse proxy on the CentOS
  • admin on How to use react-router with a few languages
  • admin on How to install npm and nodejs the latest versions on ubuntu
©2021 Kselax.ru Theme by ThemeGiant