I'm trying to build a multilingual site where the language preference is part of the URL, e.g.
http://example.com/en/<somepage> (English)
http://example.com/jp/<somepage> (Japanese)
http://example.com/../ (etc)
The language selection is supposed to be dynamic and new languages will be added as time goes (the en and jp part should be variable).
I went through documentation and examples but couldn't find such a case. How can I configure my routes in such a way? Is it documented somewhere? Was this discussed before (it seems like a common pattern used on many sites).
Overview covers nesting, although for a different use case.
Your route config might look like:
var routes = (
<Route name="app" path="/:lang" handler={App}>
<Route name="something" handler={SomePage}/>
<Route name="other" handler={SomeOtherPage}/>
<DefaultRoute handler={YetAnotherPage}/>
</Route>
);
+
Router.run(routes, function (Handler, state) {
React.render(<Handler params={state.params}/>, rootEl);
});
+
var App = React.createClass({
render() {
return <RouteHandler lang={this.props.params.lang} />
}
}
This way all your nested route handlers (SomePage, etc) will get lang prop.
How does the proposed solution above handle the default language case, ie having:
http://example.com/... (english) <-- no :lang param right?
http://example.com/fr/... (french)
http://example.com/de/... (german)
I found a router setup that suggests a solution here: http://stackoverflow.com/a/35075669/1253297.
I modified it to support the behavior I was looking for and came up with this:
export default function createRoutes() {
const langs = ['fr', 'de'];
const subRoutes = (
<Route>
<IndexRoute component={Home}/>
<Route path="about" component={About}/>
<Route path=":article" component={Article}/>
<Route path="*" component={NotFound}/>
</Route>
);
return (
<Route path="/" component={App}>
{langs.map(lang => (
<Route key={lang} path={lang}>
{subRoutes}
</Route>
))}
{subRoutes}
</Route>
);
}
This setup seems to work in my application so far, but it does feel inelegant.
I would love to know what you think of it
_Edit:_ now I am stumped again because I am not seeing how the solution above exposes which is the current lang to the rest of the app.
@Maximilianos You would get that as a param on your route components. A component at the top of your subRoutes tree could set that in some global or on context when it mounts or receives props.
Hey @timdorr thanks for help. I was just looking at getting the lang from the passed props like you suggest, but unlike gaearon's solution, because I am not using a dynamic segment in my url for the language (no :lang) I don't get that bit of info passed down to my rendering components params.
The best I seem to be able to get is the props.location.pathname but extracting the lang from this prop seems hacky.
Is there a way to define a prop on a route that would get passed down to its children?
If not do you think using the onEnter hook is a valid place to set this global state?
Using redux I could potentially use something like:
export default function createRoutes(store) {
const subRoutes = (
<Route>
<IndexRoute component={Home}/>
<Route path="about" component={About}/>
<Route path=":article" component={Article}/>
<Route path="*" component={NotFound}/>
</Route>
);
return (
<Route path="/" component={App}>
<Route path="fr" onEnter={() => store.dispatch(switchLang('fr'))}>
{subRoutes}
</Route>
<Route path="de" onEnter={() => store.dispatch(switchLang('de'))}>
{subRoutes}
</Route>
{subRoutes}
</Route>
);
}
_* I removed the map operation from the configuration to make it slighty easier to read, otherwise it is the same as before_
Most helpful comment
Overview covers nesting, although for a different use case.
Your route config might look like:
+
+
This way all your nested route handlers (
SomePage, etc) will getlangprop.