From 2eb4e17739b92a40cb9386d5751c0bd33e18cf0e Mon Sep 17 00:00:00 2001 From: slorber Date: Wed, 24 Feb 2021 14:05:51 +0100 Subject: [PATCH 01/19] WIP: refactor team profile cards --- website/community/team.mdx | 128 +------------ .../src/components/TeamProfileCard/index.js | 50 ----- .../src/components/TeamProfileCards/index.js | 179 ++++++++++++++++++ 3 files changed, 187 insertions(+), 170 deletions(-) delete mode 100644 website/src/components/TeamProfileCard/index.js create mode 100644 website/src/components/TeamProfileCards/index.js diff --git a/website/community/team.mdx b/website/community/team.mdx index 7179f9b140a4..aab7ae51a558 100644 --- a/website/community/team.mdx +++ b/website/community/team.mdx @@ -4,13 +4,11 @@ title: Team slug: /team --- -import TeamProfileCard from '@site/src/components/TeamProfileCard'; - -export function TeamProfileCardCol(props) { - return ( - - ); -} +import { + ActiveTeamRow, + HonoraryAlumniTeamRow, + StudentFellowsTeamRow, +} from '@site/src/components/TeamProfileCards'; ## Active Team @@ -18,129 +16,19 @@ The Docusaurus team works on the core functionality, plugins for the classic the Current members of the Docusaurus team are listed in alphabetical order below. -
- - Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ - Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 - - - Docusaurus founder and now ever grateful Docusaurus cheerleader to those who - actually write code for it. - - - React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. He - writes regularly, on his{' '} - - website - {' '} - and{' '} - - Dev.to - - . - - - Full Front End Stack developer who likes working on the Jamstack. Working on - Docusaurus made him Facebook's unofficial part-time Open Source webmaster, - which is an awesome role to be in. - -
+ ## Honorary Alumni Docusaurus would never be what it is today without the huge contributions from these folks who have moved on to bigger and greater things. -
- - Maintainer @docusaurus · 🔥🔥🔥 - - - 🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes docs - and spams this world with many websites. - -
+ ## Student Fellows A handful of students have also worked on Docusaurus as part of their school term/internship and the [Major League Hacking Fellowship program](https://fellowship.mlh.io/), contributing amazing features such as plugin options validation, migration tooling, and a Bootstrap theme. -
- - Fullstack developer who loves to code and try new technologies. In his free - time, he contributes to open source, writes blog posts on his{' '} - - website - {' '} - and watches Anime. - - - Developer and Creative, trying to gain the skills to build whatever he can - think of. - - - Fanny got started with web development in high school, building a project - for the school kitchen. In her free time she loves contributing to Open - Source, occasionally writing on{' '} - - her blog - {' '} - about her experiences, cooking, and creating{' '} - - Spotify playlists - - . - - - Sam started programming in 2011 and built his{' '} - website in 2015. He is interested in - programming languages, dev infra and web development, and has built his own{' '} - programming language and{' '} - mini React. - - - Open-source enthusiast who aims to become as awesome as the other humans on - this page. Working on Docusaurus brought him closer to his goal. 🌱 - - - Fullstack web developer who loves learning new technologies and applying - them! Loves contributing to open source as well as writing content articles - and tutorials. - -
+ ## Acknowledgements diff --git a/website/src/components/TeamProfileCard/index.js b/website/src/components/TeamProfileCard/index.js deleted file mode 100644 index 172d2a81b1a9..000000000000 --- a/website/src/components/TeamProfileCard/index.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * 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'; - -export default function TeamProfileCard({ - className, - name, - children, - githubUrl, - twitterUrl, -}) { - return ( -
-
-
-
- {`${name}'s -
-

{name}

-
-
-
-
{children}
-
-
- {githubUrl && ( - - GitHub - - )} - {twitterUrl && ( - - Twitter - - )} -
-
-
-
- ); -} diff --git a/website/src/components/TeamProfileCards/index.js b/website/src/components/TeamProfileCards/index.js new file mode 100644 index 000000000000..0666a5359c7c --- /dev/null +++ b/website/src/components/TeamProfileCards/index.js @@ -0,0 +1,179 @@ +/** + * 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'; + +function TeamProfileCard({className, name, children, githubUrl, twitterUrl}) { + return ( +
+
+
+
+ {`${name}'s +
+

{name}

+
+
+
+
{children}
+
+
+ {githubUrl && ( + + GitHub + + )} + {twitterUrl && ( + + Twitter + + )} +
+
+
+
+ ); +} + +function TeamProfileCardCol(props) { + return ( + + ); +} + +export function ActiveTeamRow() { + return ( +
+ + Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ + Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 + + + Docusaurus founder and now ever grateful Docusaurus cheerleader to those + who actually write code for it. + + + React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. + He writes regularly, on his{' '} + + website + {' '} + and{' '} + + Dev.to + + . + + + Full Front End Stack developer who likes working on the Jamstack. + Working on Docusaurus made him Facebook's unofficial part-time Open + Source webmaster, which is an awesome role to be in. + +
+ ); +} + +export function HonoraryAlumniTeamRow() { + return ( +
+ + Maintainer @docusaurus · 🔥🔥🔥 + + + 🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes + docs and spams this world with many websites. + +
+ ); +} + +export function StudentFellowsTeamRow() { + return ( +
+ + Fullstack developer who loves to code and try new technologies. In his + free time, he contributes to open source, writes blog posts on his{' '} + + website + {' '} + and watches Anime. + + + Developer and Creative, trying to gain the skills to build whatever he + can think of. + + + Fanny got started with web development in high school, building a + project for the school kitchen. In her free time she loves contributing + to Open Source, occasionally writing on{' '} + + her blog + {' '} + about her experiences, cooking, and creating{' '} + + Spotify playlists + + . + + + Sam started programming in 2011 and built his{' '} + website in 2015. He is interested + in programming languages, dev infra and web development, and has built + his own{' '} + programming language and{' '} + mini React. + + + Open-source enthusiast who aims to become as awesome as the other humans + on this page. Working on Docusaurus brought him closer to his goal. 🌱 + + + Fullstack web developer who loves learning new technologies and applying + them! Loves contributing to open source as well as writing content + articles and tutorials. + +
+ ); +} From 2b6548efa6739b25829411d843494ac4a40d50a8 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 11:23:28 +0100 Subject: [PATCH 02/19] Add Interpolate / interpolate APIs --- .../src/index.d.ts | 26 ++++- .../src/client/exports/Interpolate.tsx | 96 +++++++++++++++++++ .../src/client/exports/Translate.tsx | 13 ++- .../exports/__tests__/Interpolate.test.tsx | 64 +++++++++++++ .../src/components/TeamProfileCards/index.js | 48 ++++++---- 5 files changed, 223 insertions(+), 24 deletions(-) create mode 100644 packages/docusaurus/src/client/exports/Interpolate.tsx create mode 100644 packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 96203f53b8f2..cac0dfeb70b0 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -84,10 +84,30 @@ declare module '@docusaurus/Link' { export default Link; } +declare module '@docusaurus/Interpolate' { + import type {ReactNode} from 'react'; + + export type InterpolateProps = { + children: Str; + // TODO use TS template literal feature to make values typesafe! + values: Record; + }; + + export default function Interpolate( + props: InterpolateProps, + ): JSX.Element; +} + declare module '@docusaurus/Translate' { - type TranslateProps = {children: string; id?: string; description?: string}; - const Translate: (props: TranslateProps) => JSX.Element; - export default Translate; + import type {InterpolateProps} from '@docusaurus/Interpolate'; + + type TranslateProps = InterpolateProps & { + id?: string; + description?: string; + }; + export default function Translate( + props: TranslateProps, + ): JSX.Element; export function translate(param: { message: string; diff --git a/packages/docusaurus/src/client/exports/Interpolate.tsx b/packages/docusaurus/src/client/exports/Interpolate.tsx new file mode 100644 index 000000000000..e393da9f6fc6 --- /dev/null +++ b/packages/docusaurus/src/client/exports/Interpolate.tsx @@ -0,0 +1,96 @@ +/** + * 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, {ReactNode} from 'react'; + +const ValueRegexp = /{{\w+}}/g; +const ValueFoundMarker = '{{}}'; // does not care much + +// TODO use TS template literal feature to make values typesafe! +// (requires upgrading TS first) +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type ExtractInterpolateParams = string; + +type InterpolateValues = Record< + ExtractInterpolateParams, + Value +>; + +// TS function overload: if all the values are plain strings, then interpolate returns a simple string +export function interpolate( + text: Str, + values?: InterpolateValues, +): string; + +// If values contain any ReactNode, then the return is a ReactNode +export function interpolate( + text: Str, + values?: InterpolateValues, +): ReactNode; + +export function interpolate( + text: Str, + values?: InterpolateValues, +): ReactNode { + const elements: Value[] = []; + + const processedText = text.replace(ValueRegexp, (match: string) => { + // remove {{ and }} around the placeholder + const key = match.substr( + 2, + match.length - 4, + ) as ExtractInterpolateParams; + + const value = values?.[key]; + + if (React.isValidElement(value) || typeof value === 'string') { + elements.push(value); + return ValueFoundMarker; + } + + return match; + }); + + // No interpolation to be done: just return the text + if (elements.length === 0) { + return text; + } + // Basic string interpolation: returns interpolated string + else if (elements.every((el) => typeof el === 'string')) { + return processedText + .split(ValueFoundMarker) + .reduce((str, value, index) => { + return str.concat(value).concat((elements[index] as string) ?? ''); + }, ''); + } + // JSX interpolation: returns ReactNode + else { + return processedText + .split(ValueFoundMarker) + .reduce((array, value, index) => { + return [ + ...array, + + {value} + {elements[index]} + , + ]; + }, []); + } +} + +export type InterpolateProps = { + children: Str; + values?: InterpolateValues; +}; + +export default function Interpolate< + Str extends string, + Value extends ReactNode +>({children, values}: InterpolateProps) { + return interpolate(children, values); +} diff --git a/packages/docusaurus/src/client/exports/Translate.tsx b/packages/docusaurus/src/client/exports/Translate.tsx index d5ff9bff1fff..b9711ed6e795 100644 --- a/packages/docusaurus/src/client/exports/Translate.tsx +++ b/packages/docusaurus/src/client/exports/Translate.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; +import Interpolate, {InterpolateProps} from '@docusaurus/Interpolate'; // Can't read it from context, due to exposing imperative API import codeTranslations from '@generated/codeTranslations'; @@ -33,16 +34,20 @@ export function translate({message, id}: TranslateParam): string { return localizedMessage ?? message; } -export type TranslateProps = { - children: string; +export type TranslateProps = InterpolateProps & { id?: string; description?: string; }; // Maybe we'll want to improve this component with additional features // Like toggling a translation mode that adds a little translation button near the text? -export default function Translate({children, id}: TranslateProps): JSX.Element { +export default function Translate({ + children, + id, + values, +}: TranslateProps): JSX.Element { const localizedMessage: string = getLocalizedMessage({message: children, id}) ?? children; - return <>{localizedMessage}; + + return {localizedMessage}; } diff --git a/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx b/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx new file mode 100644 index 000000000000..deb2ec54b3f9 --- /dev/null +++ b/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx @@ -0,0 +1,64 @@ +/** + * 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 {interpolate} from '../Interpolate'; + +describe('Interpolate', () => { + test('without placeholders', () => { + const text = 'Hello how are you?'; + expect(interpolate(text)).toEqual(text); + }); + + test('placeholders with string values', () => { + const text = 'Hello {{name}} how are you {{day}}?'; + const values = {name: 'Sébastien', day: 'today'}; + expect(interpolate(text, values)).toMatchInlineSnapshot( + `"Hello Sébastien how are you today?"`, + ); + }); + + test('placeholders with string values mismatch', () => { + // Should we emit warnings in such case? + const text = 'Hello {{name}} how are you {{unprovidedValue}}?'; + const values = {name: 'Sébastien', extraValue: 'today'}; + expect(interpolate(text, values)).toMatchInlineSnapshot( + `"Hello Sébastien how are you {{unprovidedValue}}?"`, + ); + }); + + test('placeholders with values not provided', () => { + // Should we emit warnings in such case? + const text = 'Hello {{name}} how are you {{day}}?'; + expect(interpolate(text)).toEqual(text); + expect(interpolate(text, {})).toEqual(text); + }); + + test('placeholders with JSX values', () => { + const text = 'Hello {{name}} how are you {{day}}?'; + const values = {name: Sébastien, day: today}; + expect(interpolate(text, values)).toMatchSnapshot(); + }); + + test('placeholders with mixed vales', () => { + const text = 'Hello {{name}} how are you {{day}}?'; + const values = {name: 'Sébastien', day: today}; + expect(interpolate(text, values)).toMatchSnapshot(); + }); + + test('acceptance test', () => { + const text = + 'Hello {{name}} how are you {{day}}? Another {{unprovidedValue}}!'; + const values = { + name: 'Sébastien', + day: today, + extraUselessValue1:
test
, + extraUselessValue2: 'hi', + }; + expect(interpolate(text, values)).toMatchSnapshot(); + }); +}); diff --git a/website/src/components/TeamProfileCards/index.js b/website/src/components/TeamProfileCards/index.js index 0666a5359c7c..d593d3cf691f 100644 --- a/website/src/components/TeamProfileCards/index.js +++ b/website/src/components/TeamProfileCards/index.js @@ -6,6 +6,8 @@ */ import React from 'react'; +import Translate from '@docusaurus/Translate'; +import Link from '@docusaurus/Link'; function TeamProfileCard({className, name, children, githubUrl, twitterUrl}) { return ( @@ -55,38 +57,50 @@ export function ActiveTeamRow() { - Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ - Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 + + Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ + Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 + - Docusaurus founder and now ever grateful Docusaurus cheerleader to those - who actually write code for it. + + Docusaurus founder and now ever grateful Docusaurus cheerleader to + those who actually write code for it. + - React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. - He writes regularly, on his{' '} - - website - {' '} - and{' '} - - Dev.to - - . + + + website + + + ), + devto: Dev.to, + }}> + { + 'React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. He writes regularly, on his {{website}} and {{devto}}.' + } + - Full Front End Stack developer who likes working on the Jamstack. - Working on Docusaurus made him Facebook's unofficial part-time Open - Source webmaster, which is an awesome role to be in. + + Full Front End Stack developer who likes working on the Jamstack. + Working on Docusaurus made him Facebook's unofficial part-time Open + Source webmaster, which is an awesome role to be in. + ); From ad4d5d5712f3ea36f895089af35286a81c2a2eaa Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 11:29:41 +0100 Subject: [PATCH 03/19] Add interpolate snapshot test --- .../__snapshots__/Interpolate.test.tsx.snap | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap diff --git a/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap b/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap new file mode 100644 index 000000000000..b032a1af6c9c --- /dev/null +++ b/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Interpolate acceptance test 1`] = ` +Array [ + + Hello + Sébastien + , + + how are you + + today + + , + + ? Another {{unprovidedValue}}! + , +] +`; + +exports[`Interpolate placeholders with JSX values 1`] = ` +Array [ + + Hello + + Sébastien + + , + + how are you + + today + + , + + ? + , +] +`; + +exports[`Interpolate placeholders with mixed vales 1`] = ` +Array [ + + Hello + Sébastien + , + + how are you + + today + + , + + ? + , +] +`; From eac8c7144ccda0ef13f77d10c57d6cfaac330934 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 11:55:29 +0100 Subject: [PATCH 04/19] comments --- packages/docusaurus/src/client/exports/Interpolate.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/docusaurus/src/client/exports/Interpolate.tsx b/packages/docusaurus/src/client/exports/Interpolate.tsx index e393da9f6fc6..bf9fe9ee76d3 100644 --- a/packages/docusaurus/src/client/exports/Interpolate.tsx +++ b/packages/docusaurus/src/client/exports/Interpolate.tsx @@ -7,6 +7,12 @@ import React, {ReactNode} from 'react'; +/* +Minimal implementation of a React interpolate component. +We don't ship a markdown parser nor a feature-complete i18n library on purpose. +More details here: https://github.com/facebook/docusaurus/pull/4295 +*/ + const ValueRegexp = /{{\w+}}/g; const ValueFoundMarker = '{{}}'; // does not care much From 3e70088ce0e28b08c0e7a9860a5143b9753c0006 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 12:00:51 +0100 Subject: [PATCH 05/19] fix Interpolate TS types --- .../src/index.d.ts | 25 +++++++++++++++++-- .../src/client/exports/Interpolate.tsx | 12 ++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index cac0dfeb70b0..3d56a0f30f55 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -87,10 +87,31 @@ declare module '@docusaurus/Link' { declare module '@docusaurus/Interpolate' { import type {ReactNode} from 'react'; + // TODO use TS template literal feature to make values typesafe! + // (requires upgrading TS first) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + export type ExtractInterpolateParams = string; + + export type InterpolateValues< + Str extends string, + Value extends ReactNode + > = Record, Value>; + + // TS function overload: if all the values are plain strings, then interpolate returns a simple string + export function interpolate( + text: Str, + values?: InterpolateValues, + ): string; + + // If values contain any ReactNode, then the return is a ReactNode + export function interpolate( + text: Str, + values?: InterpolateValues, + ): ReactNode; + export type InterpolateProps = { children: Str; - // TODO use TS template literal feature to make values typesafe! - values: Record; + values?: InterpolateValues; }; export default function Interpolate( diff --git a/packages/docusaurus/src/client/exports/Interpolate.tsx b/packages/docusaurus/src/client/exports/Interpolate.tsx index bf9fe9ee76d3..c2dd7a45cdbf 100644 --- a/packages/docusaurus/src/client/exports/Interpolate.tsx +++ b/packages/docusaurus/src/client/exports/Interpolate.tsx @@ -89,14 +89,14 @@ export function interpolate( } } -export type InterpolateProps = { +export type InterpolateProps = { children: Str; - values?: InterpolateValues; + values?: InterpolateValues; }; -export default function Interpolate< - Str extends string, - Value extends ReactNode ->({children, values}: InterpolateProps) { +export default function Interpolate({ + children, + values, +}: InterpolateProps) { return interpolate(children, values); } From daa6ebc97ead2f6d49fbe61d99389fdc36bde429 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 12:29:42 +0100 Subject: [PATCH 06/19] Interpolate should handle numbers and other JS types --- .../docusaurus/src/client/exports/Interpolate.tsx | 14 +++++++++----- .../client/exports/__tests__/Interpolate.test.tsx | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/docusaurus/src/client/exports/Interpolate.tsx b/packages/docusaurus/src/client/exports/Interpolate.tsx index c2dd7a45cdbf..3f4a35f8a50e 100644 --- a/packages/docusaurus/src/client/exports/Interpolate.tsx +++ b/packages/docusaurus/src/client/exports/Interpolate.tsx @@ -42,7 +42,7 @@ export function interpolate( text: Str, values?: InterpolateValues, ): ReactNode { - const elements: Value[] = []; + const elements: (Value | string)[] = []; const processedText = text.replace(ValueRegexp, (match: string) => { // remove {{ and }} around the placeholder @@ -53,12 +53,16 @@ export function interpolate( const value = values?.[key]; - if (React.isValidElement(value) || typeof value === 'string') { - elements.push(value); + if (value) { + const element = React.isValidElement(value) + ? value + : // For non-React elements: basic primitive->string conversion + String(value); + elements.push(element); return ValueFoundMarker; + } else { + return match; // no match? add warning? } - - return match; }); // No interpolation to be done: just return the text diff --git a/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx b/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx index deb2ec54b3f9..44b830640f96 100644 --- a/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx +++ b/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx @@ -22,6 +22,20 @@ describe('Interpolate', () => { ); }); + test('placeholders with string values', () => { + const text = '{{number}} {{string}} {{object}} {{array}}'; + const values = { + number: 42, + string: 'Hello', + object: {hello: 'world'}, + array: ['Hello'], + }; + // Do we need to improve the JS type -> String conversion logic here? + expect(interpolate(text, values)).toMatchInlineSnapshot( + `"42 Hello [object Object] Hello"`, + ); + }); + test('placeholders with string values mismatch', () => { // Should we emit warnings in such case? const text = 'Hello {{name}} how are you {{unprovidedValue}}?'; From 9812c7c09bff0dbf2c198a2643d9811c1e342388 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 12:30:16 +0100 Subject: [PATCH 07/19] translate BlogPostItem --- .../src/theme/BlogPostItem/index.tsx | 95 ++++++++++++++++--- 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx index e0d88f6812c7..10c56781670f 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx @@ -8,7 +8,7 @@ import React from 'react'; import clsx from 'clsx'; import {MDXProvider} from '@mdx-js/react'; -import Translate from '@docusaurus/Translate'; +import Translate, {translate} from '@docusaurus/Translate'; import Link from '@docusaurus/Link'; import MDXComponents from '@theme/MDXComponents'; import Seo from '@theme/Seo'; @@ -17,18 +17,66 @@ import type {Props} from '@theme/BlogPostItem'; import styles from './styles.module.css'; const MONTHS = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', + translate({ + id: 'common.month.january', + description: 'January month translation', + message: 'January', + }), + translate({ + id: 'common.month.february', + description: 'February month translation', + message: 'February', + }), + translate({ + id: 'common.month.march', + description: 'March month translation', + message: 'March', + }), + translate({ + id: 'common.month.april', + description: 'April month translation', + message: 'April', + }), + translate({ + id: 'common.month.may', + description: 'May month translation', + message: 'May', + }), + translate({ + id: 'common.month.june', + description: 'June month translation', + message: 'June', + }), + translate({ + id: 'common.month.july', + description: 'July month translation', + message: 'July', + }), + translate({ + id: 'common.month.august', + description: 'August month translation', + message: 'August', + }), + translate({ + id: 'common.month.september', + description: 'September month translation', + message: 'September', + }), + translate({ + id: 'common.month.october', + description: 'October month translation', + message: 'October', + }), + translate({ + id: 'common.month.november', + description: 'November month translation', + message: 'November', + }), + translate({ + id: 'common.month.december', + description: 'December month translation', + message: 'December', + }), ]; function BlogPostItem(props: Props): JSX.Element { @@ -62,8 +110,25 @@ function BlogPostItem(props: Props): JSX.Element {
From 684c84c85a17127d9fdca3555ec8175753d5e554 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 14:41:57 +0100 Subject: [PATCH 08/19] interpolate translate() fn + add translations for blog post tag header --- .../src/index.d.ts | 16 +++++++----- .../src/theme/BlogTagsPostsPage/index.tsx | 26 +++++++++++++++---- .../src/client/exports/Interpolate.tsx | 8 +++--- .../src/client/exports/Translate.tsx | 21 ++++++++++----- 4 files changed, 50 insertions(+), 21 deletions(-) diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 3d56a0f30f55..ddfcbda7cb73 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -90,17 +90,17 @@ declare module '@docusaurus/Interpolate' { // TODO use TS template literal feature to make values typesafe! // (requires upgrading TS first) // eslint-disable-next-line @typescript-eslint/no-unused-vars - export type ExtractInterpolateParams = string; + export type ExtractInterpolatePlaceholders = string; export type InterpolateValues< Str extends string, Value extends ReactNode - > = Record, Value>; + > = Record, Value>; // TS function overload: if all the values are plain strings, then interpolate returns a simple string export function interpolate( text: Str, - values?: InterpolateValues, + values?: InterpolateValues, ): string; // If values contain any ReactNode, then the return is a ReactNode @@ -120,7 +120,10 @@ declare module '@docusaurus/Interpolate' { } declare module '@docusaurus/Translate' { - import type {InterpolateProps} from '@docusaurus/Interpolate'; + import type { + InterpolateProps, + InterpolateValues, + } from '@docusaurus/Interpolate'; type TranslateProps = InterpolateProps & { id?: string; @@ -130,10 +133,11 @@ declare module '@docusaurus/Translate' { props: TranslateProps, ): JSX.Element; - export function translate(param: { - message: string; + export function translate(param: { + message: Str; id?: string; description?: string; + values?: InterpolateValues; }): string; } diff --git a/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx index c89b0051217c..f6f64f5efd97 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx @@ -12,10 +12,22 @@ import BlogPostItem from '@theme/BlogPostItem'; import Link from '@docusaurus/Link'; import type {Props} from '@theme/BlogTagsPostsPage'; import BlogSidebar from '@theme/BlogSidebar'; -import Translate from '@docusaurus/Translate'; +import Translate, {translate} from '@docusaurus/Translate'; -function pluralize(count: number, word: string) { - return count > 1 ? `${word}s` : word; +function pluralizePosts(count: number): string { + return count === 1 + ? translate({ + id: 'theme.blog.post.onePost', + description: 'Label to describe one blog post', + message: 'One post', + values: {count}, + }) + : translate({ + id: 'theme.blog.post.nPosts', + description: 'Label to describe multiple blog posts', + message: '{{count}} posts', + values: {count}, + }); } function BlogTagsPostPage(props: Props): JSX.Element { @@ -35,8 +47,12 @@ function BlogTagsPostPage(props: Props): JSX.Element {

- {count} {pluralize(count, 'post')} tagged with "{tagName} - " + + {'{{nPosts}} tagged with "{{tagName}}"'} +

= string; +type ExtractInterpolatePlaceholders = string; type InterpolateValues = Record< - ExtractInterpolateParams, + ExtractInterpolatePlaceholders, Value >; // TS function overload: if all the values are plain strings, then interpolate returns a simple string export function interpolate( text: Str, - values?: InterpolateValues, + values?: InterpolateValues, ): string; // If values contain any ReactNode, then the return is a ReactNode @@ -49,7 +49,7 @@ export function interpolate( const key = match.substr( 2, match.length - 4, - ) as ExtractInterpolateParams; + ) as ExtractInterpolatePlaceholders; const value = values?.[key]; diff --git a/packages/docusaurus/src/client/exports/Translate.tsx b/packages/docusaurus/src/client/exports/Translate.tsx index b9711ed6e795..1a6fa6347ed3 100644 --- a/packages/docusaurus/src/client/exports/Translate.tsx +++ b/packages/docusaurus/src/client/exports/Translate.tsx @@ -6,7 +6,11 @@ */ import React from 'react'; -import Interpolate, {InterpolateProps} from '@docusaurus/Interpolate'; +import Interpolate, { + interpolate, + InterpolateProps, + InterpolateValues, +} from '@docusaurus/Interpolate'; // Can't read it from context, due to exposing imperative API import codeTranslations from '@generated/codeTranslations'; @@ -21,17 +25,22 @@ function getLocalizedMessage({ return codeTranslations[id ?? message] ?? message; } -export type TranslateParam = { - message: string; +export type TranslateParam = { + message: Str; id?: string; description?: string; + values?: InterpolateValues; }; // Imperative translation API is useful for some edge-cases: // - translating page titles (meta) // - translating string props (input placeholders, image alt, aria labels...) -export function translate({message, id}: TranslateParam): string { - const localizedMessage = getLocalizedMessage({message, id}); - return localizedMessage ?? message; +export function translate({ + message, + id, + values, +}: TranslateParam): string { + const localizedMessage = getLocalizedMessage({message, id}) ?? message; + return interpolate(localizedMessage, values); } export type TranslateProps = InterpolateProps & { From 23df278d9d210ba5df6fb6a9df50050cecf471b2 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 15:10:46 +0100 Subject: [PATCH 09/19] localize the LastUpdated component --- .../src/theme/BlogTagsPostsPage/index.tsx | 1 + .../src/theme/DocItem/index.tsx | 41 ++------- .../src/theme/DocItem/styles.module.css | 4 - .../src/theme/LastUpdated/index.tsx | 88 +++++++++++++++++++ .../src/theme/LastUpdated/styles.module.css | 10 +++ 5 files changed, 104 insertions(+), 40 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx create mode 100644 packages/docusaurus-theme-classic/src/theme/LastUpdated/styles.module.css diff --git a/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx index f6f64f5efd97..1f770fc1f735 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogTagsPostsPage/index.tsx @@ -14,6 +14,7 @@ import type {Props} from '@theme/BlogTagsPostsPage'; import BlogSidebar from '@theme/BlogSidebar'; import Translate, {translate} from '@docusaurus/Translate'; +// Very simple pluralization: probably good enough for now function pluralizePosts(count: number): string { return count === 1 ? translate({ diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx index 764eac5492ba..329fd3a36c8a 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx @@ -9,6 +9,7 @@ import React from 'react'; import DocPaginator from '@theme/DocPaginator'; import DocVersionSuggestions from '@theme/DocVersionSuggestions'; import Seo from '@theme/Seo'; +import LastUpdated from '@theme/LastUpdated'; import type {Props} from '@theme/DocItem'; import TOC from '@theme/TOC'; import EditThisPage from '@theme/EditThisPage'; @@ -78,42 +79,10 @@ function DocItem(props: Props): JSX.Element { {editUrl && } {(lastUpdatedAt || lastUpdatedBy) && ( -
- - - {/* TODO: wait for using interpolation in translation function */} - Last updated{' '} - {lastUpdatedAt && ( - <> - on{' '} - - {lastUpdatedBy && ' '} - - )} - {lastUpdatedBy && ( - <> - by {lastUpdatedBy} - - )} - {process.env.NODE_ENV === 'development' && ( -
- - {' '} - (Simulated during dev for better perf) - -
- )} -
-
-
+ )} diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css b/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css index 6c365bdf7455..41c2d0c0e005 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css @@ -26,7 +26,3 @@ padding: 0 0.3rem; } } - -.docLastUpdatedAt { - font-weight: bold; -} diff --git a/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx b/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx new file mode 100644 index 000000000000..29d17c2f5439 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx @@ -0,0 +1,88 @@ +/** + * 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 styles from './styles.module.css'; +import Translate from '@docusaurus/Translate'; + +function LastUpdatedAtDate({lastUpdatedAt}: {lastUpdatedAt: number}) { + return ( + + {new Date(lastUpdatedAt * 1000).toLocaleDateString()} + + ), + }}> + {'on {{date}}'} + + ); +} + +function LastUpdatedByUser({lastUpdatedBy}: {lastUpdatedBy: string}) { + return ( + {lastUpdatedBy}, + }}> + {'by {{user}}'} + + ); +} + +export default function LastUpdated({ + lastUpdatedAt, + lastUpdatedBy, +}: { + lastUpdatedAt: number | undefined; + lastUpdatedBy: string | undefined; +}) { + return ( +
+ + + + {' '} + + + ) : ( + '' + ), + by: lastUpdatedBy ? ( + <> + {' '} + + + ) : ( + '' + ), + }}> + {'Last updated{{on}}{{by}}'} + + {process.env.NODE_ENV === 'development' && ( +
+ (Simulated during dev for better perf) +
+ )} +
+
+
+ ); +} diff --git a/packages/docusaurus-theme-classic/src/theme/LastUpdated/styles.module.css b/packages/docusaurus-theme-classic/src/theme/LastUpdated/styles.module.css new file mode 100644 index 000000000000..10bd9cf12841 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/LastUpdated/styles.module.css @@ -0,0 +1,10 @@ +/** + * 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. + */ + +.lastUpdatedDate { + font-weight: bold; +} From 07bb0d08e8c85e81304953bc817ddfa18ccffcbe Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 15:35:25 +0100 Subject: [PATCH 10/19] translate DocVersionSuggestions --- .../src/theme/DocVersionSuggestions/index.tsx | 120 ++++++++++++++---- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx index 5aa37268e04e..2f29ee6283d8 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx @@ -8,6 +8,7 @@ import React from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import Link from '@docusaurus/Link'; +import Translate from '@docusaurus/Translate'; import { useActivePlugin, useActiveVersion, @@ -15,6 +16,82 @@ import { } from '@theme/hooks/useDocs'; import {useDocsPreferredVersion} from '@docusaurus/theme-common'; +function UnreleasedVersionLabel({ + siteTitle, + versionLabel, +}: { + siteTitle: string; + versionLabel: string; +}) { + return ( + {versionLabel}, + }}> + { + 'This is unreleased documentation for {{siteTitle}} {{versionLabel}} version.' + } + + ); +} + +function UnmaintainedVersionLabel({ + siteTitle, + versionLabel, +}: { + siteTitle: string; + versionLabel: string; +}) { + return ( + {versionLabel}, + }}> + { + 'This is documentation for {{siteTitle}} {{versionLabel}}, which is no longer actively maintained.' + } + + ); +} + +function LatestVersionSuggestionLabel({ + versionLabel, + to, + onClick, +}: { + to: string; + onClick: () => void; + versionLabel: string; +}) { + return ( + + + + latest version + + + + ), + }}> + {'For up-to-date documentation, see the {{link}} ({{versionLabel}}).'} + + ); +} + const getVersionMainDoc = (version) => version.docs.find((doc) => doc.id === version.mainDocId); @@ -44,34 +121,25 @@ function DocVersionSuggestions(): JSX.Element { return (
- { - // TODO need refactoring - // TODO need translate after interpolation appears - activeVersion.name === 'current' ? ( -
- This is unreleased documentation for {siteTitle}{' '} - {activeVersion.label} version. -
+
+ {activeVersion.name === 'current' ? ( + ) : ( -
- This is documentation for {siteTitle}{' '} - {activeVersion.label}, which is no longer actively - maintained. -
- ) - } + + )} +
- For up-to-date documentation, see the{' '} - - - savePreferredVersionName(latestVersionSuggestion.name) - }> - latest version - - {' '} - ({latestVersionSuggestion.label}). + savePreferredVersionName(latestVersionSuggestion.name)} + />
); From d52fc85897675a7ac6ba88f0bf82a8279cecc087 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 16:08:57 +0100 Subject: [PATCH 11/19] fix test --- .../src/webpack/__tests__/__snapshots__/base.test.ts.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap index a9a3d4752149..779a2399337f 100644 --- a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap +++ b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap @@ -6,6 +6,7 @@ Object { "@docusaurus/ComponentCreator": "../../client/exports/ComponentCreator.tsx", "@docusaurus/ExecutionEnvironment": "../../client/exports/ExecutionEnvironment.ts", "@docusaurus/Head": "../../client/exports/Head.tsx", + "@docusaurus/Interpolate": "../../client/exports/Interpolate.tsx", "@docusaurus/Link": "../../client/exports/Link.tsx", "@docusaurus/Noop": "../../client/exports/Noop.ts", "@docusaurus/Translate": "../../client/exports/Translate.tsx", From f1cfd2d2074b60ba0bc37487135ec7cb099cf501 Mon Sep 17 00:00:00 2001 From: slorber Date: Thu, 25 Feb 2021 16:12:25 +0100 Subject: [PATCH 12/19] add some new translations --- .../codeTranslations/base.json | 26 ++++++++++++++++++- .../codeTranslations/fr.json | 26 ++++++++++++++++++- .../src/theme/BlogTagsListPage/index.tsx | 1 - .../src/theme/BlogTagsPostsPage/index.tsx | 5 ++-- .../src/theme/DocVersionSuggestions/index.tsx | 6 +++-- .../src/theme/LastUpdated/index.tsx | 11 +++++--- 6 files changed, 63 insertions(+), 12 deletions(-) diff --git a/packages/docusaurus-theme-classic/codeTranslations/base.json b/packages/docusaurus-theme-classic/codeTranslations/base.json index adf52aad84e9..59029b767326 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/base.json +++ b/packages/docusaurus-theme-classic/codeTranslations/base.json @@ -40,5 +40,29 @@ "theme.PwaReloadPopup.refreshButtonText": "Refresh", "theme.PwaReloadPopup.closeButtonAriaLabel": "Close", "theme.Playground.liveEditor": "Live Editor", - "theme.Playground.result": "Result" + "theme.Playground.result": "Result", + "common.month.january": "January", + "common.month.february": "February", + "common.month.march": "March", + "common.month.april": "April", + "common.month.may": "May", + "common.month.june": "June", + "common.month.july": "July", + "common.month.august": "August", + "common.month.september": "September", + "common.month.october": "October", + "common.month.november": "November", + "common.month.december": "December", + "theme.blog.post.date": "{{month}} {{day}}, {{year}}", + "theme.blog.post.readingTime": "{{readingTime}} min read", + "theme.blog.post.onePost": "One post", + "theme.blog.post.nPosts": "{{count}} posts", + "theme.blog.tagTitle": "{{nPosts}} tagged with \"{{tagName}}\"", + "theme.docs.versions.unreleasedVersionLabel": "This is unreleased documentation for {{siteTitle}} {{versionLabel}} version.", + "theme.docs.versions.unmaintainedVersionLabel": "This is documentation for {{siteTitle}} {{versionLabel}}, which is no longer actively maintained.", + "theme.docs.versions.latestVersionSuggestionLabel": "For up-to-date documentation, see the {{latestVersionLink}} ({{versionLabel}}).", + "theme.docs.versions.latestVersionLinkLabel": "latest version", + "theme.lastUpdated.atDate": "on {{date}}", + "theme.lastUpdated.byUser": "by {{user}}", + "theme.lastUpdated.lastUpdatedAtBy": "Last updated{{atDate}}{{byUser}}" } diff --git a/packages/docusaurus-theme-classic/codeTranslations/fr.json b/packages/docusaurus-theme-classic/codeTranslations/fr.json index 56aff31a09c9..fc53f77edf6c 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/fr.json +++ b/packages/docusaurus-theme-classic/codeTranslations/fr.json @@ -40,5 +40,29 @@ "theme.PwaReloadPopup.refreshButtonText": "Rafraichir", "theme.PwaReloadPopup.closeButtonAriaLabel": "Fermer", "theme.Playground.liveEditor": "Éditeur en direct", - "theme.Playground.result": "Résultat" + "theme.Playground.result": "Résultat", + "common.month.january": "Janvier", + "common.month.february": "Février", + "common.month.march": "Mars", + "common.month.april": "Avril", + "common.month.may": "Mai", + "common.month.june": "Juin", + "common.month.july": "Juillet", + "common.month.august": "Août", + "common.month.september": "Septembre", + "common.month.october": "Octobre", + "common.month.november": "Novembre", + "common.month.december": "Décembre", + "theme.blog.post.date": "{{day}} {{month}} {{year}}", + "theme.blog.post.readingTime": "{{readingTime}} min de lecture", + "theme.blog.post.onePost": "Un article", + "theme.blog.post.nPosts": "{{count}} articles", + "theme.blog.tagTitle": "{{nPosts}} taggés avec \"{{tagName}}\"", + "theme.docs.versions.unreleasedVersionLabel": "Ceci est la documentation de la prochaine version {{versionLabel}} de {{siteTitle}}.", + "theme.docs.versions.unmaintainedVersionLabel": "Ceci est la documentation de {{siteTitle}} {{versionLabel}}, qui n'est plus activement maintenue.", + "theme.docs.versions.latestVersionSuggestionLabel": "Pour une documentation à jour, consultez la {{latestVersionLink}} ({{versionLabel}}).", + "theme.docs.versions.latestVersionLinkLabel": "dernière version", + "theme.lastUpdated.atDate": "le {{date}}", + "theme.lastUpdated.byUser": "par {{user}}", + "theme.lastUpdated.lastUpdatedAtBy": "Dernière mise à jour{{atDate}}{{byUser}}" } diff --git a/packages/docusaurus-theme-classic/src/theme/BlogTagsListPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogTagsListPage/index.tsx index c35a775066ad..d08ba34c8856 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogTagsListPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogTagsListPage/index.tsx @@ -50,7 +50,6 @@ function BlogTagsListPage(props: Props): JSX.Element { )) .filter((item) => item != null); - // TODO soon: translate hardcoded labels, but factorize them (blog + docs will both have tags) return (

{'{{nPosts}} tagged with "{{tagName}}"'} diff --git a/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx index 2f29ee6283d8..6dada5a09ded 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx @@ -75,7 +75,7 @@ function LatestVersionSuggestionLabel({ description="The label userd to tell the user that he's browsing an unmaintained doc version" values={{ versionLabel, - link: ( + latestVersionLink: ( ), }}> - {'For up-to-date documentation, see the {{link}} ({{versionLabel}}).'} + { + 'For up-to-date documentation, see the {{latestVersionLink}} ({{versionLabel}}).' + } ); } diff --git a/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx b/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx index 29d17c2f5439..4f82bbbdf09f 100644 --- a/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx @@ -16,6 +16,9 @@ function LastUpdatedAtDate({lastUpdatedAt}: {lastUpdatedAt: number}) { description="The words used to describe on which date a page has been last updated" values={{ // TODO localize this date + // If it's the only place we need this, we'd rather keep it simple + // Day.js may be a good lightweight option? + // https://www.skypack.dev/blog/2021/02/the-best-javascript-date-libraries/ date: (

diff --git a/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx index 6dada5a09ded..9018ba72fc67 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocVersionSuggestions/index.tsx @@ -32,7 +32,7 @@ function UnreleasedVersionLabel({ versionLabel: {versionLabel}, }}> { - 'This is unreleased documentation for {{siteTitle}} {{versionLabel}} version.' + 'This is unreleased documentation for {siteTitle} {versionLabel} version.' }
); @@ -54,7 +54,7 @@ function UnmaintainedVersionLabel({ versionLabel: {versionLabel}, }}> { - 'This is documentation for {{siteTitle}} {{versionLabel}}, which is no longer actively maintained.' + 'This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.' } ); @@ -88,7 +88,7 @@ function LatestVersionSuggestionLabel({ ), }}> { - 'For up-to-date documentation, see the {{latestVersionLink}} ({{versionLabel}}).' + 'For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).' } ); diff --git a/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx b/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx index 4f82bbbdf09f..338b7c9827b4 100644 --- a/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/LastUpdated/index.tsx @@ -27,7 +27,7 @@ function LastUpdatedAtDate({lastUpdatedAt}: {lastUpdatedAt: number}) { ), }}> - {'on {{date}}'} + {'on {date}'} ); } @@ -40,7 +40,7 @@ function LastUpdatedByUser({lastUpdatedBy}: {lastUpdatedBy: string}) { values={{ user: {lastUpdatedBy}, }}> - {'by {{user}}'} + {'by {user}'} ); } @@ -77,7 +77,7 @@ export default function LastUpdated({ '' ), }}> - {'Last updated{{atDate}}{{byUser}}'} + {'Last updated{atDate}{byUser}'} {process.env.NODE_ENV === 'development' && (
diff --git a/packages/docusaurus/src/client/exports/Interpolate.tsx b/packages/docusaurus/src/client/exports/Interpolate.tsx index e1c9406649ea..006e8be04683 100644 --- a/packages/docusaurus/src/client/exports/Interpolate.tsx +++ b/packages/docusaurus/src/client/exports/Interpolate.tsx @@ -13,8 +13,8 @@ We don't ship a markdown parser nor a feature-complete i18n library on purpose. More details here: https://github.com/facebook/docusaurus/pull/4295 */ -const ValueRegexp = /{{\w+}}/g; -const ValueFoundMarker = '{{}}'; // does not care much +const ValueRegexp = /{\w+}/g; +const ValueFoundMarker = '{}'; // does not care much // TODO use TS template literal feature to make values typesafe! // (requires upgrading TS first) @@ -47,8 +47,8 @@ export function interpolate( const processedText = text.replace(ValueRegexp, (match: string) => { // remove {{ and }} around the placeholder const key = match.substr( - 2, - match.length - 4, + 1, + match.length - 2, ) as ExtractInterpolatePlaceholders; const value = values?.[key]; diff --git a/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx b/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx index 44b830640f96..b4d72253d31c 100644 --- a/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx +++ b/packages/docusaurus/src/client/exports/__tests__/Interpolate.test.tsx @@ -15,7 +15,7 @@ describe('Interpolate', () => { }); test('placeholders with string values', () => { - const text = 'Hello {{name}} how are you {{day}}?'; + const text = 'Hello {name} how are you {day}?'; const values = {name: 'Sébastien', day: 'today'}; expect(interpolate(text, values)).toMatchInlineSnapshot( `"Hello Sébastien how are you today?"`, @@ -23,7 +23,7 @@ describe('Interpolate', () => { }); test('placeholders with string values', () => { - const text = '{{number}} {{string}} {{object}} {{array}}'; + const text = '{number} {string} {object} {array}'; const values = { number: 42, string: 'Hello', @@ -38,35 +38,34 @@ describe('Interpolate', () => { test('placeholders with string values mismatch', () => { // Should we emit warnings in such case? - const text = 'Hello {{name}} how are you {{unprovidedValue}}?'; + const text = 'Hello {name} how are you {unprovidedValue}?'; const values = {name: 'Sébastien', extraValue: 'today'}; expect(interpolate(text, values)).toMatchInlineSnapshot( - `"Hello Sébastien how are you {{unprovidedValue}}?"`, + `"Hello Sébastien how are you {unprovidedValue}?"`, ); }); test('placeholders with values not provided', () => { // Should we emit warnings in such case? - const text = 'Hello {{name}} how are you {{day}}?'; + const text = 'Hello {name} how are you {day}?'; expect(interpolate(text)).toEqual(text); expect(interpolate(text, {})).toEqual(text); }); test('placeholders with JSX values', () => { - const text = 'Hello {{name}} how are you {{day}}?'; + const text = 'Hello {name} how are you {day}?'; const values = {name: Sébastien, day: today}; expect(interpolate(text, values)).toMatchSnapshot(); }); test('placeholders with mixed vales', () => { - const text = 'Hello {{name}} how are you {{day}}?'; + const text = 'Hello {name} how are you {day}?'; const values = {name: 'Sébastien', day: today}; expect(interpolate(text, values)).toMatchSnapshot(); }); test('acceptance test', () => { - const text = - 'Hello {{name}} how are you {{day}}? Another {{unprovidedValue}}!'; + const text = 'Hello {name} how are you {day}? Another {unprovidedValue}!'; const values = { name: 'Sébastien', day: today, diff --git a/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap b/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap index b032a1af6c9c..a42c4388ab6e 100644 --- a/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap +++ b/packages/docusaurus/src/client/exports/__tests__/__snapshots__/Interpolate.test.tsx.snap @@ -13,7 +13,7 @@ Array [ , - ? Another {{unprovidedValue}}! + ? Another {unprovidedValue}! , ] `; From fa0a7828fa0a2ef58ee20c19812bd1fd705e8f16 Mon Sep 17 00:00:00 2001 From: slorber Date: Fri, 26 Feb 2021 10:54:01 +0100 Subject: [PATCH 16/19] refactor month key --- .../codeTranslations/base.json | 24 +++++++++---------- .../codeTranslations/de.json | 24 +++++++++---------- .../codeTranslations/fa.json | 24 +++++++++---------- .../codeTranslations/fr.json | 24 +++++++++---------- .../codeTranslations/ru.json | 24 +++++++++---------- .../src/theme/BlogPostItem/index.tsx | 24 +++++++++---------- 6 files changed, 72 insertions(+), 72 deletions(-) diff --git a/packages/docusaurus-theme-classic/codeTranslations/base.json b/packages/docusaurus-theme-classic/codeTranslations/base.json index 5967dea08e09..c3083fc1794a 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/base.json +++ b/packages/docusaurus-theme-classic/codeTranslations/base.json @@ -1,16 +1,16 @@ { - "common.month.april": "April", - "common.month.august": "August", - "common.month.december": "December", - "common.month.february": "February", - "common.month.january": "January", - "common.month.july": "July", - "common.month.june": "June", - "common.month.march": "March", - "common.month.may": "May", - "common.month.november": "November", - "common.month.october": "October", - "common.month.september": "September", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "Close", "theme.CodeBlock.copied": "Copied", "theme.CodeBlock.copy": "Copy", diff --git a/packages/docusaurus-theme-classic/codeTranslations/de.json b/packages/docusaurus-theme-classic/codeTranslations/de.json index 7a5b7722a571..42f26f7865b5 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/de.json +++ b/packages/docusaurus-theme-classic/codeTranslations/de.json @@ -1,16 +1,16 @@ { - "common.month.april": "April", - "common.month.august": "August", - "common.month.december": "December", - "common.month.february": "February", - "common.month.january": "January", - "common.month.july": "July", - "common.month.june": "June", - "common.month.march": "March", - "common.month.may": "May", - "common.month.november": "November", - "common.month.october": "October", - "common.month.september": "September", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "Schließen", "theme.CodeBlock.copied": "Kopiert", "theme.CodeBlock.copy": "Kopieren", diff --git a/packages/docusaurus-theme-classic/codeTranslations/fa.json b/packages/docusaurus-theme-classic/codeTranslations/fa.json index afa5109cfffb..4858f18dd0df 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/fa.json +++ b/packages/docusaurus-theme-classic/codeTranslations/fa.json @@ -1,16 +1,16 @@ { - "common.month.april": "April", - "common.month.august": "August", - "common.month.december": "December", - "common.month.february": "February", - "common.month.january": "January", - "common.month.july": "July", - "common.month.june": "June", - "common.month.march": "March", - "common.month.may": "May", - "common.month.november": "November", - "common.month.october": "October", - "common.month.september": "September", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "بستن", "theme.CodeBlock.copied": "کپی شد", "theme.CodeBlock.copy": "کپی کردن", diff --git a/packages/docusaurus-theme-classic/codeTranslations/fr.json b/packages/docusaurus-theme-classic/codeTranslations/fr.json index 945048e35ce7..dcd808d0cb5a 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/fr.json +++ b/packages/docusaurus-theme-classic/codeTranslations/fr.json @@ -1,16 +1,16 @@ { - "common.month.april": "Avril", - "common.month.august": "Août", - "common.month.december": "Décembre", - "common.month.february": "Février", - "common.month.january": "Janvier", - "common.month.july": "Juillet", - "common.month.june": "Juin", - "common.month.march": "Mars", - "common.month.may": "Mai", - "common.month.november": "Novembre", - "common.month.october": "Octobre", - "common.month.september": "Septembre", + "theme.common.month.april": "Avril", + "theme.common.month.august": "Août", + "theme.common.month.december": "Décembre", + "theme.common.month.february": "Février", + "theme.common.month.january": "Janvier", + "theme.common.month.july": "Juillet", + "theme.common.month.june": "Juin", + "theme.common.month.march": "Mars", + "theme.common.month.may": "Mai", + "theme.common.month.november": "Novembre", + "theme.common.month.october": "Octobre", + "theme.common.month.september": "Septembre", "theme.AnnouncementBar.closeButtonAriaLabel": "Fermer", "theme.CodeBlock.copied": "Copié", "theme.CodeBlock.copy": "Copier", diff --git a/packages/docusaurus-theme-classic/codeTranslations/ru.json b/packages/docusaurus-theme-classic/codeTranslations/ru.json index a007618ce89a..9f6681697cb8 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/ru.json +++ b/packages/docusaurus-theme-classic/codeTranslations/ru.json @@ -1,16 +1,16 @@ { - "common.month.april": "April", - "common.month.august": "August", - "common.month.december": "December", - "common.month.february": "February", - "common.month.january": "January", - "common.month.july": "July", - "common.month.june": "June", - "common.month.march": "March", - "common.month.may": "May", - "common.month.november": "November", - "common.month.october": "October", - "common.month.september": "September", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "Закрыть", "theme.CodeBlock.copied": "Скопировано", "theme.CodeBlock.copy": "Скопировать", diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx index 05288800fcf6..b301ac0a66d0 100644 --- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/index.tsx @@ -18,62 +18,62 @@ import styles from './styles.module.css'; const MONTHS = [ translate({ - id: 'common.month.january', + id: 'theme.common.month.january', description: 'January month translation', message: 'January', }), translate({ - id: 'common.month.february', + id: 'theme.common.month.february', description: 'February month translation', message: 'February', }), translate({ - id: 'common.month.march', + id: 'theme.common.month.march', description: 'March month translation', message: 'March', }), translate({ - id: 'common.month.april', + id: 'theme.common.month.april', description: 'April month translation', message: 'April', }), translate({ - id: 'common.month.may', + id: 'theme.common.month.may', description: 'May month translation', message: 'May', }), translate({ - id: 'common.month.june', + id: 'theme.common.month.june', description: 'June month translation', message: 'June', }), translate({ - id: 'common.month.july', + id: 'theme.common.month.july', description: 'July month translation', message: 'July', }), translate({ - id: 'common.month.august', + id: 'theme.common.month.august', description: 'August month translation', message: 'August', }), translate({ - id: 'common.month.september', + id: 'theme.common.month.september', description: 'September month translation', message: 'September', }), translate({ - id: 'common.month.october', + id: 'theme.common.month.october', description: 'October month translation', message: 'October', }), translate({ - id: 'common.month.november', + id: 'theme.common.month.november', description: 'November month translation', message: 'November', }), translate({ - id: 'common.month.december', + id: 'theme.common.month.december', description: 'December month translation', message: 'December', }), From de9cc59ea0875e6904924b39c7ce275258b553de Mon Sep 17 00:00:00 2001 From: slorber Date: Fri, 26 Feb 2021 10:54:44 +0100 Subject: [PATCH 17/19] order --- .../codeTranslations/base.json | 26 +++++++++---------- .../codeTranslations/de.json | 26 +++++++++---------- .../codeTranslations/fa.json | 26 +++++++++---------- .../codeTranslations/fr.json | 26 +++++++++---------- .../codeTranslations/ru.json | 26 +++++++++---------- 5 files changed, 65 insertions(+), 65 deletions(-) diff --git a/packages/docusaurus-theme-classic/codeTranslations/base.json b/packages/docusaurus-theme-classic/codeTranslations/base.json index c3083fc1794a..6f43123bbe51 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/base.json +++ b/packages/docusaurus-theme-classic/codeTranslations/base.json @@ -1,16 +1,4 @@ { - "theme.common.month.april": "April", - "theme.common.month.august": "August", - "theme.common.month.december": "December", - "theme.common.month.february": "February", - "theme.common.month.january": "January", - "theme.common.month.july": "July", - "theme.common.month.june": "June", - "theme.common.month.march": "March", - "theme.common.month.may": "May", - "theme.common.month.november": "November", - "theme.common.month.october": "October", - "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "Close", "theme.CodeBlock.copied": "Copied", "theme.CodeBlock.copy": "Copy", @@ -45,6 +33,18 @@ "theme.blog.tagTitle": "{nPosts} tagged with \"{tagName}\"", "theme.common.editThisPage": "Edit this page", "theme.common.headingLinkTitle": "Direct link to heading", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.common.skipToMainContent": "Skip to main content", "theme.docs.paginator.navAriaLabel": "Docs pages navigation", "theme.docs.paginator.next": "Next", @@ -65,4 +65,4 @@ "theme.tags.tagsListLabel": "Tags:", "theme.tags.tagsPageLink": "View All Tags", "theme.tags.tagsPageTitle": "Tags" -} +} \ No newline at end of file diff --git a/packages/docusaurus-theme-classic/codeTranslations/de.json b/packages/docusaurus-theme-classic/codeTranslations/de.json index 42f26f7865b5..ad96bfe8aeab 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/de.json +++ b/packages/docusaurus-theme-classic/codeTranslations/de.json @@ -1,16 +1,4 @@ { - "theme.common.month.april": "April", - "theme.common.month.august": "August", - "theme.common.month.december": "December", - "theme.common.month.february": "February", - "theme.common.month.january": "January", - "theme.common.month.july": "July", - "theme.common.month.june": "June", - "theme.common.month.march": "March", - "theme.common.month.may": "May", - "theme.common.month.november": "November", - "theme.common.month.october": "October", - "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "Schließen", "theme.CodeBlock.copied": "Kopiert", "theme.CodeBlock.copy": "Kopieren", @@ -45,6 +33,18 @@ "theme.blog.tagTitle": "{nPosts} tagged with \"{tagName}\"", "theme.common.editThisPage": "Diese Seite bearbeiten", "theme.common.headingLinkTitle": "Direkter Link zur Überschrift", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.common.skipToMainContent": "Zum Hauptinhalt springen", "theme.docs.paginator.navAriaLabel": "Dokumentation Seiten Navigation", "theme.docs.paginator.next": "Weiter", @@ -65,4 +65,4 @@ "theme.tags.tagsListLabel": "Tags:", "theme.tags.tagsPageLink": "Alle Tags anzeigen", "theme.tags.tagsPageTitle": "Tags" -} +} \ No newline at end of file diff --git a/packages/docusaurus-theme-classic/codeTranslations/fa.json b/packages/docusaurus-theme-classic/codeTranslations/fa.json index 4858f18dd0df..bcfae0eaa795 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/fa.json +++ b/packages/docusaurus-theme-classic/codeTranslations/fa.json @@ -1,16 +1,4 @@ { - "theme.common.month.april": "April", - "theme.common.month.august": "August", - "theme.common.month.december": "December", - "theme.common.month.february": "February", - "theme.common.month.january": "January", - "theme.common.month.july": "July", - "theme.common.month.june": "June", - "theme.common.month.march": "March", - "theme.common.month.may": "May", - "theme.common.month.november": "November", - "theme.common.month.october": "October", - "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "بستن", "theme.CodeBlock.copied": "کپی شد", "theme.CodeBlock.copy": "کپی کردن", @@ -45,6 +33,18 @@ "theme.blog.tagTitle": "{nPosts} tagged with \"{tagName}\"", "theme.common.editThisPage": "ویرایش صفحه", "theme.common.headingLinkTitle": "لینک مستقیم به عنوان", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.common.skipToMainContent": "رفتن به مطلب اصلی", "theme.docs.paginator.navAriaLabel": "کنترل صفحه اسناد", "theme.docs.paginator.next": "بعدی", @@ -65,4 +65,4 @@ "theme.tags.tagsListLabel": ":برچسب ها", "theme.tags.tagsPageLink": "مشاهده تمام برچسب ها", "theme.tags.tagsPageTitle": "برچسب ها" -} +} \ No newline at end of file diff --git a/packages/docusaurus-theme-classic/codeTranslations/fr.json b/packages/docusaurus-theme-classic/codeTranslations/fr.json index dcd808d0cb5a..6fa2854f69a6 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/fr.json +++ b/packages/docusaurus-theme-classic/codeTranslations/fr.json @@ -1,16 +1,4 @@ { - "theme.common.month.april": "Avril", - "theme.common.month.august": "Août", - "theme.common.month.december": "Décembre", - "theme.common.month.february": "Février", - "theme.common.month.january": "Janvier", - "theme.common.month.july": "Juillet", - "theme.common.month.june": "Juin", - "theme.common.month.march": "Mars", - "theme.common.month.may": "Mai", - "theme.common.month.november": "Novembre", - "theme.common.month.october": "Octobre", - "theme.common.month.september": "Septembre", "theme.AnnouncementBar.closeButtonAriaLabel": "Fermer", "theme.CodeBlock.copied": "Copié", "theme.CodeBlock.copy": "Copier", @@ -45,6 +33,18 @@ "theme.blog.tagTitle": "{nPosts} taggés avec \"{tagName}\"", "theme.common.editThisPage": "Éditer cette page", "theme.common.headingLinkTitle": "Lien direct vers le titre", + "theme.common.month.april": "Avril", + "theme.common.month.august": "Août", + "theme.common.month.december": "Décembre", + "theme.common.month.february": "Février", + "theme.common.month.january": "Janvier", + "theme.common.month.july": "Juillet", + "theme.common.month.june": "Juin", + "theme.common.month.march": "Mars", + "theme.common.month.may": "Mai", + "theme.common.month.november": "Novembre", + "theme.common.month.october": "Octobre", + "theme.common.month.september": "Septembre", "theme.common.skipToMainContent": "Aller au contenu principal", "theme.docs.paginator.navAriaLabel": "Pagination des documents", "theme.docs.paginator.next": "Suivant", @@ -65,4 +65,4 @@ "theme.tags.tagsListLabel": "Tags:", "theme.tags.tagsPageLink": "Voir tous les tags", "theme.tags.tagsPageTitle": "Tags" -} +} \ No newline at end of file diff --git a/packages/docusaurus-theme-classic/codeTranslations/ru.json b/packages/docusaurus-theme-classic/codeTranslations/ru.json index 9f6681697cb8..7442c507e663 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/ru.json +++ b/packages/docusaurus-theme-classic/codeTranslations/ru.json @@ -1,16 +1,4 @@ { - "theme.common.month.april": "April", - "theme.common.month.august": "August", - "theme.common.month.december": "December", - "theme.common.month.february": "February", - "theme.common.month.january": "January", - "theme.common.month.july": "July", - "theme.common.month.june": "June", - "theme.common.month.march": "March", - "theme.common.month.may": "May", - "theme.common.month.november": "November", - "theme.common.month.october": "October", - "theme.common.month.september": "September", "theme.AnnouncementBar.closeButtonAriaLabel": "Закрыть", "theme.CodeBlock.copied": "Скопировано", "theme.CodeBlock.copy": "Скопировать", @@ -45,6 +33,18 @@ "theme.blog.tagTitle": "{nPosts} tagged with \"{tagName}\"", "theme.common.editThisPage": "Отредактировать эту страницу", "theme.common.headingLinkTitle": "Прямая ссылка на этот заголовок", + "theme.common.month.april": "April", + "theme.common.month.august": "August", + "theme.common.month.december": "December", + "theme.common.month.february": "February", + "theme.common.month.january": "January", + "theme.common.month.july": "July", + "theme.common.month.june": "June", + "theme.common.month.march": "March", + "theme.common.month.may": "May", + "theme.common.month.november": "November", + "theme.common.month.october": "October", + "theme.common.month.september": "September", "theme.common.skipToMainContent": "Перейти к основному содержимому", "theme.docs.paginator.navAriaLabel": "Навигация по странице документации", "theme.docs.paginator.next": "Следующая страница", @@ -65,4 +65,4 @@ "theme.tags.tagsListLabel": "Теги:", "theme.tags.tagsPageLink": "Посмотреть все теги", "theme.tags.tagsPageTitle": "Теги" -} +} \ No newline at end of file From 8968c775f2d1fe5f021b11d0cb69e954a0fab558 Mon Sep 17 00:00:00 2001 From: slorber Date: Fri, 26 Feb 2021 11:30:15 +0100 Subject: [PATCH 18/19] team page translation improvements --- .../src/components/TeamProfileCards/index.js | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/website/src/components/TeamProfileCards/index.js b/website/src/components/TeamProfileCards/index.js index d593d3cf691f..50c51bec3a58 100644 --- a/website/src/components/TeamProfileCards/index.js +++ b/website/src/components/TeamProfileCards/index.js @@ -9,6 +9,16 @@ import React from 'react'; import Translate from '@docusaurus/Translate'; import Link from '@docusaurus/Link'; +function WebsiteLink({to, children}) { + return ( + + {children || ( + website + )} + + ); +} + function TeamProfileCard({className, name, children, githubUrl, twitterUrl}) { return (
@@ -57,7 +67,7 @@ export function ActiveTeamRow() { - + Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 @@ -66,7 +76,7 @@ export function ActiveTeamRow() { name="Joel Marcey" githubUrl="https://github.com/JoelMarcey" twitterUrl="https://twitter.com/joelmarcey"> - + Docusaurus founder and now ever grateful Docusaurus cheerleader to those who actually write code for it. @@ -76,19 +86,13 @@ export function ActiveTeamRow() { githubUrl="https://github.com/slorber" twitterUrl="https://twitter.com/sebastienlorber"> - - website - - - ), + website: , devto: Dev.to, }}> { - 'React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. He writes regularly, on his {{website}} and {{devto}}.' + 'React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. He writes regularly, on his {website} and {devto}.' } @@ -113,14 +117,18 @@ export function HonoraryAlumniTeamRow() { name="Endilie Yacop Sucipto" githubUrl="https://github.com/endiliey" twitterUrl="https://twitter.com/endiliey"> - Maintainer @docusaurus · 🔥🔥🔥 + + Maintainer @docusaurus · 🔥🔥🔥 + - 🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes - docs and spams this world with many websites. + + 🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes + docs and spams this world with many websites. +
); From 86e6b9830ec2363018f9ca8ea38ceccfe4828e4e Mon Sep 17 00:00:00 2001 From: slorber Date: Fri, 26 Feb 2021 13:06:22 +0100 Subject: [PATCH 19/19] Add interpolation doc + improve i18n doc --- website/docs/docusaurus-core.md | 112 +++++++++++++++++++++---- website/docs/i18n/i18n-introduction.md | 7 +- website/docs/i18n/i18n-tutorial.md | 34 ++++++-- 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/website/docs/docusaurus-core.md b/website/docs/docusaurus-core.md index 50ffe6deb4b1..b9ea6e3c1fdb 100644 --- a/website/docs/docusaurus-core.md +++ b/website/docs/docusaurus-core.md @@ -125,9 +125,44 @@ const MyComponent = () => { }; ``` +### `` + +A simple interpolation component for text containing dynamic placeholders. + +The placeholders will be replaced with the provided dynamic values and JSX elements of your choice (strings, links, styled elements...). + +#### Props + +- `children`: text containing interpolation placeholders like `{placeholderName}` +- `values`: object containing interpolation placeholder values + +```jsx +import React from 'react'; +import Link from '@docusaurus/Link'; +import Interpolate from '@docusaurus/Interpolate'; + +export default function VisitMyWebsiteMessage() { + return ( + // highlight-start + + website + + ), + }}> + {'Hello, {firstName}! How are you? Take a look at my {website}'} + + // highlight-end + ); +} +``` + ### `` -When [localizing your site](./i18n/i18n-introduction.md), the `` component will allow providing **translation support to React components**, such as your homepage. +When [localizing your site](./i18n/i18n-introduction.md), the `` component will allow providing **translation support to React components**, such as your homepage. The `` component supports [interpolation](#interpolate). The translation strings will be extracted from your code with the [`docusaurus write-translations`](./cli.md#docusaurus-write-translations) CLI and create a `code.json` translation file in `website/i18n/`. @@ -135,15 +170,16 @@ The translation strings will be extracted from your code with the [`docusaurus w The `` props **must be hardcoded strings**. -It is **not possible to use variables**, or the extraction wouldn't work. +Apart the `values` prop used for interpolation, it is **not possible to use variables**, or the static extraction wouldn't work. ::: #### Props -- `children`: untranslated string in the default site locale` +- `children`: untranslated string in the default site locale (can contain [interpolation placeholders](#interpolate)) - `id`: optional value to use as key in JSON translation files - `description`: optional text to help the translator +- `values`: optional object containing interpolation placeholder values #### Example @@ -169,7 +205,9 @@ export default function Home() {
{/* highlight-start */} - My website content + + {'Welcome, {firstName}! How are you?'} + {/* highlight-end */}
@@ -378,19 +416,58 @@ const MyComponent = () => { ## Functions +### `interpolate` + +The imperative counterpart of the [``](#interpolate) component. + +#### Signature + +```ts +// Simple string interpolation +function interpolate(text: string, values: Record): string; + +// JSX interpolation +function interpolate( + text: string, + values: Record, +): ReactNode; +``` + +#### Example + +```jsx +// highlight-start +import {interpolate} from '@docusaurus/Interpolate'; +// highlight-end + +const message = interpolate('Welcome {firstName}', {firstName: 'Sébastien'}); +``` + ### `translate` -The imperative counterpart of the [``](#translate) component. +The imperative counterpart of the [``](#translate) component. Also supporting [placeholders interpolation](#interpolate). :::tip -Use the imperative API for the **rare cases** when a **component cannot be used**, such as: +Use the imperative API for the **rare cases** where a **component cannot be used**, such as: -- the `placeholder` props of form input - the page `title` metadata +- the `placeholder` props of form inputs +- the `aria-label` props for accessibility ::: +#### Signature + +```ts +function translate( + translation: {message: string; id?: string; description?: string}, + values: Record, +): string; +``` + +#### Example + ```jsx title="src/index.js" import React from 'react'; import Layout from '@theme/Layout'; @@ -406,16 +483,19 @@ export default function Home() { title={translate({message: 'My page meta title'})} // highlight-end > - diff --git a/website/docs/i18n/i18n-introduction.md b/website/docs/i18n/i18n-introduction.md index 3c67091be19a..6e33a992838e 100644 --- a/website/docs/i18n/i18n-introduction.md +++ b/website/docs/i18n/i18n-introduction.md @@ -5,7 +5,7 @@ sidebar_label: Introduction slug: /i18n/introduction --- -It is possible to translate a Docusaurus website through its internationalization support (abbreviated as [i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization)). +It is **easy to translate a Docusaurus website** with its internationalization ([i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization)) support. :::caution @@ -15,7 +15,7 @@ i18n is a new feature (released early 2021), please report any bug you find. ## Goals -This section should help you understand the design decisions behind the Docusaurus i18n support. +It is important to understand the **design decisions** behind the Docusaurus i18n support. For more context, you can read the initial [RFC](https://github.com/facebook/docusaurus/issues/3317) and [PR](https://github.com/facebook/docusaurus/pull/3325). @@ -27,13 +27,14 @@ The goals of the Docusaurus i18n system are: - **Flexible translation workflows**: based on Git (monorepo, forks or submodules), SaaS software, FTP... - **Flexible deployment options**: single or multiple domains. - **Modular**: allow plugin author to provide i18n support. -- **Low-overhead runtime**: static json/markdown content does not require a heavy i18n JS library. +- **Low-overhead runtime**: documentation is mostly static and does not require a heavy JS library or polyfills. - **Acceptable build-times**: allow building and deploying localized sites independently. - **Localize assets**: an image of your site might contain text that should be translated. - **No coupling**: not forced to use any SaaS, yet the integration is possible. - **Easy to use with [Crowdin](http://crowdin.com/)**: multiple Docusaurus v1 sites use Crowdin, and should be able to migrate to v2. - **Good SEO defaults**: setting useful SEO headers like [`hreflang`](https://developers.google.com/search/docs/advanced/crawling/localized-versions) for you. - **RTL support**: locales reading right-to-left (Arabic, Hebrew...) should be easy to use. +- **Default translations**: theme labels are translated for you in [many languages](https://github.com/facebook/docusaurus/tree/master/packages/docusaurus-theme-classic/codeTranslations). ### i18n goals (TODO) diff --git a/website/docs/i18n/i18n-tutorial.md b/website/docs/i18n/i18n-tutorial.md index 1cf830d2744b..3f9d2618ab98 100644 --- a/website/docs/i18n/i18n-tutorial.md +++ b/website/docs/i18n/i18n-tutorial.md @@ -65,7 +65,17 @@ Start your localized site in dev mode, using the locale of your choice: npm run start -- --locale fr ``` -Your site is accessible at **`http://localhost:3000/fr/`**, but **falls back to untranslated content**. +Your site is accessible at **`http://localhost:3000/fr/`** + +We haven't provided any translation, and the site is **mostly untranslated**. + +:::tip + +Docusaurus provides **default translations** for generic theme labels, such as "Next" and "Previous" for the pagination. + +Please help us complete those **[default translations](https://github.com/facebook/docusaurus/tree/master/packages/docusaurus-theme-classic/codeTranslations)**. + +::: :::caution @@ -94,6 +104,8 @@ Open the homepage, and use the [translation APIs](../docusaurus-core.md#translat ```jsx title="src/index.js" import React from 'react'; import Layout from '@theme/Layout'; +import Link from '@docusaurus/Link'; + // highlight-start import Translate, {translate} from '@docusaurus/Translate'; // highlight-end @@ -103,13 +115,19 @@ export default function Home() {

{/* highlight-start */} - - Welcome to my website - + Welcome to my website {/* highlight-end */}

+
+ {/* highlight-start */} + blog}}> + {'You can also visit my {blog}'} + + {/* highlight-end */} -
-
+
); } @@ -129,7 +147,9 @@ export default function Home() { :::caution -Docusaurus provides a **very simple and lightweight translation runtime**: documentation websites generally don't need advanced i18n features. +Docusaurus provides a **very small and lightweight translation runtime** on purpose, and only supports basic [placeholders interpolation](../docusaurus-core.md#interpolate), using a subset of the [ICU Message Format](https://formatjs.io/docs/core-concepts/icu-syntax/). + +Most documentation websites are generally **static** and don't need advanced i18n features (**plurals**, **genders**...). Use a library like [react-intl](https://www.npmjs.com/package/react-intl) for more advanced use-cases. :::