From f2180a33e89f284256d07efc805fa350fddb5d87 Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Sat, 31 Aug 2019 10:06:36 +0400 Subject: [PATCH 01/13] Add Translatable component - Use YAML file to store translations - Make texts in components translatable --- content/strings.yml | 6 ++++++ src/components/CodeEditor/CodeEditor.js | 11 +++++++---- src/components/CodeExample/CodeExample.js | 5 ++++- src/components/ErrorDecoder/ErrorDecoder.js | 13 ++++++++++--- src/components/MarkdownPage/MarkdownPage.js | 3 ++- src/components/Translatable/Translatable.js | 18 ++++++++++++++++++ src/components/Translatable/index.js | 3 +++ 7 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 content/strings.yml create mode 100644 src/components/Translatable/Translatable.js create mode 100644 src/components/Translatable/index.js diff --git a/content/strings.yml b/content/strings.yml new file mode 100644 index 00000000000..8bec50a1a7b --- /dev/null +++ b/content/strings.yml @@ -0,0 +1,6 @@ +"Babel could not be loaded": "" +"This can be caused by an ad blocker. If you're using one, consider adding reactjs.org to the whitelist so the live code examples will work.": "" +"Loading code example...": "" +"When you encounter an error, you'll receive a link to this page for that specific error and we'll show you the full error text.": "" +"The full text of the error you just encountered is:": "" +"Edit this page": "" \ No newline at end of file diff --git a/src/components/CodeEditor/CodeEditor.js b/src/components/CodeEditor/CodeEditor.js index 2abb8ad4b2d..474b8d5dc88 100644 --- a/src/components/CodeEditor/CodeEditor.js +++ b/src/components/CodeEditor/CodeEditor.js @@ -10,6 +10,7 @@ import Remarkable from 'remarkable'; import {LiveEditor, LiveProvider} from 'react-live'; import {colors, media} from 'theme'; import MetaTitle from 'templates/components/MetaTitle'; +import Translatable from '../Translatable'; // Replace unicode to text for other languages const unicodeToText = text => @@ -62,12 +63,14 @@ class CodeEditor extends Component { if (showBabelErrorMessage) { errorMessage = ( - Babel could not be loaded. + Babel could not be loaded.

