From e89a31a0f3c35f1496aac42728d62a3b86d96d92 Mon Sep 17 00:00:00 2001 From: lukas Date: Mon, 18 Dec 2023 08:52:27 +0100 Subject: [PATCH] Translate components --- public/locales/de.json | 99 +++++++++++++- public/locales/en.json | 99 +++++++++++++- src/app/components/Pdf-viewer/PdfViewer.tsx | 14 +- src/app/i18n.ts | 3 + .../room-notification/RoomNotification.jsx | 12 +- src/app/organisms/room/message/Message.tsx | 14 +- src/app/templates/auth/Auth.jsx | 127 ++++++++++-------- src/app/templates/client/Client.jsx | 13 +- 8 files changed, 301 insertions(+), 80 deletions(-) diff --git a/public/locales/de.json b/public/locales/de.json index 0d84c3107a..cc706c685e 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -1,6 +1,17 @@ { "common": { - "options": "Optionen" + "options": "Optionen", + "or": "oder" + }, + "Components": { + "Files": { + "download": "Herunterladen", + "failure_pdf": "Fehler beim Laden der PDF", + "retry": "Erneut Versuchen", + "previous": "Vorherige", + "jump_to_page": "Spring zu Seite", + "next": "Nächste" + } }, "Organisms": { "Welcome": { @@ -76,6 +87,19 @@ "ConfirmDialog": { "cancel": "Abbrechen" }, + "Message": { + "add_reaction": "Reaktion hinzufügen", + "reply": "Antworten", + "edit": "Bearbeiten", + "read_receipts": "Lesebestätigungen", + "view_source": "Quelle ansehen" + }, + "RoomNotification": { + "default": "Global", + "all_messages": "Alle Nachrichten", + "mentions_and_keywords": "Erwähnungen & Schlüsselwörter", + "mute": "Stummschalten" + }, "RoomOptions": { "title": "Optionen für {{room_name}}", "leave": { @@ -97,5 +121,78 @@ "settings": "Einstellungen", "leave": "Verlassen" } + }, + "Templates": { + "Auth": { + "loading_homeserver_list": "Lade Liste der Homeserver...", + "looking_for_homeserver": "Suche nach Homeserver...", + "connecting_to_homeserver": "Verbinde mit {{homeserver}}...", + "unable_to_connect": "Keine Verbindung möglich. Bitte prüfe deine Eingabe", + "username_taken": "Benutzername ist bereits vergeben", + "registration_in_progress": "Registrierung in Bearbeitung...", + "link_about": "Über", + "link_twitter": "Twitter", + "link_matrix": "Powered by Matrix", + "dont_have_an_account": "Du hast noch keinen Account?", + "already_have_an_account": "Du hast bereits einen Account?", + "register_link": "Registrieren", + "login_link": "Anmelden", + "redirecting": "Leite weiter...", + "login_in_progress": "Anmeldung in Bearbeitung...", + "bad_localpart_error": "Der Benutzername darf nur die Zeichen a-z, 0-9 oder '=_-./' enthalten", + "user_id_too_long_error": "Deine Benutzer-ID, einschließlich des Hostnamens, darf nicht mehr als 255 Zeichen lang sein.", + "bad_password_error": "Das Kennwort muss mindestens 1 Kleinbuchstaben, 1 Großbuchstaben, 1 Ziffer, 1 Sonderzeichen und 8-127 Zeichen (keine Leerzeichen) enthalten.", + "confirm_password_error": "Die Kennwörter stimmen nicht überein", + "bad_email_error": "Ungültige E-Mail-Adresse", + "invalid_password": "Ungültiges Kennwort", + "check_credentials": "Bitte prüfe deine Zugangsdaten", + "login_types": { + "username": "Benutzername", + "email": "E-Mail" + }, + "homeserver_form": { + "title": "Homeserver", + "header": "Liste der Homeserver" + }, + "login_form": { + "title": "Anmeldung", + "prompt_email": "E-Mail", + "prompt_username": "Benutzername", + "prompt_password": "Kennwort", + "login_button": "Anmelden" + }, + "register_form": { + "title": "Registrierung", + "prompt_email_required": "E-Mail (erforderlich)", + "prompt_email_optional": "E-Mail", + "prompt_username": "Benutzername", + "prompt_password": "Kennwort", + "prompt_confirm_password": "Kennwort bestätigen", + "register_button": "Registrieren" + }, + "terms_and_conditions": { + "title": "Den Bedingungen zustimmen", + "description": "Um die Registrierung abzuschließen, musst du den Nutzungsbedingungen zustimmen.", + "accept": "Ich stimme den Nutzungsbedingungen zu", + "submit_button": "Absenden" + }, + "validate_email": { + "title": "E-Mail verifizieren", + "continue_button": "Fortfahren", + "message": "Bitte prüfe dein E-Mail-Postfach {{email_address}} und validiere deine E-Mail-Adresse bevor du fortfährst" + }, + "captcha": { + "message": "Bitte markiere das folgende Feld um fortzufahren" + } + }, + "Client": { + "loading_messages": { + "default": "Aufwärmen", + "message_one": "Beinahe am Ziel...", + "message_two": "Sieht aus, als hättest du eine Menge Zeug aufzuwärmen!" + }, + "logout_prompt": "Abmeldung", + "clear_cache": "Zwischenspeicher löschen & neuladen" + } } } diff --git a/public/locales/en.json b/public/locales/en.json index 86ab77f635..a04a1c0d97 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -1,6 +1,17 @@ { "common": { - "options": "Options" + "options": "Options", + "or": "Or" + }, + "Components": { + "PDF": { + "download": "Download", + "failure": "Failed to load PDF", + "retry": "Retry", + "previous": "Previous", + "jump_to_page": "Jump To Page", + "next": "Next" + } }, "Organisms": { "Welcome": { @@ -76,6 +87,19 @@ "ConfirmDialog": { "cancel": "Cancel" }, + "Message": { + "add_reaction": "Add reaction", + "reply": "Reply", + "edit": "Edit", + "read_receipts": "Read receipts", + "view_source": "View source" + }, + "RoomNotification": { + "default": "Global", + "all_messages": "All messages", + "mentions_and_keywords": "Mentions & Keywords", + "mute": "Mute" + }, "RoomOptions": { "title": "Options for {{room_name}}", "leave": { @@ -97,5 +121,78 @@ "settings": "Settings", "leave": "Leave" } + }, + "Templates": { + "Auth": { + "loading_homeserver_list": "Loading homeserver list...", + "looking_for_homeserver": "Looking for homeserver...", + "connecting_to_homeserver": "Connecting to {{homeserver}}...", + "unable_to_connect": "Unable to connect. Please check your input", + "username_taken": "Username is already taken", + "registration_in_progress": "Registration in progress...", + "link_about": "About", + "link_twitter": "Twitter", + "link_matrix": "Powered by Matrix", + "dont_have_an_account": "Dont have an account?", + "already_have_an_account": "Already have an account?", + "register_link": "Register", + "login_link": "Login", + "redirecting": "Redirecting...", + "login_in_progress": "Login in progress...", + "bad_localpart_error": "Username can only contain characters a-z, 0-9, or '=_-./'", + "user_id_too_long_error": "Your user ID, including the hostname, can't be more than 255 characters long.", + "bad_password_error": "Password must contain at least 1 lowercase, 1 uppercase, 1 number, 1 non-alphanumeric character, 8-127 characters with no space.", + "confirm_password_error": "Passwords don't match.", + "bad_email_error": "Invalid email address", + "invalid_password": "Invalid password", + "check_credentials": "Please check your credentials", + "login_types": { + "username": "Username", + "email": "Email" + }, + "homeserver_form": { + "title": "Homeserver", + "header": "Homeserver list" + }, + "login_form": { + "title": "Login", + "prompt_email": "Email", + "prompt_username": "Username", + "prompt_password": "Password", + "login_button": "Login" + }, + "register_form": { + "title": "Register", + "prompt_email_required": "Email (Required)", + "prompt_email_optional": "Email", + "prompt_username": "Username", + "prompt_password": "Password", + "prompt_confirm_password": "Confirm password", + "register_button": "Register" + }, + "terms_and_conditions": { + "title": "Agree with terms", + "description": "In order to complete registration, you need to agree to the terms and conditions.", + "accept": "I accept Terms and Conditions", + "submit_button": "Submit" + }, + "validate_email": { + "title": "Verify email", + "continue_button": "Continue", + "message": "Please check your email {{email_address}} and validate before continuing further" + }, + "captcha": { + "message": "Pleace check the box below to proceed" + } + }, + "Client": { + "loading_messages": { + "default": "Heating up", + "message_one": "Almost there...", + "message_two": "Looks like you have a lot of stuff to heat up!" + }, + "logout_prompt": "Logout", + "clear_cache": "Clear cache & reload" + } } } diff --git a/src/app/components/Pdf-viewer/PdfViewer.tsx b/src/app/components/Pdf-viewer/PdfViewer.tsx index c440cce9b8..2904413bf6 100644 --- a/src/app/components/Pdf-viewer/PdfViewer.tsx +++ b/src/app/components/Pdf-viewer/PdfViewer.tsx @@ -19,6 +19,7 @@ import { as, config, } from 'folds'; +import { useTranslation } from 'react-i18next'; import FocusTrap from 'focus-trap-react'; import FileSaver from 'file-saver'; import * as css from './PdfViewer.css'; @@ -97,6 +98,7 @@ export const PdfViewer = as<'div', PdfViewerProps>( if (docState.status !== AsyncStatus.Success) return; setPageNo((n) => Math.min(n + 1, docState.data.numPages)); }; + const { t } = useTranslation(); return ( @@ -139,7 +141,7 @@ export const PdfViewer = as<'div', PdfViewerProps>( radii="300" before={} > - Download + {t('Components.Files.download')} @@ -147,7 +149,7 @@ export const PdfViewer = as<'div', PdfViewerProps>( {isLoading && } {isError && ( <> - Failed to load PDF + {t('Components.Files.failure_pdf')} )} @@ -183,7 +185,7 @@ export const PdfViewer = as<'div', PdfViewerProps>( onClick={handlePrevPage} aria-disabled={pageNo <= 1} > - Previous + {t('Components.Files.previous')} ( aria-label="Page Number" /> @@ -247,7 +249,7 @@ export const PdfViewer = as<'div', PdfViewerProps>( onClick={handleNextPage} aria-disabled={pageNo >= docState.data.numPages} > - Next + {t('Components.Files.next')} )} diff --git a/src/app/i18n.ts b/src/app/i18n.ts index 7a28a5e7cb..56df31ecc8 100644 --- a/src/app/i18n.ts +++ b/src/app/i18n.ts @@ -25,6 +25,9 @@ i18n backend: { loadPath: 'public/locales/{{lng}}.json', }, + react: { + useSuspense: false, + }, }); export default i18n; diff --git a/src/app/molecules/room-notification/RoomNotification.jsx b/src/app/molecules/room-notification/RoomNotification.jsx index 1c088e5f00..e048deac84 100644 --- a/src/app/molecules/room-notification/RoomNotification.jsx +++ b/src/app/molecules/room-notification/RoomNotification.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import PropTypes from 'prop-types'; import './RoomNotification.scss'; +import { useTranslation } from 'react-i18next'; import initMatrix from '../../../client/initMatrix'; import cons from '../../../client/state/cons'; @@ -16,19 +17,19 @@ import BellOffIC from '../../../../public/res/ic/outlined/bell-off.svg'; const items = [{ iconSrc: BellIC, - text: 'Global', + text: 'Molecules.RoomNotification.default', type: cons.notifs.DEFAULT, }, { iconSrc: BellRingIC, - text: 'All messages', + text: 'Molecules.RoomNotification.all_messages', type: cons.notifs.ALL_MESSAGES, }, { iconSrc: BellPingIC, - text: 'Mentions & Keywords', + text: 'Molecules.RoomNotification.mentions_and_keywords', type: cons.notifs.MENTIONS_AND_KEYWORDS, }, { iconSrc: BellOffIC, - text: 'Mute', + text: 'Molecules.RoomNotification.mute', type: cons.notifs.MUTE, }]; @@ -115,6 +116,7 @@ function useNotifications(roomId) { function RoomNotification({ roomId }) { const [activeType, setNotification] = useNotifications(roomId); + const { t } = useTranslation(); return (
@@ -127,7 +129,7 @@ function RoomNotification({ roomId }) { onClick={() => setNotification(item)} > - {item.text} + {t(item.text)} diff --git a/src/app/organisms/room/message/Message.tsx b/src/app/organisms/room/message/Message.tsx index 25d894f312..ed98becbb8 100644 --- a/src/app/organisms/room/message/Message.tsx +++ b/src/app/organisms/room/message/Message.tsx @@ -31,6 +31,7 @@ import React, { useCallback, useState, } from 'react'; +import { useTranslation } from 'react-i18next'; import FocusTrap from 'focus-trap-react'; import { useHover, useFocusWithin } from 'react-aria'; import { MatrixEvent, Room } from 'matrix-js-sdk'; @@ -180,6 +181,7 @@ export const MessageReadReceiptItem = as< setOpen(false); onClose?.(); }; + const { t } = useTranslation(); return ( <> @@ -208,7 +210,7 @@ export const MessageReadReceiptItem = as< aria-pressed={open} > - Read Receipts + {t('Molecules.Message.read_receipts')} @@ -257,6 +259,7 @@ export const MessageSourceCodeItem = as< setOpen(false); onClose?.(); }; + const { t } = useTranslation(); return ( <> @@ -290,7 +293,7 @@ export const MessageSourceCodeItem = as< aria-pressed={open} > - View Source + {t('Molecules.Message.view_source')} @@ -712,6 +715,7 @@ export const Message = as<'div', MessageProps>( const closeMenu = () => { setMenu(false); }; + const { t } = useTranslation(); return ( ( size="T300" truncate > - Add Reaction + {t('Molecules.Message.add_reaction')} )} @@ -858,7 +862,7 @@ export const Message = as<'div', MessageProps>( size="T300" truncate > - Reply + {t('Molecules.Message.reply')} {canEditEvent(mx, mEvent) && onEditId && ( @@ -878,7 +882,7 @@ export const Message = as<'div', MessageProps>( size="T300" truncate > - Edit Message + {t('Molecules.Message.edit')} )} diff --git a/src/app/templates/auth/Auth.jsx b/src/app/templates/auth/Auth.jsx index 7c21173605..40d74160b9 100644 --- a/src/app/templates/auth/Auth.jsx +++ b/src/app/templates/auth/Auth.jsx @@ -5,6 +5,7 @@ import './Auth.scss'; import ReCAPTCHA from 'react-google-recaptcha'; import { Formik } from 'formik'; +import { useTranslation, Trans } from 'react-i18next'; import * as auth from '../../../client/action/auth'; import cons from '../../../client/state/cons'; import { Debounce, getUrlPrams } from '../../../util/common'; @@ -27,15 +28,10 @@ import CinnySvg from '../../../../public/res/svg/cinny.svg'; import SSOButtons from '../../molecules/sso-buttons/SSOButtons'; const LOCALPART_SIGNUP_REGEX = /^[a-z0-9_\-.=/]+$/; -const BAD_LOCALPART_ERROR = 'Username can only contain characters a-z, 0-9, or \'=_-./\''; -const USER_ID_TOO_LONG_ERROR = 'Your user ID, including the hostname, can\'t be more than 255 characters long.'; const PASSWORD_STRENGHT_REGEX = /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[^\w\d\s:])([^\s]){8,127}$/; -const BAD_PASSWORD_ERROR = 'Password must contain at least 1 lowercase, 1 uppercase, 1 number, 1 non-alphanumeric character, 8-127 characters with no space.'; -const CONFIRM_PASSWORD_ERROR = 'Passwords don\'t match.'; const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; -const BAD_EMAIL_ERROR = 'Invalid email address'; function isValidInput(value, regex) { if (typeof regex === 'string') return regex === value; @@ -50,16 +46,19 @@ let searchingHs = null; function Homeserver({ onChange }) { const [hs, setHs] = useState(null); const [debounce] = useState(new Debounce()); - const [process, setProcess] = useState({ isLoading: true, message: 'Loading homeserver list...' }); + + const { t } = useTranslation(); + + const [process, setProcess] = useState({ isLoading: true, message: t('Templates.Auth.loading_homeserver_list') }); const hsRef = useRef(); const setupHsConfig = async (servername) => { - setProcess({ isLoading: true, message: 'Looking for homeserver...' }); + setProcess({ isLoading: true, message: t('Templates.Auth.looking_for_homeserver') }); let baseUrl = null; baseUrl = await getBaseUrl(servername); if (searchingHs !== servername) return; - setProcess({ isLoading: true, message: `Connecting to ${baseUrl}...` }); + setProcess({ isLoading: true, message: t('Templates.Auth.connecting_to_homeserver', { homeserver: baseUrl }) }); const tempClient = auth.createTemporaryClient(baseUrl); Promise.allSettled([tempClient.loginFlows(), tempClient.register()]) @@ -74,7 +73,7 @@ function Homeserver({ onChange }) { }).catch(() => { if (searchingHs !== servername) return; onChange(null); - setProcess({ isLoading: false, error: 'Unable to connect. Please check your input.' }); + setProcess({ isLoading: false, error: t('Templates.Auth.unable_to_connect') }); }); }; @@ -118,14 +117,14 @@ function Homeserver({ onChange }) { onChange={handleHsInput} value={hs?.selected} forwardRef={hsRef} - label="Homeserver" + label={t('Templates.Auth.homeserver_form.title')} disabled={hs === null || !hs.allowCustom} /> ( <> - Homeserver list + {t('Templates.Auth.homeserver_form.header')} { hs?.list.map((hsName) => ( flow.type === 'm.login.password')[0]; const ssoProviders = loginFlow?.filter((flow) => flow.type === 'm.login.sso')[0]; @@ -173,7 +173,7 @@ function Login({ loginFlow, baseUrl }) { const validator = (values) => { const errors = {}; if (typeIndex === 1 && values.email.length > 0 && !isValidInput(values.email, EMAIL_REGEX)) { - errors.email = BAD_EMAIL_ERROR; + errors.email = t('Templates.Auth.bad_email_error'); } return errors; }; @@ -196,7 +196,7 @@ function Login({ loginFlow, baseUrl }) { window.location.reload(); }).catch((error) => { let msg = error.message; - if (msg === 'Unknown message') msg = 'Please check your credentials'; + if (msg === 'Unknown message') msg = t('Templates.Auth.check_credentials'); actions.setErrors({ password: msg === 'Invalid password' ? msg : undefined, other: msg !== 'Invalid password' ? msg : undefined, @@ -208,7 +208,7 @@ function Login({ loginFlow, baseUrl }) { return ( <>
- Login + {t('Templates.Auth.login_form.title')} {isPassword && ( ( <> - {isSubmitting && } + {isSubmitting && }
- {typeIndex === 0 && } + {typeIndex === 0 && } {errors.username && {errors.username}} - {typeIndex === 1 && } + {typeIndex === 1 && } {errors.email && {errors.email}}
- + setPassVisible(!passVisible)} src={passVisible ? EyeIC : EyeBlindIC} size="extra-small" />
{errors.password && {errors.password}} {errors.other && {errors.other}}
- +
)} )} - {ssoProviders && isPassword && OR} + {ssoProviders && isPassword && {t('common.or')}} {ssoProviders && ( { const errors = {}; - if (values.username.list > 255) errors.username = USER_ID_TOO_LONG_ERROR; + if (values.username.list > 255) errors.username = t('Templates.Auth.user_id_too_long_error'); if (values.username.length > 0 && !isValidInput(values.username, LOCALPART_SIGNUP_REGEX)) { - errors.username = BAD_LOCALPART_ERROR; + errors.username = t('Templates.Auth.bad_localpart_error'); } if (values.password.length > 0 && !isValidInput(values.password, PASSWORD_STRENGHT_REGEX)) { - errors.password = BAD_PASSWORD_ERROR; + errors.password = t('Templates.Auth.bad_password_error'); } if (values.confirmPassword.length > 0 && !isValidInput(values.confirmPassword, values.password)) { - errors.confirmPassword = CONFIRM_PASSWORD_ERROR; + errors.confirmPassword = t('Templates.Auth.confirm_password_error'); } if (values.email.length > 0 && !isValidInput(values.email, EMAIL_REGEX)) { - errors.email = BAD_EMAIL_ERROR; + errors.email = t('Templates.Auth.bad_email_error'); } return errors; }; @@ -335,7 +337,7 @@ function Register({ registerInfo, loginFlow, baseUrl }) { return tempClient.isUsernameAvailable(values.username) .then(async (isAvail) => { if (!isAvail) { - actions.setErrors({ username: 'Username is already taken' }); + actions.setErrors({ username: t('Templates.Auth.username_taken') }); actions.setSubmitting(false); return; } @@ -349,12 +351,12 @@ function Register({ registerInfo, loginFlow, baseUrl }) { } sid = result.sid; } - setProcess({ type: 'processing', message: 'Registration in progress....' }); + setProcess({ type: 'processing', message: t('Templates.Auth.registration_in_progress') }); actions.setSubmitting(false); }).catch((err) => { const msg = err.message || err.error; if (['M_USER_IN_USE', 'M_INVALID_USERNAME', 'M_EXCLUSIVE'].indexOf(err.errcode) > -1) { - actions.setErrors({ username: err.errcode === 'M_USER_IN_USE' ? 'Username is already taken' : msg }); + actions.setErrors({ username: err.errcode === 'M_USER_IN_USE' ? t('Templates.Auth.username_taken') : msg }); } else if (msg) actions.setErrors({ other: msg }); actions.setSubmitting(false); @@ -409,7 +411,7 @@ function Register({ registerInfo, loginFlow, baseUrl }) { session, }); if (d.done) refreshWindow(); - else setProcess({ type: 'processing', message: 'Registration in progress...' }); + else setProcess({ type: 'processing', message: t('Templates.Auth.registration_in_progress') }); }; const handleTerms = async () => { const [username, password] = getInputs(); @@ -418,7 +420,7 @@ function Register({ registerInfo, loginFlow, baseUrl }) { session, }); if (d.done) refreshWindow(); - else setProcess({ type: 'processing', message: 'Registration in progress...' }); + else setProcess({ type: 'processing', message: t('Templates.Auth.registration_in_progress') }); }; const handleEmailVerify = async () => { const [username, password] = getInputs(); @@ -429,17 +431,17 @@ function Register({ registerInfo, loginFlow, baseUrl }) { session, }); if (d.done) refreshWindow(); - else setProcess({ type: 'processing', message: 'Registration in progress...' }); + else setProcess({ type: 'processing', message: t('Templates.Auth.registration_in_progress') }); }; return ( <> {process.type === 'processing' && } - {process.type === 'm.login.recaptcha' && } + {process.type === 'm.login.recaptcha' && } {process.type === 'm.login.terms' && } {process.type === 'm.login.email.identity' && }
- {!isDisabled && Register} + {!isDisabled && {t('Templates.Auth.register_form.title')}} {isDisabled && {registerInfo.error}}
{!isDisabled && ( @@ -452,25 +454,25 @@ function Register({ registerInfo, loginFlow, baseUrl }) { values, errors, handleChange, handleSubmit, isSubmitting, }) => ( <> - {process.type === undefined && isSubmitting && } + {process.type === undefined && isSubmitting && }
- + {errors.username && {errors.username}}
- + setPassVisible(!passVisible)} src={passVisible ? EyeIC : EyeBlindIC} size="extra-small" />
{errors.password && {errors.password}}
- + setCPassVisible(!cPassVisible)} src={cPassVisible ? EyeIC : EyeBlindIC} size="extra-small" />
{errors.confirmPassword && {errors.confirmPassword}} - {isEmail && } + {isEmail && } {errors.email && {errors.email}} {errors.other && {errors.other}}
- +
@@ -498,6 +500,7 @@ Register.propTypes = { function AuthCard() { const [hsConfig, setHsConfig] = useState(null); const [type, setType] = useState('login'); + const { t } = useTranslation(); const handleHsChange = (info) => { console.log(info); @@ -520,13 +523,13 @@ function AuthCard() { )} { hsConfig !== null && ( - {`${(type === 'login' ? 'Don\'t have' : 'Already have')} an account?`} + {t(type === 'login' ? 'Templates.Auth.dont_have_an_account' : 'Templates.Auth.already_have_an_account')} )} @@ -536,6 +539,7 @@ function AuthCard() { function Auth() { const [loginToken, setLoginToken] = useState(getUrlPrams('loginToken')); + const { t } = useTranslation(); useEffect(async () => { if (!loginToken) return; @@ -558,7 +562,7 @@ function Auth() {
- {loginToken && } + {loginToken && } {!loginToken && ( @@ -624,21 +628,26 @@ Recaptcha.propTypes = { }; function Terms({ url, onSubmit }) { + const { t } = useTranslation(); + return (
{ e.preventDefault(); onSubmit(); }}>
- Agree with terms + {t('Templates.Auth.terms_and_conditions.title')}
- In order to complete registration, you need to agree to the terms and conditions. + {t('Templates.Auth.terms_and_conditions.description')}
- {'I accept '} - Terms and Conditions + }} + />
- +
@@ -650,18 +659,22 @@ Terms.propTypes = { }; function EmailVerify({ email, onContinue }) { + const { t } = useTranslation(); return (
- Verify email + {t('Templates.Auth.validate_email.title')}
- {'Please check your email '} - {`(${email})`} - {' and validate before continuing further.'} + }} + />
- +
); @@ -681,4 +694,4 @@ ProcessWrapper.propTypes = { children: PropTypes.node.isRequired, }; -export default Auth; +export default Auth; \ No newline at end of file diff --git a/src/app/templates/client/Client.jsx b/src/app/templates/client/Client.jsx index e9be6b16eb..78df5a29ce 100644 --- a/src/app/templates/client/Client.jsx +++ b/src/app/templates/client/Client.jsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import './Client.scss'; +import { useTranslation } from 'react-i18next'; import { initHotkeys } from '../../../client/event/hotkeys'; import { initRoomListListener } from '../../../client/event/roomList'; @@ -37,9 +38,11 @@ function SystemEmojiFeature() { function Client() { const [isLoading, changeLoading] = useState(true); - const [loadingMsg, setLoadingMsg] = useState('Heating up'); + const [loadingMsg, setLoadingMsg] = useState('Templates.Client.loading_messages.default'); const classNameHidden = 'client__item-hidden'; + const { t } = useTranslation(); + const navWrapperRef = useRef(null); const roomWrapperRef = useRef(null); @@ -66,7 +69,7 @@ function Client() { changeLoading(true); let counter = 0; const iId = setInterval(() => { - const msgList = ['Almost there...', 'Looks like you have a lot of stuff to heat up!']; + const msgList = ['Templates.Client.loading_messages.message_one', 'Templates.Client.loading_messages.message_two']; if (counter === msgList.length - 1) { setLoadingMsg(msgList[msgList.length - 1]); clearInterval(iId); @@ -93,9 +96,9 @@ function Client() { content={ <> initMatrix.clearCacheAndReload()}> - Clear cache & reload + {t('Templates.Client.clear_cache')} - initMatrix.logout()}>Logout + initMatrix.logout()}>{t('Templates.Client.logout_prompt')} } render={(toggle) => ( @@ -105,7 +108,7 @@ function Client() {
- {loadingMsg} + {t(loadingMsg)}