mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-08 22:03:01 +02:00
feat(v2): Extract/translate hardcoded labels from classic theme (#4168)
* Translate theme hardcoded strings * improve test
This commit is contained in:
parent
823d0fe3c2
commit
ab7951571e
17 changed files with 217 additions and 60 deletions
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
import type {Metadata} from '@theme/BlogListPage';
|
import type {Metadata} from '@theme/BlogListPage';
|
||||||
|
|
||||||
function BlogListPaginator(props: {readonly metadata: Metadata}): JSX.Element {
|
function BlogListPaginator(props: {readonly metadata: Metadata}): JSX.Element {
|
||||||
|
@ -18,14 +19,28 @@ function BlogListPaginator(props: {readonly metadata: Metadata}): JSX.Element {
|
||||||
<div className="pagination-nav__item">
|
<div className="pagination-nav__item">
|
||||||
{previousPage && (
|
{previousPage && (
|
||||||
<Link className="pagination-nav__link" to={previousPage}>
|
<Link className="pagination-nav__link" to={previousPage}>
|
||||||
<div className="pagination-nav__label">« Newer Entries</div>
|
<div className="pagination-nav__label">
|
||||||
|
«{' '}
|
||||||
|
<Translate
|
||||||
|
id="theme.BlogListPaginator.newerEntries"
|
||||||
|
description="The label used to navigate to the newer blog posts page (previous page)">
|
||||||
|
Newer Entries
|
||||||
|
</Translate>
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="pagination-nav__item pagination-nav__item--next">
|
<div className="pagination-nav__item pagination-nav__item--next">
|
||||||
{nextPage && (
|
{nextPage && (
|
||||||
<Link className="pagination-nav__link" to={nextPage}>
|
<Link className="pagination-nav__link" to={nextPage}>
|
||||||
<div className="pagination-nav__label">Older Entries »</div>
|
<div className="pagination-nav__label">
|
||||||
|
<Translate
|
||||||
|
id="theme.BlogListPaginator.olderEntries"
|
||||||
|
description="The label used to navigate to the older blog posts page (next page)">
|
||||||
|
Older Entries
|
||||||
|
</Translate>{' '}
|
||||||
|
»
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import {MDXProvider} from '@mdx-js/react';
|
import {MDXProvider} from '@mdx-js/react';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
import Head from '@docusaurus/Head';
|
import Head from '@docusaurus/Head';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import MDXComponents from '@theme/MDXComponents';
|
import MDXComponents from '@theme/MDXComponents';
|
||||||
|
@ -133,7 +133,13 @@ function BlogPostItem(props: Props): JSX.Element {
|
||||||
<Link
|
<Link
|
||||||
to={metadata.permalink}
|
to={metadata.permalink}
|
||||||
aria-label={`Read more about ${title}`}>
|
aria-label={`Read more about ${title}`}>
|
||||||
<strong>Read More</strong>
|
<strong>
|
||||||
|
<Translate
|
||||||
|
id="theme.BlogPostItem.readMore"
|
||||||
|
description="The label used in blog post item excerps to link to full blog posts">
|
||||||
|
Read More
|
||||||
|
</Translate>
|
||||||
|
</strong>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -6,14 +6,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
import BlogPostItem from '@theme/BlogPostItem';
|
import BlogPostItem from '@theme/BlogPostItem';
|
||||||
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
import BlogPostPaginator from '@theme/BlogPostPaginator';
|
||||||
import type {Props} from '@theme/BlogPostPage';
|
import type {Props} from '@theme/BlogPostPage';
|
||||||
import BlogSidebar from '@theme/BlogSidebar';
|
import BlogSidebar from '@theme/BlogSidebar';
|
||||||
import TOC from '@theme/TOC';
|
import TOC from '@theme/TOC';
|
||||||
import IconEdit from '@theme/IconEdit';
|
import EditThisPage from '@theme/EditThisPage';
|
||||||
|
|
||||||
function BlogPostPage(props: Props): JSX.Element {
|
function BlogPostPage(props: Props): JSX.Element {
|
||||||
const {content: BlogPostContents, sidebar} = props;
|
const {content: BlogPostContents, sidebar} = props;
|
||||||
|
@ -39,14 +38,7 @@ function BlogPostPage(props: Props): JSX.Element {
|
||||||
isBlogPostPage>
|
isBlogPostPage>
|
||||||
<BlogPostContents />
|
<BlogPostContents />
|
||||||
</BlogPostItem>
|
</BlogPostItem>
|
||||||
<div>
|
<div>{editUrl && <EditThisPage editUrl={editUrl} />}</div>
|
||||||
{editUrl && (
|
|
||||||
<a href={editUrl} target="_blank" rel="noreferrer noopener">
|
|
||||||
<IconEdit />
|
|
||||||
Edit this page
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{(nextItem || prevItem) && (
|
{(nextItem || prevItem) && (
|
||||||
<div className="margin-vert--xl">
|
<div className="margin-vert--xl">
|
||||||
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import type {Props} from '@theme/BlogPostPaginator';
|
import type {Props} from '@theme/BlogPostPaginator';
|
||||||
|
|
||||||
|
@ -17,7 +18,13 @@ function BlogPostPaginator(props: Props): JSX.Element {
|
||||||
<div className="pagination-nav__item">
|
<div className="pagination-nav__item">
|
||||||
{prevItem && (
|
{prevItem && (
|
||||||
<Link className="pagination-nav__link" to={prevItem.permalink}>
|
<Link className="pagination-nav__link" to={prevItem.permalink}>
|
||||||
<div className="pagination-nav__sublabel">Newer Post</div>
|
<div className="pagination-nav__sublabel">
|
||||||
|
<Translate
|
||||||
|
id="theme.BlogPostPaginator.newerPost"
|
||||||
|
description="The blog post button label to navigate to the newer/previous post">
|
||||||
|
Newer Post
|
||||||
|
</Translate>
|
||||||
|
</div>
|
||||||
<div className="pagination-nav__label">
|
<div className="pagination-nav__label">
|
||||||
« {prevItem.title}
|
« {prevItem.title}
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +34,13 @@ function BlogPostPaginator(props: Props): JSX.Element {
|
||||||
<div className="pagination-nav__item pagination-nav__item--next">
|
<div className="pagination-nav__item pagination-nav__item--next">
|
||||||
{nextItem && (
|
{nextItem && (
|
||||||
<Link className="pagination-nav__link" to={nextItem.permalink}>
|
<Link className="pagination-nav__link" to={nextItem.permalink}>
|
||||||
<div className="pagination-nav__sublabel">Older Post</div>
|
<div className="pagination-nav__sublabel">
|
||||||
|
<Translate
|
||||||
|
id="theme.BlogPostPaginator.olderPost"
|
||||||
|
description="The blog post button label to navigate to the older/next post">
|
||||||
|
Older Post
|
||||||
|
</Translate>
|
||||||
|
</div>
|
||||||
<div className="pagination-nav__label">
|
<div className="pagination-nav__label">
|
||||||
{nextItem.title} »
|
{nextItem.title} »
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -49,6 +49,7 @@ function BlogTagsListPage(props: Props): JSX.Element {
|
||||||
))
|
))
|
||||||
.filter((item) => item != null);
|
.filter((item) => item != null);
|
||||||
|
|
||||||
|
// TODO soon: translate hardcoded labels, but factorize them (blog + docs will both have tags)
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
title="Tags"
|
title="Tags"
|
||||||
|
|
|
@ -21,6 +21,7 @@ function BlogTagsPostPage(props: Props): JSX.Element {
|
||||||
const {metadata, items, sidebar} = props;
|
const {metadata, items, sidebar} = props;
|
||||||
const {allTagsPath, name: tagName, count} = metadata;
|
const {allTagsPath, name: tagName, count} = metadata;
|
||||||
|
|
||||||
|
// TODO soon: translate hardcoded labels, but factorize them (blog + docs will both have tags)
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
title={`Posts tagged "${tagName}"`}
|
title={`Posts tagged "${tagName}"`}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import copy from 'copy-text-to-clipboard';
|
||||||
import rangeParser from 'parse-numeric-range';
|
import rangeParser from 'parse-numeric-range';
|
||||||
import usePrismTheme from '@theme/hooks/usePrismTheme';
|
import usePrismTheme from '@theme/hooks/usePrismTheme';
|
||||||
import type {Props} from '@theme/CodeBlock';
|
import type {Props} from '@theme/CodeBlock';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
import {useThemeConfig} from '@docusaurus/theme-common';
|
import {useThemeConfig} from '@docusaurus/theme-common';
|
||||||
|
@ -86,11 +87,11 @@ const highlightDirectiveRegex = (lang) => {
|
||||||
};
|
};
|
||||||
const codeBlockTitleRegex = /(?:title=")(.*)(?:")/;
|
const codeBlockTitleRegex = /(?:title=")(.*)(?:")/;
|
||||||
|
|
||||||
export default ({
|
export default function CodeBlock({
|
||||||
children,
|
children,
|
||||||
className: languageClassName,
|
className: languageClassName,
|
||||||
metastring,
|
metastring,
|
||||||
}: Props): JSX.Element => {
|
}: Props): JSX.Element {
|
||||||
const {prism} = useThemeConfig();
|
const {prism} = useThemeConfig();
|
||||||
|
|
||||||
const [showCopied, setShowCopied] = useState(false);
|
const [showCopied, setShowCopied] = useState(false);
|
||||||
|
@ -242,11 +243,23 @@ export default ({
|
||||||
aria-label="Copy code to clipboard"
|
aria-label="Copy code to clipboard"
|
||||||
className={clsx(styles.copyButton)}
|
className={clsx(styles.copyButton)}
|
||||||
onClick={handleCopyCode}>
|
onClick={handleCopyCode}>
|
||||||
{showCopied ? 'Copied' : 'Copy'}
|
{showCopied ? (
|
||||||
|
<Translate
|
||||||
|
id="theme.CodeBlock.copied"
|
||||||
|
description="The copied button label on code blocks">
|
||||||
|
Copied
|
||||||
|
</Translate>
|
||||||
|
) : (
|
||||||
|
<Translate
|
||||||
|
id="theme.CodeBlock.copy"
|
||||||
|
description="The copy button label on code blocks">
|
||||||
|
Copy
|
||||||
|
</Translate>
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Highlight>
|
</Highlight>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Head from '@docusaurus/Head';
|
import Head from '@docusaurus/Head';
|
||||||
import {useTitleFormatter} from '@docusaurus/theme-common';
|
import {useTitleFormatter} from '@docusaurus/theme-common';
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
@ -15,7 +14,7 @@ import DocPaginator from '@theme/DocPaginator';
|
||||||
import DocVersionSuggestions from '@theme/DocVersionSuggestions';
|
import DocVersionSuggestions from '@theme/DocVersionSuggestions';
|
||||||
import type {Props} from '@theme/DocItem';
|
import type {Props} from '@theme/DocItem';
|
||||||
import TOC from '@theme/TOC';
|
import TOC from '@theme/TOC';
|
||||||
import IconEdit from '@theme/IconEdit';
|
import EditThisPage from '@theme/EditThisPage';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
|
@ -107,15 +106,7 @@ function DocItem(props: Props): JSX.Element {
|
||||||
<div className="margin-vert--xl">
|
<div className="margin-vert--xl">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
{editUrl && (
|
{editUrl && <EditThisPage editUrl={editUrl} />}
|
||||||
<a
|
|
||||||
href={editUrl}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener">
|
|
||||||
<IconEdit />
|
|
||||||
Edit this page
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{(lastUpdatedAt || lastUpdatedBy) && (
|
{(lastUpdatedAt || lastUpdatedBy) && (
|
||||||
<div className="col text--right">
|
<div className="col text--right">
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
import type {Props} from '@theme/DocPaginator';
|
import type {Props} from '@theme/DocPaginator';
|
||||||
|
|
||||||
function DocPaginator(props: Props): JSX.Element {
|
function DocPaginator(props: Props): JSX.Element {
|
||||||
|
@ -19,7 +20,13 @@ function DocPaginator(props: Props): JSX.Element {
|
||||||
<Link
|
<Link
|
||||||
className="pagination-nav__link"
|
className="pagination-nav__link"
|
||||||
to={metadata.previous.permalink}>
|
to={metadata.previous.permalink}>
|
||||||
<div className="pagination-nav__sublabel">Previous</div>
|
<div className="pagination-nav__sublabel">
|
||||||
|
<Translate
|
||||||
|
id="theme.DocPaginator.previous"
|
||||||
|
description="The label used to navigate to the previous doc">
|
||||||
|
Previous
|
||||||
|
</Translate>
|
||||||
|
</div>
|
||||||
<div className="pagination-nav__label">
|
<div className="pagination-nav__label">
|
||||||
« {metadata.previous.title}
|
« {metadata.previous.title}
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,7 +36,13 @@ function DocPaginator(props: Props): JSX.Element {
|
||||||
<div className="pagination-nav__item pagination-nav__item--next">
|
<div className="pagination-nav__item pagination-nav__item--next">
|
||||||
{metadata.next && (
|
{metadata.next && (
|
||||||
<Link className="pagination-nav__link" to={metadata.next.permalink}>
|
<Link className="pagination-nav__link" to={metadata.next.permalink}>
|
||||||
<div className="pagination-nav__sublabel">Next</div>
|
<div className="pagination-nav__sublabel">
|
||||||
|
<Translate
|
||||||
|
id="theme.DocPaginator.next"
|
||||||
|
description="The label used to navigate to the next doc">
|
||||||
|
Next
|
||||||
|
</Translate>
|
||||||
|
</div>
|
||||||
<div className="pagination-nav__label">
|
<div className="pagination-nav__label">
|
||||||
{metadata.next.title} »
|
{metadata.next.title} »
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
|
||||||
|
import type {Props} from '@theme/EditThisPage';
|
||||||
|
import IconEdit from '@theme/IconEdit';
|
||||||
|
|
||||||
|
export default function EditThisPage({editUrl}: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<a href={editUrl} target="_blank" rel="noreferrer noopener">
|
||||||
|
<IconEdit />
|
||||||
|
<Translate
|
||||||
|
id="theme.EditThisPage.editThisPage"
|
||||||
|
description="The link label to edit the current page">
|
||||||
|
Edit this page
|
||||||
|
</Translate>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
|
||||||
function NotFound(): JSX.Element {
|
function NotFound(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -14,11 +15,27 @@ function NotFound(): JSX.Element {
|
||||||
<main className="container margin-vert--xl">
|
<main className="container margin-vert--xl">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col col--6 col--offset-3">
|
<div className="col col--6 col--offset-3">
|
||||||
<h1 className="hero__title">Page Not Found</h1>
|
<h1 className="hero__title">
|
||||||
<p>We could not find what you were looking for.</p>
|
<Translate
|
||||||
|
id="theme.NotFound.title"
|
||||||
|
description="The title of the 404 page">
|
||||||
|
Page Not Found
|
||||||
|
</Translate>
|
||||||
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
|
<Translate
|
||||||
|
id="theme.NotFound.p1"
|
||||||
|
description="The first paragraph of the 404 page">
|
||||||
|
We could not find what you were looking for.
|
||||||
|
</Translate>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<Translate
|
||||||
|
id="theme.NotFound.p2"
|
||||||
|
description="The 2nd paragraph of the 404 page">
|
||||||
Please contact the owner of the site that linked you to the
|
Please contact the owner of the site that linked you to the
|
||||||
original URL and let them know their link is broken.
|
original URL and let them know their link is broken.
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {useRef, useEffect} from 'react';
|
import React, {useRef, useEffect} from 'react';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
import {useLocation} from '@docusaurus/router';
|
import {useLocation} from '@docusaurus/router';
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
|
|
||||||
function programmaticFocus(el) {
|
function programmaticFocus(el) {
|
||||||
|
@ -39,7 +39,11 @@ function SkipToContent(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef}>
|
<div ref={containerRef}>
|
||||||
<a href="#main" className={styles.skipToContent} onClick={handleSkip}>
|
<a href="#main" className={styles.skipToContent} onClick={handleSkip}>
|
||||||
|
<Translate
|
||||||
|
id="theme.SkipToContent.skipToMainContent"
|
||||||
|
description="The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation">
|
||||||
Skip to main content
|
Skip to main content
|
||||||
|
</Translate>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -92,6 +92,14 @@ declare module '@theme/DocVersionSuggestions' {
|
||||||
export default DocVersionSuggestions;
|
export default DocVersionSuggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@theme/EditThisPage' {
|
||||||
|
export type Props = {
|
||||||
|
readonly editUrl: string;
|
||||||
|
};
|
||||||
|
const EditThisPage: (props: Props) => JSX.Element;
|
||||||
|
export default EditThisPage;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '@theme/Footer' {
|
declare module '@theme/Footer' {
|
||||||
const Footer: () => JSX.Element | null;
|
const Footer: () => JSX.Element | null;
|
||||||
export default Footer;
|
export default Footer;
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live';
|
import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import Translate from '@docusaurus/Translate';
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
|
|
||||||
function Playground({children, theme, transformCode, ...props}) {
|
export default function Playground({children, theme, transformCode, ...props}) {
|
||||||
return (
|
return (
|
||||||
<LiveProvider
|
<LiveProvider
|
||||||
code={children.replace(/\n$/, '')}
|
code={children.replace(/\n$/, '')}
|
||||||
|
@ -23,7 +24,11 @@ function Playground({children, theme, transformCode, ...props}) {
|
||||||
styles.playgroundHeader,
|
styles.playgroundHeader,
|
||||||
styles.playgroundEditorHeader,
|
styles.playgroundEditorHeader,
|
||||||
)}>
|
)}>
|
||||||
|
<Translate
|
||||||
|
id="theme.Playground.liveEditor"
|
||||||
|
description="The live editor label of the live codeblocks">
|
||||||
Live Editor
|
Live Editor
|
||||||
|
</Translate>
|
||||||
</div>
|
</div>
|
||||||
<LiveEditor className={styles.playgroundEditor} />
|
<LiveEditor className={styles.playgroundEditor} />
|
||||||
<div
|
<div
|
||||||
|
@ -31,7 +36,11 @@ function Playground({children, theme, transformCode, ...props}) {
|
||||||
styles.playgroundHeader,
|
styles.playgroundHeader,
|
||||||
styles.playgroundPreviewHeader,
|
styles.playgroundPreviewHeader,
|
||||||
)}>
|
)}>
|
||||||
|
<Translate
|
||||||
|
id="theme.Playground.result"
|
||||||
|
description="The result label of the live codeblocks">
|
||||||
Result
|
Result
|
||||||
|
</Translate>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.playgroundPreview}>
|
<div className={styles.playgroundPreview}>
|
||||||
<LivePreview />
|
<LivePreview />
|
||||||
|
@ -40,5 +49,3 @@ function Playground({children, theme, transformCode, ...props}) {
|
||||||
</LiveProvider>
|
</LiveProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Playground;
|
|
||||||
|
|
|
@ -238,21 +238,54 @@ describe('extractPluginsSourceCodeTranslations', () => {
|
||||||
return {
|
return {
|
||||||
name: 'abc',
|
name: 'abc',
|
||||||
getPathsToWatch() {
|
getPathsToWatch() {
|
||||||
return [path.join(pluginDir, '**/*.{js,jsx,ts,tsx}')];
|
return [path.join(pluginDir, 'subpath', '**/*.{js,jsx,ts,tsx}')];
|
||||||
|
},
|
||||||
|
getThemePath() {
|
||||||
|
return path.join(pluginDir, 'src', 'theme');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugin1Dir = await createTmpDir();
|
const plugin1Dir = await createTmpDir();
|
||||||
const plugin1File = path.join(plugin1Dir, 'file.jsx');
|
const plugin1File1 = path.join(plugin1Dir, 'subpath', 'file1.jsx');
|
||||||
await fs.ensureDir(path.dirname(plugin1File));
|
await fs.ensureDir(path.dirname(plugin1File1));
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
plugin1File,
|
plugin1File1,
|
||||||
`
|
`
|
||||||
export default function MyComponent() {
|
export default function MyComponent() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input text={translate({id: 'plugin1Id',message: 'plugin1 message',description: 'plugin1 description'})}/>
|
<input text={translate({id: 'plugin1Id1',message: 'plugin1 message 1',description: 'plugin1 description 1'})}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
const plugin1File2 = path.join(plugin1Dir, 'src', 'theme', 'file2.jsx');
|
||||||
|
await fs.ensureDir(path.dirname(plugin1File2));
|
||||||
|
await fs.writeFile(
|
||||||
|
plugin1File2,
|
||||||
|
`
|
||||||
|
export default function MyComponent() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<input text={translate({id: 'plugin1Id2',message: 'plugin1 message 2',description: 'plugin1 description 2'})}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// This one should not be found! On purpose!
|
||||||
|
const plugin1File3 = path.join(plugin1Dir, 'unscannedFolder', 'file3.jsx');
|
||||||
|
await fs.ensureDir(path.dirname(plugin1File3));
|
||||||
|
await fs.writeFile(
|
||||||
|
plugin1File3,
|
||||||
|
`
|
||||||
|
export default function MyComponent() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<input text={translate({id: 'plugin1Id3',message: 'plugin1 message 3',description: 'plugin1 description 3'})}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +294,7 @@ export default function MyComponent() {
|
||||||
const plugin1 = createTestPlugin(plugin1Dir);
|
const plugin1 = createTestPlugin(plugin1Dir);
|
||||||
|
|
||||||
const plugin2Dir = await createTmpDir();
|
const plugin2Dir = await createTmpDir();
|
||||||
const plugin2File = path.join(plugin1Dir, 'sub', 'path', 'file.tsx');
|
const plugin2File = path.join(plugin1Dir, 'subpath', 'file.tsx');
|
||||||
await fs.ensureDir(path.dirname(plugin2File));
|
await fs.ensureDir(path.dirname(plugin2File));
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
plugin2File,
|
plugin2File,
|
||||||
|
@ -271,7 +304,7 @@ type Props = {hey: string};
|
||||||
export default function MyComponent(props: Props) {
|
export default function MyComponent(props: Props) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input text={translate({id: 'plugin2Id',message: 'plugin2 message',description: 'plugin2 description'})}/>
|
<input text={translate({id: 'plugin2Id1',message: 'plugin2 message 1',description: 'plugin2 description 1'})}/>
|
||||||
<Translate
|
<Translate
|
||||||
id="plugin2Id2"
|
id="plugin2Id2"
|
||||||
description="plugin2 description 2"
|
description="plugin2 description 2"
|
||||||
|
@ -291,13 +324,17 @@ export default function MyComponent(props: Props) {
|
||||||
TestBabelOptions,
|
TestBabelOptions,
|
||||||
);
|
);
|
||||||
expect(translations).toEqual({
|
expect(translations).toEqual({
|
||||||
plugin1Id: {
|
plugin1Id1: {
|
||||||
description: 'plugin1 description',
|
description: 'plugin1 description 1',
|
||||||
message: 'plugin1 message',
|
message: 'plugin1 message 1',
|
||||||
},
|
},
|
||||||
plugin2Id: {
|
plugin1Id2: {
|
||||||
description: 'plugin2 description',
|
description: 'plugin1 description 2',
|
||||||
message: 'plugin2 message',
|
message: 'plugin1 message 2',
|
||||||
|
},
|
||||||
|
plugin2Id1: {
|
||||||
|
description: 'plugin2 description 1',
|
||||||
|
message: 'plugin2 message 1',
|
||||||
},
|
},
|
||||||
plugin2Id2: {
|
plugin2Id2: {
|
||||||
description: 'plugin2 description 2',
|
description: 'plugin2 description 2',
|
||||||
|
|
|
@ -31,15 +31,28 @@ function isTranslatableSourceCodePath(filePath: string): boolean {
|
||||||
return TranslatableSourceCodeExtension.has(nodePath.extname(filePath));
|
return TranslatableSourceCodeExtension.has(nodePath.extname(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPluginSourceCodeFilePaths(plugin: InitPlugin): string[] {
|
||||||
|
// The getPathsToWatch() generally returns the js/jsx/ts/tsx/md/mdx file paths
|
||||||
|
// We can use this method as well to know which folders we should try to extract translations from
|
||||||
|
// Hacky/implicit, but do we want to introduce a new lifecycle method just for that???
|
||||||
|
const codePaths: string[] = plugin.getPathsToWatch?.() ?? [];
|
||||||
|
|
||||||
|
// We also include theme code
|
||||||
|
const themePath = plugin.getThemePath?.();
|
||||||
|
if (themePath) {
|
||||||
|
codePaths.push(themePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codePaths;
|
||||||
|
}
|
||||||
|
|
||||||
async function getSourceCodeFilePaths(
|
async function getSourceCodeFilePaths(
|
||||||
plugins: InitPlugin[],
|
plugins: InitPlugin[],
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
// The getPathsToWatch() generally returns the js/jsx/ts/tsx/md/mdx file paths
|
// The getPathsToWatch() generally returns the js/jsx/ts/tsx/md/mdx file paths
|
||||||
// We can use this method as well to know which folders we should try to extract translations from
|
// We can use this method as well to know which folders we should try to extract translations from
|
||||||
// Hacky/implicit, but do we want to introduce a new lifecycle method for that???
|
// Hacky/implicit, but do we want to introduce a new lifecycle method for that???
|
||||||
const allPathsToWatch = flatten(
|
const allPathsToWatch = flatten(plugins.map(getPluginSourceCodeFilePaths));
|
||||||
plugins.map((plugin) => plugin.getPathsToWatch?.() ?? []),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Required for Windows support, as paths using \ should not be used by globby
|
// Required for Windows support, as paths using \ should not be used by globby
|
||||||
// (also using the windows hard drive prefix like c: is not a good idea)
|
// (also using the windows hard drive prefix like c: is not a good idea)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"deploy": "docusaurus deploy",
|
"deploy": "docusaurus deploy",
|
||||||
"clear": "docusaurus clear",
|
"clear": "docusaurus clear",
|
||||||
"serve": "docusaurus serve",
|
"serve": "docusaurus serve",
|
||||||
|
"write-translations": "docusaurus write-translations",
|
||||||
"start:baseUrl": "cross-env BASE_URL='/build/' yarn start",
|
"start:baseUrl": "cross-env BASE_URL='/build/' yarn start",
|
||||||
"build:baseUrl": "cross-env BASE_URL='/build/' yarn build",
|
"build:baseUrl": "cross-env BASE_URL='/build/' yarn build",
|
||||||
"start:bootstrap": "cross-env DOCUSAURUS_PRESET=bootstrap yarn start",
|
"start:bootstrap": "cross-env DOCUSAURUS_PRESET=bootstrap yarn start",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue