mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-26 07:25:20 +00:00
JIT choose default docs language and persist user selections with localStorage
This commit is contained in:
@@ -97,7 +97,7 @@ module.exports = ({page, boundActionCreators}, pluginOptions) => {
|
||||
|
||||
createRedirect({
|
||||
fromPath: nonLocalizedPath,
|
||||
toPath: path,
|
||||
toPath: `/docs-language-redirect/?${nonLocalizedPath}`,
|
||||
redirectInBrowser: true,
|
||||
Language: language,
|
||||
});
|
||||
|
||||
23
src/pages/docs-language-redirect.js
Normal file
23
src/pages/docs-language-redirect.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Redirect} from 'react-router-dom';
|
||||
import {getSelectedLanguage} from 'utils/languageUtils';
|
||||
|
||||
const DocsRedirect = ({location}) => {
|
||||
// Redirect the user to their most recent locale, or English as a fallback.
|
||||
const language = getSelectedLanguage();
|
||||
|
||||
return <Redirect to={`/${language}${location.search.substr(1)}`} />;
|
||||
};
|
||||
|
||||
DocsRedirect.propTypes = {
|
||||
location: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default DocsRedirect;
|
||||
@@ -11,9 +11,7 @@ import TitleAndMetaTags from 'components/TitleAndMetaTags';
|
||||
import Link from 'gatsby-link';
|
||||
import React from 'react';
|
||||
import {sharedStyles} from 'theme';
|
||||
|
||||
// $FlowFixMe This is a valid path
|
||||
import languages from '../../crowdin/languages.json';
|
||||
import {getTranslatedLanguages} from 'utils/languageUtils';
|
||||
|
||||
const Translations = () => (
|
||||
<Container>
|
||||
@@ -27,7 +25,7 @@ const Translations = () => (
|
||||
languages:
|
||||
</p>
|
||||
<ul>
|
||||
{languages.map(language => (
|
||||
{getTranslatedLanguages().map(language => (
|
||||
<li key={language}>
|
||||
<Link to={`/${language}/docs/hello-world.html`}>
|
||||
{language}
|
||||
|
||||
@@ -9,16 +9,26 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {createLinkDocs} from 'utils/createLink';
|
||||
import {sectionListDocs} from 'utils/sectionList';
|
||||
import {setSelectedLanguage} from 'utils/languageUtils';
|
||||
|
||||
const Docs = ({data, location}) => (
|
||||
<MarkdownPage
|
||||
createLink={createLinkDocs}
|
||||
location={location}
|
||||
markdownRemark={data.markdownRemark}
|
||||
sectionList={sectionListDocs}
|
||||
titlePostfix=" - React"
|
||||
/>
|
||||
);
|
||||
const Docs = ({data, location}) => {
|
||||
// Store the user's most recent locale based on the current URL.
|
||||
// We'll restore this language when they visit a new (unlocalized) URL.
|
||||
const matches = location.pathname.substr(1).split('/');
|
||||
if (matches.length > 1) {
|
||||
setSelectedLanguage(matches[0]);
|
||||
}
|
||||
|
||||
return (
|
||||
<MarkdownPage
|
||||
createLink={createLinkDocs}
|
||||
location={location}
|
||||
markdownRemark={data.markdownRemark}
|
||||
sectionList={sectionListDocs}
|
||||
titlePostfix=" - React"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Docs.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
|
||||
@@ -24,7 +24,6 @@ type CreateLinkBaseProps = {
|
||||
|
||||
const createLinkBlog = ({
|
||||
isActive,
|
||||
isLocalized,
|
||||
item,
|
||||
location,
|
||||
section,
|
||||
@@ -32,7 +31,6 @@ const createLinkBlog = ({
|
||||
return (
|
||||
<Link
|
||||
css={[linkCss, isActive && activeLinkCss]}
|
||||
isLocalized={isLocalized}
|
||||
location={location}
|
||||
to={item.id}>
|
||||
{isActive && <span css={activeLinkBefore} />}
|
||||
@@ -43,7 +41,6 @@ const createLinkBlog = ({
|
||||
|
||||
const createLinkCommunity = ({
|
||||
isActive,
|
||||
isLocalized,
|
||||
item,
|
||||
location,
|
||||
section,
|
||||
@@ -65,7 +62,7 @@ const createLinkCommunity = ({
|
||||
}
|
||||
return createLinkDocs({
|
||||
isActive,
|
||||
isLocalized,
|
||||
isLocalized: false,
|
||||
item,
|
||||
location,
|
||||
section,
|
||||
@@ -97,7 +94,6 @@ type CreateLinkTutorialProps = {
|
||||
|
||||
const createLinkTutorial = ({
|
||||
isActive,
|
||||
isLocalized,
|
||||
item,
|
||||
location,
|
||||
onLinkClick,
|
||||
@@ -106,7 +102,6 @@ const createLinkTutorial = ({
|
||||
return (
|
||||
<Link
|
||||
css={[linkCss, isActive && activeLinkCss]}
|
||||
isLocalized={isLocalized}
|
||||
location={location}
|
||||
onClick={onLinkClick}
|
||||
to={item.href}>
|
||||
|
||||
46
src/utils/languageUtils.js
Normal file
46
src/utils/languageUtils.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
// $FlowFixMe This is a valid path
|
||||
import languagesArray from '../../crowdin/languages.json';
|
||||
|
||||
const DEFAULT_LANGUAGE = 'en-US';
|
||||
|
||||
const languagesMap = languagesArray.reduce((map: Object, language: string) => {
|
||||
map[language] = true;
|
||||
return map;
|
||||
}, Object.create(null));
|
||||
|
||||
export function getTranslatedLanguages(): Array<string> {
|
||||
return languagesArray;
|
||||
}
|
||||
|
||||
export function getSelectedLanguage(): string {
|
||||
let language = localStorage.getItem('selectedLanguage');
|
||||
if (languagesMap[language]) {
|
||||
return ((language: any): string);
|
||||
} else {
|
||||
const {languages} = navigator;
|
||||
for (let i = 0; i < languages.length; i++) {
|
||||
language = languages[i];
|
||||
if (languagesMap[language]) {
|
||||
return language;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DEFAULT_LANGUAGE;
|
||||
}
|
||||
|
||||
export function setSelectedLanguage(language: string): void {
|
||||
if (languagesMap[language]) {
|
||||
localStorage.setItem('selectedLanguage', language);
|
||||
} else if (process.env.NODE_ENV !== 'production') {
|
||||
console.warn(
|
||||
`Specified language "${language}" is not a valid translation.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user