diff --git a/web/src/components/header.tsx b/web/src/components/header.tsx index 744d0f79..7f93f9b7 100644 --- a/web/src/components/header.tsx +++ b/web/src/components/header.tsx @@ -6,6 +6,7 @@ import { Localized } from '@fluent/react'; import logoURL from '../../img/cv-logo-one-color-black.svg'; import '../../css/header.css'; +import { useLocaleUrl } from '../urls'; import type { RootState } from '../types'; import LoginButton from './login-button'; @@ -15,31 +16,35 @@ type Props = { }; function NavItems({ authed, closeNavigation }: Props) { + // As the profile link is conditionally rendered we need to always use + // the hook first, as otherwise not all hooks will be rendered at all times. + const localizedProfileUrl = useLocaleUrl('/profile'); + return ( - + Home - + How-to - + Add - + Review - + Rejected Sentences - + My Sentences - + Statistics {authed && ( - + Profile )} diff --git a/web/src/components/home.tsx b/web/src/components/home.tsx index c273b64d..d0d4794e 100644 --- a/web/src/components/home.tsx +++ b/web/src/components/home.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Localized } from '@fluent/react'; +import { useLocaleUrl } from '../urls'; + import '../../css/home.css'; export default function Home() { @@ -29,7 +31,7 @@ export default function Home() {

- +

Collect sentences

@@ -39,7 +41,7 @@ export default function Home() {
- +

Review sentences

diff --git a/web/src/components/language-info.tsx b/web/src/components/language-info.tsx index 68098375..34fbd019 100644 --- a/web/src/components/language-info.tsx +++ b/web/src/components/language-info.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { Link, useRouteMatch } from 'react-router-dom'; +import { Link } from 'react-router-dom'; import { Localized } from '@fluent/react'; -import { getReviewUrl } from './review'; +import { useLocaleUrl, getReviewUrl } from '../urls'; type Props = { total: number; @@ -14,10 +14,6 @@ type Props = { nativeLanguageName: string; }; -type LanguageInfoRouteMatch = { - locale: string; -}; - const LanguageInfo = (props: Props) => { const { total, @@ -28,14 +24,15 @@ const LanguageInfo = (props: Props) => { languageName, nativeLanguageName, } = props; - const match = useRouteMatch(); - const totalSentences = total; const totalInReview = total - validated - rejected; const unreviewedSentencesByYou = unreviewedByYou; const validatedSentences = validated; const rejectedSentences = rejected; + const localizedAddUrl = useLocaleUrl('/add'); + const localizedReviewUrl = getReviewUrl(language); + return (

@@ -57,11 +54,11 @@ const LanguageInfo = (props: Props) => { , + reviewLink: , }} > - Review now! + Review now! )} @@ -69,11 +66,11 @@ const LanguageInfo = (props: Props) => { , + addLink: , }} > - Add more sentences now! + Add more sentences now! )} diff --git a/web/src/components/review.tsx b/web/src/components/review.tsx index 5c1a55b0..d622f358 100644 --- a/web/src/components/review.tsx +++ b/web/src/components/review.tsx @@ -9,6 +9,7 @@ import { reviewSentences, saveSkippedSentences, } from '../actions/sentences'; +import { useLocaleUrl, getReviewUrl } from '../urls'; import truthyFilter from '../truthyFilter'; import type { RootState, ReviewedState } from '../types'; @@ -16,12 +17,6 @@ import LanguageSelector from './language-selector'; import ReviewForm from './review-form'; import ReviewCriteria from './review-criteria'; -export const getReviewUrl = (locale: string, language: string | undefined) => { - const prefix = locale ? `/${locale}` : ''; - const languageToReview = language || ''; - return `${prefix}/review/${languageToReview}`; -}; - type ReviewRouteMatch = { language: string; locale: string; @@ -41,6 +36,8 @@ export default function Review() { const [language, setLanguage] = useState(match.params.language || ''); const [newlySkippedSentences, setNewlySkippedSentences] = useState([]); const dispatch = useDispatch(); + const localizedAddUrl = useLocaleUrl('/add'); + const localizedProfileUrl = useLocaleUrl('/profile'); // If user only has one language possible, use it. if (languages.length === 1 && languages[0] !== language) { @@ -60,12 +57,12 @@ export default function Review() { , + profileLink: , }} >

You have not selected any languages. Please go to your  - Profile to select languages. + Profile to select languages.

); @@ -73,7 +70,7 @@ export default function Review() { const onSelectLanguage = (language: string) => { setLanguage(language); - history.push(getReviewUrl(match.params.locale, language)); + history.push(getReviewUrl(language)); }; const onReviewed = (reviewedState: ReviewedState) => { @@ -141,12 +138,12 @@ export default function Review() { , + addLink: , }} >

No sentences to review.  - Add more sentences now! + Add more sentences now!

)} diff --git a/web/src/components/stats.tsx b/web/src/components/stats.tsx index 3a413d20..3e604d66 100644 --- a/web/src/components/stats.tsx +++ b/web/src/components/stats.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { Localized, useLocalization } from '@fluent/react'; +import { Localized } from '@fluent/react'; import { getStats } from '../actions/languages'; import truthyFilter from '../truthyFilter'; @@ -26,8 +26,6 @@ export default function Stats() { .map((lang) => allLanguages.find((extendedLanguage) => extendedLanguage.id === lang)) .filter(truthyFilter); - const { l10n } = useLocalization(); - return (
diff --git a/web/src/components/submit-form.tsx b/web/src/components/submit-form.tsx index 3938724a..cd81b83e 100644 --- a/web/src/components/submit-form.tsx +++ b/web/src/components/submit-form.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { Link } from 'react-router-dom'; import { Localized, useLocalization } from '@fluent/react'; +import { useLocaleUrl } from '../urls'; import type { Language, SubmissionFailures } from '../types'; import LanguageSelector from './language-selector'; import Sentence from './sentence'; @@ -54,6 +55,7 @@ export default function SubmitForm({ confirmed: false, }); const [language, setLanguage] = useState(firstLanguage ? firstLanguage.id : ''); + const localizedHowToUrl = useLocaleUrl('/how-to'); const handleInputChange = ( event: React.FormEvent | React.ChangeEvent @@ -253,11 +255,11 @@ export default function SubmitForm({ , + howToLink: , }} >

- Please check the guidelines. + Please check the guidelines.

diff --git a/web/src/urls.ts b/web/src/urls.ts new file mode 100644 index 00000000..e3d7d9f8 --- /dev/null +++ b/web/src/urls.ts @@ -0,0 +1,19 @@ +import { useRouteMatch } from 'react-router-dom'; + +type LocaleMatch = { locale: string }; + +export const getReviewUrl = (language: string | undefined) => { + const match = useRouteMatch(); + const locale = match?.params?.locale; + const prefix = locale ? `/${locale}` : ''; + const languageToReview = language || ''; + return `${prefix}/review/${languageToReview}`; +}; + +export const useLocaleUrl = (path: string) => { + const match = useRouteMatch(); + const locale = match?.params?.locale; + const prefix = locale ? `/${locale}` : ''; + const pathWithSlash = path.startsWith('/') ? path : `/${path}`; + return `${prefix}${pathWithSlash}`; +};