Skip to content

Commit 31381a8

Browse files
author
Brian Vaughn
committed
Iterating on Crowdin scripts, Link, pages, etc
1 parent 70b9bd5 commit 31381a8

File tree

12 files changed

+85
-17
lines changed

12 files changed

+85
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.idea
44
node_modules
55
public
6+
yarn-error.log

crowdin/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__translations/
1+
__exports/
22
translations/

crowdin/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
## How does this work?
2+
3+
### Downloading content from Crowdin
4+
5+
This subdirectory contains some JavaScript files as well as a symlink for the default language (English) that points to [the `content` directory](https://github.com/reactjs/reactjs.org/tree/master/content):
6+
```sh
7+
.
8+
└── crowdin
9+
   ├── config.js # Crowdin configuration settings
10+
   ├── download.js # Node Download script
11+
   └── translations
12+
   └── en-US -> ../../content
13+
```
14+
15+
Translations can be downloaded locally with `yarn crowdin:download`. This uses the Crowdin API to download data into an `__exports` subdirectory:
16+
```sh
17+
.
18+
└── crowdin
19+
   ├── config.js # Crowdin configuration settings
20+
   ├── download.js # Node Download script
21+
   ├── translations
22+
   │ └── en-US -> ../../content
23+
   └── __exports
24+
      └── ... # Downloaded translations go here
25+
```
26+
27+
Next the task identifies which languages have been translated past a certain threshold (specified by `crowdin/config.js`). For these languages, the script creates symlinks in the `translations` subdirectory:
28+
```sh
29+
.
30+
└── crowdin
31+
   ├── config.js # Crowdin configuration settings
32+
   ├── download.js # Node Download script
33+
   ├── translations
34+
   │ ├── en-US -> ../../content
35+
   │ ├── es-ES -> ../__exports/.../es-ES
36+
   │ ├── zh-CN -> ../__exports/.../zh-CN
37+
   │ └── ... # Other symlinks go here
38+
   └── __exports
39+
      └── ... # Downloaded translations go here
40+
```
41+
42+
### Gatsby integration
43+
44+
A new (local) `gatsby-plugin-crowdin` plugin has been created that knows how to create localized links to certain sections of the website. **For now, only content from [the `content/docs` directory](https://github.com/reactjs/reactjs.org/tree/master/content/docs) is localized. All other sections/pages remain English only.**
45+
46+
The `gatsby-source-filesystem` plugin has also been reconfigured to read all content from the `crowdin/translations/*` (symlinked) directories rather than `content`. This way it consumes translated content when available. (Crowdin provides default language content for sections that have not yet been translated for any given locale.)
47+
48+
Because of the default symlink (`crowdin/translations/en-US` -> `content`) Gatsby will serve English content when run locally, even if the Crowdin script has not been run. This should enable fast iteration and creation of new content.

crowdin/config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
const path = require('path');
2+
3+
// Also relates to the crowdin.yaml file in the root directory
14
module.exports = {
25
key: process.env.CROWDIN_API_KEY,
36
url: 'https://api.crowdin.com/api/project/react',
47
threshold: 50,
5-
downloadedRootDirectory: 'test-17',
8+
downloadedRootDirectory: path.join('test-17', 'docs'),
69
};

crowdin/download.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ const path = require('path');
44
const {symlink, lstatSync, readdirSync} = require('fs');
55

66
const SYMLINKED_TRANSLATIONS_PATH = path.resolve(__dirname, 'translations');
7-
const DOWNLOADED_TRANSLATIONS_PATH = path.resolve(__dirname, '__translations');
7+
const DOWNLOADED_TRANSLATIONS_PATH = path.resolve(__dirname, '__exports');
88

99
// Path to the "docs" folder within the downloaded Crowdin translations bundle.
1010
const downloadedDocsPath = path.resolve(
11-
__dirname,
12-
'__translations',
11+
DOWNLOADED_TRANSLATIONS_PATH,
1312
config.downloadedRootDirectory,
14-
'docs',
1513
);
1614

1715
// Sanity check (local) Crowdin config file for expected values.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"check-all": "npm-run-all prettier --parallel lint flow",
8181
"ci-check": "npm-run-all prettier:diff --parallel lint flow",
8282
"crowdin:download": "node ./crowdin/download",
83-
"dev": "gatsby develop -H 0.0.0.0",
83+
"dev": "yarn start",
8484
"flow": "flow",
8585
"format:source": "prettier --config .prettierrc --write \"{gatsby-*.js,{flow-typed,plugins,src}/**/*.js}\"",
8686
"format:examples": "prettier --config .prettierrc.examples --write \"examples/**/*.js\"",
@@ -92,7 +92,8 @@
9292
"prettier:diff": "yarn nit:source && yarn nit:examples",
9393
"reset": "yarn reset:cache && yarn reset:translations",
9494
"reset:cache": "rimraf ./.cache",
95-
"reset:translations": "rimraf ./crowdin/__translations && find crowdin/translations -type l -not -name '*en-US' -delete"
95+
"reset:translations": "rimraf ./crowdin/__translations && find crowdin/translations -type l -not -name '*en-US' -delete",
96+
"start": "gatsby develop -H 0.0.0.0"
9697
},
9798
"devDependencies": {
9899
"eslint-config-prettier": "^2.6.0",

plugins/gatsby-plugin-crowdin/Link.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ import React from 'react';
1212
import {getLanguageCodeFromPath} from './utils';
1313

1414
// TODO THis is a hack :( Pass this down via context or some other way?
15-
const DEFAULT_LANGUAGE = 'en';
15+
const DEFAULT_LANGUAGE = 'en-US';
1616

17-
const DecoratedLink = ({location, to, ...rest}, ...other) => {
18-
if (to.startsWith('/')) {
17+
const DecoratedLink = ({isLocalized, location, to, ...rest}, ...other) => {
18+
if (isLocalized !== false && to.startsWith('/')) {
1919
const languageCode =
2020
getLanguageCodeFromPath(location.pathname.substr(1)) || DEFAULT_LANGUAGE;
2121

@@ -29,6 +29,7 @@ const DecoratedLink = ({location, to, ...rest}, ...other) => {
2929
};
3030

3131
DecoratedLink.propTypes = {
32+
isLocalized: PropTypes.bool,
3233
location: PropTypes.object.isRequired,
3334
to: PropTypes.string.isRequired,
3435
};

src/pages/blog/all.html.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @flow
66
*/
77

8-
import Link from 'gatsby-link';
8+
import Link from 'gatsby-plugin-crowdin/Link';
99
import Container from 'components/Container';
1010
import Header from 'components/Header';
1111
import TitleAndMetaTags from 'components/TitleAndMetaTags';
@@ -19,9 +19,10 @@ import type {allMarkdownRemarkData} from 'types';
1919

2020
type Props = {
2121
data: allMarkdownRemarkData,
22+
location: Location,
2223
};
2324

24-
const AllBlogPosts = ({data}: Props) => (
25+
const AllBlogPosts = ({data, location}: Props) => (
2526
<Container>
2627
<div css={sharedStyles.articleLayout.container}>
2728
<div css={sharedStyles.articleLayout.content}>
@@ -53,7 +54,7 @@ const AllBlogPosts = ({data}: Props) => (
5354
width: '33.33%',
5455
},
5556
}}
56-
key={node.fields.slug}>
57+
key={node.fields.id}>
5758
<h2
5859
css={{
5960
fontSize: 24,
@@ -68,7 +69,8 @@ const AllBlogPosts = ({data}: Props) => (
6869
borderBottomColor: colors.black,
6970
},
7071
}}
71-
key={node.fields.slug}
72+
key={node.fields.id}
73+
location={location}
7274
to={node.fields.slug}>
7375
{node.frontmatter.title}
7476
</Link>
@@ -116,6 +118,7 @@ export const pageQuery = graphql`
116118
}
117119
fields {
118120
date(formatString: "MMMM DD, YYYY")
121+
id
119122
slug
120123
}
121124
}

src/templates/blog.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ const toSectionList = allMarkdownRemark => [
1414
title: 'Recent Posts',
1515
items: allMarkdownRemark.edges
1616
.map(({node}) => ({
17-
id: node.fields.id,
17+
id: node.fields.slug,
1818
title: node.frontmatter.title,
1919
}))
2020
.concat({
21+
isLocalized: false,
2122
id: '/blog/all.html',
2223
title: 'All posts ...',
2324
}),
@@ -76,6 +77,7 @@ export const pageQuery = graphql`
7677
}
7778
fields {
7879
id
80+
slug
7981
}
8082
}
8183
}

src/templates/components/NavigationFooter/NavigationFooter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
1111
import React from 'react';
1212
import {colors, fonts, media} from 'theme';
1313

14-
const NavigationFooter = ({next, prev, location}) => {
14+
const NavigationFooter = ({location, next, prev}) => {
1515
return (
1616
<div
1717
css={{

src/templates/components/Sidebar/Section.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class Section extends React.Component {
7979
isActive: isScrollSync
8080
? activeItemId === item.id
8181
: isItemActive(location, item),
82+
isLocalized: item.isLocalized,
8283
item,
8384
location,
8485
onLinkClick,
@@ -93,6 +94,7 @@ class Section extends React.Component {
9394
isActive: isScrollSync
9495
? activeItemId === subitem.id
9596
: isItemActive(location, subitem),
97+
isLocalized: subitem.isLocalized,
9698
item: subitem,
9799
location,
98100
onLinkClick,

src/utils/createLink.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,23 @@ import type {Node} from 'react';
1515

1616
type CreateLinkBaseProps = {
1717
isActive: boolean,
18+
isLocalized: ?boolean,
1819
item: Object,
1920
location: string,
2021
section: Object,
2122
};
2223

2324
const createLinkBlog = ({
2425
isActive,
26+
isLocalized,
2527
item,
2628
location,
2729
section,
2830
}: CreateLinkBaseProps): Node => {
2931
return (
3032
<Link
3133
css={[linkCss, isActive && activeLinkCss]}
34+
isLocalized={isLocalized}
3235
location={location}
3336
to={item.id}>
3437
{isActive && <span css={activeLinkBefore} />}
@@ -39,6 +42,7 @@ const createLinkBlog = ({
3942

4043
const createLinkCommunity = ({
4144
isActive,
45+
isLocalized,
4246
item,
4347
location,
4448
section,
@@ -60,6 +64,7 @@ const createLinkCommunity = ({
6064
}
6165
return createLinkDocs({
6266
isActive,
67+
isLocalized,
6368
item,
6469
location,
6570
section,
@@ -68,13 +73,15 @@ const createLinkCommunity = ({
6873

6974
const createLinkDocs = ({
7075
isActive,
76+
isLocalized,
7177
item,
7278
location,
7379
section,
7480
}: CreateLinkBaseProps): Node => {
7581
return (
7682
<Link
7783
css={[linkCss, isActive && activeLinkCss]}
84+
isLocalized={isLocalized}
7885
location={location}
7986
to={slugify(item.id, section.directory)}>
8087
{isActive && <span css={activeLinkBefore} />}
@@ -89,6 +96,7 @@ type CreateLinkTutorialProps = {
8996

9097
const createLinkTutorial = ({
9198
isActive,
99+
isLocalized,
92100
item,
93101
location,
94102
onLinkClick,
@@ -97,6 +105,7 @@ const createLinkTutorial = ({
97105
return (
98106
<Link
99107
css={[linkCss, isActive && activeLinkCss]}
108+
isLocalized={isLocalized}
100109
location={location}
101110
onClick={onLinkClick}
102111
to={item.href}>

0 commit comments

Comments
 (0)