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 (
-
+
-
+
-
+
-
+
-
+
-
+
-
+
{authed && (
-
+
)}
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}`;
+};