- This can be caused by an ad blocker. If you're using one, consider - adding reactjs.org to the whitelist so the live code examples will - work. + + This can be caused by an ad blocker. If you're using one, consider + adding reactjs.org to the whitelist so the live code examples will + work. +
); } else if (error != null) { diff --git a/src/components/CodeExample/CodeExample.js b/src/components/CodeExample/CodeExample.js index bc5d6ed10f8..27f9a563f74 100644 --- a/src/components/CodeExample/CodeExample.js +++ b/src/components/CodeExample/CodeExample.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import {colors, media} from 'theme'; import CodeEditor from '../CodeEditor/CodeEditor'; +import Translatable from '../Translatable'; class CodeExample extends Component { render() { @@ -61,7 +62,9 @@ class CodeExample extends Component { {loaded ? ( ) : ( -

Loading code example...

+

+ Loading code example... +

)} ); diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index d179a09be14..d3ca18ee222 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -8,6 +8,7 @@ import React from 'react'; import type {Node} from 'react'; +import Translatable from '../Translatable'; function replaceArgs(msg: string, argList: Array): string { let argIdx = 0; @@ -69,8 +70,10 @@ function ErrorResult(props: {|code: ?string, msg: string|}) { if (!code) { return (

- When you encounter an error, you'll receive a link to this page for that - specific error and we'll show you the full error text. + + When you encounter an error, you'll receive a link to this page for + that specific error and we'll show you the full error text. +

); } @@ -78,7 +81,11 @@ function ErrorResult(props: {|code: ?string, msg: string|}) { return (

- The full text of the error you just encountered is: + + + The full text of the error you just encountered is: + +

{urlify(errorMsg)} diff --git a/src/components/MarkdownPage/MarkdownPage.js b/src/components/MarkdownPage/MarkdownPage.js index 4e4e082f80d..ea3156b107c 100644 --- a/src/components/MarkdownPage/MarkdownPage.js +++ b/src/components/MarkdownPage/MarkdownPage.js @@ -18,6 +18,7 @@ import {sharedStyles} from 'theme'; import createCanonicalUrl from 'utils/createCanonicalUrl'; import type {Node} from 'types'; +import Translatable from '../Translatable'; type Props = { authors: Array, @@ -115,7 +116,7 @@ const MarkdownPage = ({ href={`https://github.com/reactjs/reactjs.org/tree/master/${ markdownRemark.fields.path }`}> - Edit this page + Edit this page
)} diff --git a/src/components/Translatable/Translatable.js b/src/components/Translatable/Translatable.js new file mode 100644 index 00000000000..5df28de3813 --- /dev/null +++ b/src/components/Translatable/Translatable.js @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * @emails react-core + * @flow + */ + +// $FlowFixMe +import strings from '../../../content/strings.yml'; + +const Translatable = ({children}: {children: string}) => { + if (children in strings && strings[children] !== '') { + return strings[children]; + } + return children; +}; + +export default Translatable; diff --git a/src/components/Translatable/index.js b/src/components/Translatable/index.js new file mode 100644 index 00000000000..44b44cef6ab --- /dev/null +++ b/src/components/Translatable/index.js @@ -0,0 +1,3 @@ +import Translatable from './Translatable'; + +export default Translatable; From e63db10ae166a307db1255975cde85d51a2f7815 Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Sat, 31 Aug 2019 10:27:59 +0400 Subject: [PATCH 02/13] Translate 404 page - Add a `translate` function to translate text given the argument - Use `translate` function to translate strings in variables and props - Use `translate` in Translatable component --- content/strings.yml | 5 ++++- src/components/Translatable/Translatable.js | 8 ++------ src/components/Translatable/index.js | 1 + src/components/Translatable/translate.js | 16 ++++++++++++++++ src/pages/404.js | 19 ++++++++++++++----- 5 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 src/components/Translatable/translate.js diff --git a/content/strings.yml b/content/strings.yml index 8bec50a1a7b..4df320318f1 100644 --- a/content/strings.yml +++ b/content/strings.yml @@ -3,4 +3,7 @@ "Loading code example...": "" "When you encounter an error, you'll receive a link to this page for that specific error and we'll show you the full error text.": "" "The full text of the error you just encountered is:": "" -"Edit this page": "" \ No newline at end of file +"Edit this page": "" +"We couldn't find what you were looking for.": "" +"Page Not Found": "" +"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.": "" \ No newline at end of file diff --git a/src/components/Translatable/Translatable.js b/src/components/Translatable/Translatable.js index 5df28de3813..e2135456443 100644 --- a/src/components/Translatable/Translatable.js +++ b/src/components/Translatable/Translatable.js @@ -5,14 +5,10 @@ * @flow */ -// $FlowFixMe -import strings from '../../../content/strings.yml'; +import {translate} from './translate'; const Translatable = ({children}: {children: string}) => { - if (children in strings && strings[children] !== '') { - return strings[children]; - } - return children; + return translate(children); }; export default Translatable; diff --git a/src/components/Translatable/index.js b/src/components/Translatable/index.js index 44b44cef6ab..df289034b1e 100644 --- a/src/components/Translatable/index.js +++ b/src/components/Translatable/index.js @@ -1,3 +1,4 @@ import Translatable from './Translatable'; +export {translate} from './translate'; export default Translatable; diff --git a/src/components/Translatable/translate.js b/src/components/Translatable/translate.js new file mode 100644 index 00000000000..c4e7b5572de --- /dev/null +++ b/src/components/Translatable/translate.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * @emails react-core + * @flow + */ + +// $FlowFixMe +import strings from '../../../content/strings.yml'; + +export const translate = text => { + if (text in strings && strings[text] !== '') { + return strings[text]; + } + return text; +}; diff --git a/src/pages/404.js b/src/pages/404.js index b5977ce621c..5fe380ca383 100644 --- a/src/pages/404.js +++ b/src/pages/404.js @@ -11,6 +11,7 @@ import TitleAndMetaTags from 'components/TitleAndMetaTags'; import Layout from 'components/Layout'; import React from 'react'; import {sharedStyles} from 'theme'; +import Translatable, {translate} from '../components/Translatable'; type Props = { location: Location, @@ -21,13 +22,21 @@ const PageNotFound = ({location}: Props) => (
-
Page Not Found
- +
+ Page Not Found +
+
-

We couldn't find what you were looking for.

- Please contact the owner of the site that linked you to the - original URL and let them know their link is broken. + + We couldn't find what you were looking for. + +

+

+ + Please contact the owner of the site that linked you to the + original URL and let them know their link is broken. +

From e5ecf31f019f4536ccf61a305823138d711ee153 Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Sat, 31 Aug 2019 10:28:33 +0400 Subject: [PATCH 03/13] Add flow type to translate function argument --- src/components/Translatable/translate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Translatable/translate.js b/src/components/Translatable/translate.js index c4e7b5572de..2cb299969da 100644 --- a/src/components/Translatable/translate.js +++ b/src/components/Translatable/translate.js @@ -8,7 +8,7 @@ // $FlowFixMe import strings from '../../../content/strings.yml'; -export const translate = text => { +export const translate = (text: string) => { if (text in strings && strings[text] !== '') { return strings[text]; } From eadd6fcaad6745412a9f574fb8326bb44ff5edcf Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Sat, 31 Aug 2019 10:41:17 +0400 Subject: [PATCH 04/13] Translate homepage and languages page --- content/strings.yml | 11 ++++++++++- .../TitleAndMetaTags/TitleAndMetaTags.js | 5 ++++- src/pages/index.js | 17 +++++++++++------ src/pages/languages.js | 19 +++++++++++++------ 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/content/strings.yml b/content/strings.yml index 4df320318f1..4fefb5cc6ec 100644 --- a/content/strings.yml +++ b/content/strings.yml @@ -6,4 +6,13 @@ "Edit this page": "" "We couldn't find what you were looking for.": "" "Page Not Found": "" -"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.": "" \ No newline at end of file +"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.": "" +"Get Started": "" +"Take the Tutorial": "" +"A JavaScript library for building user interfaces": "" +"The React documentation is available in the following languages:": "" +"In Progress": "" +"Needs Contributors": "" +"Don't see your language above?": "" +"Let us know": "" +"Contribute": "" \ No newline at end of file diff --git a/src/components/TitleAndMetaTags/TitleAndMetaTags.js b/src/components/TitleAndMetaTags/TitleAndMetaTags.js index facc5da7f8c..bc6b50754bc 100644 --- a/src/components/TitleAndMetaTags/TitleAndMetaTags.js +++ b/src/components/TitleAndMetaTags/TitleAndMetaTags.js @@ -8,10 +8,13 @@ import Helmet from 'react-helmet'; import React from 'react'; import {urlRoot} from 'site-constants'; +import {translate} from '../Translatable'; // $FlowFixMe This is a valid path import languages from '../../../content/languages.yml'; -const defaultDescription = 'A JavaScript library for building user interfaces'; +const defaultDescription = translate( + 'A JavaScript library for building user interfaces', +); type Props = { title: string, diff --git a/src/pages/index.js b/src/pages/index.js index b5dd5c1c13e..9fa03b873d3 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -8,6 +8,7 @@ import ButtonLink from 'components/ButtonLink'; import Container from 'components/Container'; import Flex from 'components/Flex'; import CodeExample from 'components/CodeExample'; +import Translatable, {translate} from 'components/Translatable'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import {graphql} from 'gatsby'; @@ -50,7 +51,9 @@ class Home extends Component { return (
@@ -133,7 +136,9 @@ class Home extends Component { fontSize: 30, }, }}> - A JavaScript library for building user interfaces + + A JavaScript library for building user interfaces +

- Get Started + Get Started - Take the Tutorial + Take the Tutorial @@ -294,12 +299,12 @@ class Home extends Component { }}> - Get Started + Get Started - Take the Tutorial + Take the Tutorial diff --git a/src/pages/languages.js b/src/pages/languages.js index f0309a3bb1c..451de788641 100644 --- a/src/pages/languages.js +++ b/src/pages/languages.js @@ -9,6 +9,7 @@ import Layout from 'components/Layout'; import Container from 'components/Container'; import Header from 'components/Header'; import TitleAndMetaTags from 'components/TitleAndMetaTags'; +import Translatable from 'components/Translatable'; import React from 'react'; import {urlRoot} from 'site-constants'; import {media, sharedStyles} from 'theme'; @@ -55,24 +56,30 @@ const Languages = ({location}: Props) => (

- The React documentation is available in the following languages: + + The React documentation is available in the following languages: +

-

In Progress

+

+ In Progress +

-

Needs Contributors

+

+ Needs Contributors +

- Don't see your language above?{' '} + Don't see your language above?{' '} - Let us know + Let us know .

@@ -157,7 +164,7 @@ const Language = ({code, name, status, translatedName}) => { href={`https://github.com/reactjs/${prefix}reactjs.org/`} target="_blank" rel="noopener"> - Contribute + Contribute
From fcc6a54b50d41799a4c5005da9675b346c37d4ee Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Sat, 31 Aug 2019 10:47:48 +0400 Subject: [PATCH 05/13] Translate blog, codepen example, and navigational footer strings --- content/strings.yml | 8 +++++++- src/templates/blog.js | 5 +++-- src/templates/codepen-example.js | 7 +++++-- .../components/NavigationFooter/NavigationFooter.js | 9 +++++++-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/content/strings.yml b/content/strings.yml index 4fefb5cc6ec..ae558afad6d 100644 --- a/content/strings.yml +++ b/content/strings.yml @@ -15,4 +15,10 @@ "Needs Contributors": "" "Don't see your language above?": "" "Let us know": "" -"Contribute": "" \ No newline at end of file +"Contribute": "" +"Redirecting to Codepen...": "" +"Not automatically redirecting?": "" +"All posts ...": "" +"Recent Posts": "" +"Previous article": "" +"Next article": "" \ No newline at end of file diff --git a/src/templates/blog.js b/src/templates/blog.js index 57967afcce5..c599bb9be2a 100644 --- a/src/templates/blog.js +++ b/src/templates/blog.js @@ -8,11 +8,12 @@ import React from 'react'; import {graphql} from 'gatsby'; import Layout from 'components/Layout'; import MarkdownPage from 'components/MarkdownPage'; +import {translate} from 'components/Translatable'; import {createLinkBlog} from 'utils/createLink'; const toSectionList = allMarkdownRemark => [ { - title: 'Recent Posts', + title: translate('Recent Posts'), items: allMarkdownRemark.edges .map(({node}) => ({ id: node.fields.slug, @@ -20,7 +21,7 @@ const toSectionList = allMarkdownRemark => [ })) .concat({ id: '/blog/all.html', - title: 'All posts ...', + title: translate('All posts ...'), }), }, ]; diff --git a/src/templates/codepen-example.js b/src/templates/codepen-example.js index 9b752aee6ca..0e976d128f5 100644 --- a/src/templates/codepen-example.js +++ b/src/templates/codepen-example.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import Container from 'components/Container'; import Layout from 'components/Layout'; +import Translatable from 'components/Translatable'; import {colors} from 'theme'; // Copied over styles from ButtonLink for the submit btn @@ -34,7 +35,9 @@ class CodepenExample extends Component { return ( -

Redirecting to Codepen...

+

+ Redirecting to Codepen... +

{ @@ -45,7 +48,7 @@ class CodepenExample extends Component {

- Not automatically redirecting? + Not automatically redirecting?

diff --git a/src/templates/components/NavigationFooter/NavigationFooter.js b/src/templates/components/NavigationFooter/NavigationFooter.js index 9ee0e95190f..635c6e33a6c 100644 --- a/src/templates/components/NavigationFooter/NavigationFooter.js +++ b/src/templates/components/NavigationFooter/NavigationFooter.js @@ -6,6 +6,7 @@ import Container from 'components/Container'; import Flex from 'components/Flex'; +import Translatable from 'components/Translatable'; import {Link} from 'gatsby'; import PropTypes from 'prop-types'; import React from 'react'; @@ -40,7 +41,9 @@ const NavigationFooter = ({next, prev, location}) => { {prev && (

- Previous article + + Previous article +
{ textAlign: 'right', }}>
- Next article + + Next article +
Date: Thu, 5 Sep 2019 11:16:18 +0400 Subject: [PATCH 06/13] Translate children of React elements in Translatable - This functionality only works one level deep - Translate acknowledgements --- content/strings.yml | 10 ++- src/components/Translatable/Translatable.js | 33 +++++++++- src/pages/acknowledgements.html.js | 67 +++++++++++++-------- 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/content/strings.yml b/content/strings.yml index ae558afad6d..e4f20e7e787 100644 --- a/content/strings.yml +++ b/content/strings.yml @@ -21,4 +21,12 @@ "All posts ...": "" "Recent Posts": "" "Previous article": "" -"Next article": "" \ No newline at end of file +"Next article": "" +"React - Acknowledgements": "" +"We'd like to thank all of our contributors:": "" +"In addition, we're grateful to": "" +"<0>Jeff Barczewski for allowing us to use the <1>react package name on npm.": "" +"<0>Christopher Aue for letting us use the <1>reactjs.com domain name and the <2>@reactjs username on Twitter.": "" +"<0>ProjectMoon for letting us use the <1>flux package name on npm.": "" +"Shane Anderson for allowing us to use the <1>react org on GitHub.": "" +"<0>Dmitri Voronianski for letting us use the <1>Oceanic Next color scheme on this website.": "" \ No newline at end of file diff --git a/src/components/Translatable/Translatable.js b/src/components/Translatable/Translatable.js index e2135456443..6592d8ede57 100644 --- a/src/components/Translatable/Translatable.js +++ b/src/components/Translatable/Translatable.js @@ -6,8 +6,39 @@ */ import {translate} from './translate'; +import type {Node} from 'react'; +import {Children, isValidElement} from 'react'; -const Translatable = ({children}: {children: string}) => { +const translateArray = childArray => { + let idx = 0; + const cleaned = childArray.map(child => { + if (isValidElement(child)) { + return `<${idx}>${child.props.children}`; + } + return child; + }); + + const cleanedStr = cleaned.join(''); + const translatedText = translate(cleanedStr).split( + /(<[0-9]+>.*?<\/[0-9]>)/gm, + ); + + const validElements = childArray.filter(isValidElement); + return translatedText.map(tt => { + const matches = tt.match(/<([0-9]+)>(.*?)<\/[0-9]>/m); + if (matches === null) { + return tt; + } + + const el = validElements[matches[1]]; + return {...el, props: {...el.props, children: matches[2]}}; + }); +}; + +const Translatable = ({children}: {children: Node}) => { + if (Array.isArray(children)) { + return translateArray(Children.toArray(children)); + } return translate(children); }; diff --git a/src/pages/acknowledgements.html.js b/src/pages/acknowledgements.html.js index 7a67b4c2452..c1d9a211685 100644 --- a/src/pages/acknowledgements.html.js +++ b/src/pages/acknowledgements.html.js @@ -13,6 +13,7 @@ import {urlRoot} from 'site-constants'; import {sharedStyles} from 'theme'; import names from '../../content/acknowledgements.yml'; +import Translatable, {translate} from '../components/Translatable'; const Acknowlegements = ({data, location}) => ( @@ -22,11 +23,15 @@ const Acknowlegements = ({data, location}) => (
Acknowledgements
-

We'd like to thank all of our contributors:

+

+ + We'd like to thank all of our contributors: + +

    ( ))}
-

In addition, we're grateful to

+

+ In addition, we're grateful to +

From fe75ee88884ccdb1e02d8dbc9b765524c1792a2a Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Thu, 5 Sep 2019 11:24:18 +0400 Subject: [PATCH 07/13] Translate versions and all blog posts strings --- content/strings.yml | 11 ++++++++- src/pages/blog/all.html.js | 7 ++++-- src/pages/versions.js | 46 +++++++++++++++++++++++--------------- 3 files changed, 43 insertions(+), 21 deletions(-) diff --git a/content/strings.yml b/content/strings.yml index e4f20e7e787..7ed503d46ee 100644 --- a/content/strings.yml +++ b/content/strings.yml @@ -29,4 +29,13 @@ "<0>Christopher Aue for letting us use the <1>reactjs.com domain name and the <2>@reactjs username on Twitter.": "" "<0>ProjectMoon for letting us use the <1>flux package name on npm.": "" "Shane Anderson for allowing us to use the <1>react org on GitHub.": "" -"<0>Dmitri Voronianski for letting us use the <1>Oceanic Next color scheme on this website.": "" \ No newline at end of file +"<0>Dmitri Voronianski for letting us use the <1>Oceanic Next color scheme on this website.": "" +"React - All Posts": "" +"All Posts": "" +"React - Versions": "" +"React Versions": "" +"A complete release history for React is available <0>on GitHub.": "" +"Documentation for recent releases can also be found below.": "" +"See our FAQ for information about <0>our versioning policy and commitment to stability.": "" +"Changelog": "" +"Documentation": "" \ No newline at end of file diff --git a/src/pages/blog/all.html.js b/src/pages/blog/all.html.js index 35734b5b1d3..ee2d59c2fc3 100644 --- a/src/pages/blog/all.html.js +++ b/src/pages/blog/all.html.js @@ -17,6 +17,7 @@ import toCommaSeparatedList from 'utils/toCommaSeparatedList'; import MetaTitle from 'templates/components/MetaTitle'; import type {allMarkdownRemarkData} from 'types'; +import Translatable, {translate} from '../../components/Translatable'; type Props = { data: allMarkdownRemarkData, @@ -28,10 +29,12 @@ const AllBlogPosts = ({data, location}: Props) => (
-
All Posts
+
+ All Posts +