{menuItems.map((item) => (
))}
@@ -184,7 +154,7 @@ export function Settings({ initialPage, requestClose }: SettingsProps) {
before={
}
onClick={() => setLogout(true)}
>
-
Logout
+
{t('Settings.logout')}
{logout && (
}>
diff --git a/src/app/features/settings/about/About.tsx b/src/app/features/settings/about/About.tsx
index 19b29398..14cf50bf 100644
--- a/src/app/features/settings/about/About.tsx
+++ b/src/app/features/settings/about/About.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { useTranslation } from 'react-i18next';
import { Box, Text, IconButton, Icon, Icons, Scroll, Button, config, toRem } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { SequenceCard } from '../../../components/sequence-card';
@@ -12,6 +13,7 @@ type AboutProps = {
requestClose: () => void;
};
export function About({ requestClose }: AboutProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
return (
@@ -20,7 +22,7 @@ export function About({ requestClose }: AboutProps) {
- About
+ {t('Settings.about_title')}
@@ -48,13 +50,13 @@ export function About({ requestClose }: AboutProps) {
Vojo
v4.11.1
- Yet another matrix client.
+ {t('Settings.about_tagline')}
- Options
+ {t('Settings.options')}
clearCacheAndReload(mx)}
@@ -73,14 +75,14 @@ export function About({ requestClose }: AboutProps) {
radii="300"
outlined
>
- Clear Cache
+ {t('Settings.clear_cache')}
}
/>
- Credits
+ {t('Settings.credits')}
void;
};
export function Account({ requestClose }: AccountProps) {
+ const { t } = useTranslation();
return (
- Account
+ {t('Settings.account_title')}
diff --git a/src/app/features/settings/account/ContactInfo.tsx b/src/app/features/settings/account/ContactInfo.tsx
index cfde7e29..4a06b2a8 100644
--- a/src/app/features/settings/account/ContactInfo.tsx
+++ b/src/app/features/settings/account/ContactInfo.tsx
@@ -1,5 +1,6 @@
import React, { useCallback, useEffect } from 'react';
import { Box, Text, Chip } from 'folds';
+import { useTranslation } from 'react-i18next';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile';
@@ -7,6 +8,7 @@ import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
export function ContactInformation() {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const [threePIdsState, loadThreePIds] = useAsyncCallback(
useCallback(() => mx.getThreePids(), [mx])
@@ -22,14 +24,14 @@ export function ContactInformation() {
return (
- Contact Information
+ {t('Settings.contact_info')}
-
+
{emailIds?.map((email) => (
diff --git a/src/app/features/settings/account/IgnoredUserList.tsx b/src/app/features/settings/account/IgnoredUserList.tsx
index 98db9459..5b0c1f56 100644
--- a/src/app/features/settings/account/IgnoredUserList.tsx
+++ b/src/app/features/settings/account/IgnoredUserList.tsx
@@ -1,5 +1,6 @@
import React, { ChangeEventHandler, FormEventHandler, useCallback, useState } from 'react';
import { Box, Button, Chip, Icon, IconButton, Icons, Input, Spinner, Text, config } from 'folds';
+import { useTranslation } from 'react-i18next';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile';
@@ -10,6 +11,7 @@ import { useIgnoredUsers } from '../../../hooks/useIgnoredUsers';
import { useAlive } from '../../../hooks/useAlive';
function IgnoreUserInput({ userList }: { userList: string[] }) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const [userId, setUserId] = useState('');
const alive = useAlive();
@@ -89,7 +91,7 @@ function IgnoreUserInput({ userList }: { userList: string[] }) {
disabled={ignoring}
>
{ignoring && }
- Block
+ {t('Settings.block')}
);
@@ -129,12 +131,13 @@ function IgnoredUserChip({ userId, userList }: { userId: string; userList: strin
}
export function IgnoredUserList() {
+ const { t } = useTranslation();
const ignoredUsers = useIgnoredUsers();
return (
- Blocked Users
+ {t('Settings.blocked_users')}
{ignoredUsers.length > 0 && (
- Users
+ {t('Settings.users')}
{ignoredUsers.map((userId) => (
diff --git a/src/app/features/settings/account/MatrixId.tsx b/src/app/features/settings/account/MatrixId.tsx
index 0c06a75d..c8fea158 100644
--- a/src/app/features/settings/account/MatrixId.tsx
+++ b/src/app/features/settings/account/MatrixId.tsx
@@ -1,5 +1,6 @@
import React from 'react';
import { Box, Text, Chip } from 'folds';
+import { useTranslation } from 'react-i18next';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
@@ -7,12 +8,13 @@ import { SettingTile } from '../../../components/setting-tile';
import { copyToClipboard } from '../../../utils/dom';
export function MatrixId() {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const userId = mx.getUserId()!;
return (
- Matrix ID
+ {t('Settings.matrix_id')}
copyToClipboard(userId)}>
- Copy
+ {t('Settings.copy')}
}
/>
diff --git a/src/app/features/settings/account/Profile.tsx b/src/app/features/settings/account/Profile.tsx
index e982a799..e68dfd21 100644
--- a/src/app/features/settings/account/Profile.tsx
+++ b/src/app/features/settings/account/Profile.tsx
@@ -25,6 +25,7 @@ import {
Spinner,
} from 'folds';
import FocusTrap from 'focus-trap-react';
+import { useTranslation } from 'react-i18next';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile';
@@ -49,6 +50,7 @@ type ProfileProps = {
userId: string;
};
function ProfileAvatar({ profile, userId }: ProfileProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication();
const capabilities = useCapabilities();
@@ -91,7 +93,7 @@ function ProfileAvatar({ profile, userId }: ProfileProps) {
- Avatar
+ {t('Settings.avatar')}
}
after={
@@ -123,7 +125,7 @@ function ProfileAvatar({ profile, userId }: ProfileProps) {
radii="300"
disabled={disableSetAvatar}
>
- Upload
+ {t('Settings.upload')}
{avatarUrl && (
)}
@@ -183,7 +185,7 @@ function ProfileAvatar({ profile, userId }: ProfileProps) {
size="500"
>
- Remove Avatar
+ {t('Settings.remove_avatar')}
setAlertRemove(false)} radii="300">
@@ -191,10 +193,10 @@ function ProfileAvatar({ profile, userId }: ProfileProps) {
- Are you sure you want to remove profile avatar?
+ {t('Settings.remove_avatar_confirm')}
@@ -206,6 +208,7 @@ function ProfileAvatar({ profile, userId }: ProfileProps) {
}
function ProfileDisplayName({ profile, userId }: ProfileProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const capabilities = useCapabilities();
const disableSetDisplayname = capabilities['m.set_displayname']?.enabled === false;
@@ -248,7 +251,7 @@ function ProfileDisplayName({ profile, userId }: ProfileProps) {
- Display Name
+ {t('Settings.display_name')}
}
>
@@ -295,7 +298,7 @@ function ProfileDisplayName({ profile, userId }: ProfileProps) {
type="submit"
>
{changingDisplayName && }
- Save
+ {t('Settings.save')}
@@ -304,13 +307,14 @@ function ProfileDisplayName({ profile, userId }: ProfileProps) {
}
export function Profile() {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const userId = mx.getUserId()!;
const profile = useUserProfile(userId);
return (
- Profile
+ {t('Settings.profile')}
void;
};
export function AccountData({ expand, onExpandToggle, onSelect }: AccountDataProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const [accountDataTypes, setAccountDataKeys] = useState(() =>
Array.from(mx.store.accountData.keys())
@@ -27,7 +29,7 @@ export function AccountData({ expand, onExpandToggle, onSelect }: AccountDataPro
return (
- Account Data
+ {t('Settings.account_data')}
onExpandToggle(!expand)}
@@ -49,15 +51,15 @@ export function AccountData({ expand, onExpandToggle, onSelect }: AccountDataPro
}
>
- {expand ? 'Collapse' : 'Expand'}
+ {expand ? t('Settings.collapse') : t('Settings.expand')}
}
/>
{expand && (
- Events
- Total: {accountDataTypes.length}
+ {t('Settings.events')}
+ {t('Settings.total', { count: accountDataTypes.length })}
diff --git a/src/app/features/settings/developer-tools/DevelopTools.tsx b/src/app/features/settings/developer-tools/DevelopTools.tsx
index a3f04567..de6f202e 100644
--- a/src/app/features/settings/developer-tools/DevelopTools.tsx
+++ b/src/app/features/settings/developer-tools/DevelopTools.tsx
@@ -1,4 +1,5 @@
import React, { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Button } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { SequenceCard } from '../../../components/sequence-card';
@@ -18,6 +19,7 @@ type DeveloperToolsProps = {
requestClose: () => void;
};
export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const [developerTools, setDeveloperTools] = useSetting(settingsAtom, 'developerTools');
const [expand, setExpend] = useState(false);
@@ -47,7 +49,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
- Developer Tools
+ {t('Settings.devtools_title')}
@@ -62,7 +64,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
- Options
+ {t('Settings.options')}
@@ -101,7 +103,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
radii="300"
outlined
>
- Copy
+ {t('Settings.copy')}
}
/>
diff --git a/src/app/features/settings/devices/DeviceTile.tsx b/src/app/features/settings/devices/DeviceTile.tsx
index 71b684f5..601da394 100644
--- a/src/app/features/settings/devices/DeviceTile.tsx
+++ b/src/app/features/settings/devices/DeviceTile.tsx
@@ -18,6 +18,7 @@ import {
import { CryptoApi } from 'matrix-js-sdk/lib/crypto-api';
import FocusTrap from 'focus-trap-react';
import { IMyDevice, MatrixError } from 'matrix-js-sdk';
+import { useTranslation } from 'react-i18next';
import { SettingTile } from '../../../components/setting-tile';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { timeDayMonYear, timeHourMinute, today, yesterday } from '../../../utils/time';
@@ -43,17 +44,18 @@ export function DeviceTilePlaceholder() {
}
function DeviceActiveTime({ ts }: { ts: number }) {
+ const { t } = useTranslation();
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
return (
- {'Last activity: '}
+ {t('Settings.last_activity')}
<>
- {today(ts) && 'Today'}
- {yesterday(ts) && 'Yesterday'}
+ {today(ts) && t('Settings.today')}
+ {yesterday(ts) && t('Settings.yesterday')}
{!today(ts) && !yesterday(ts) && timeDayMonYear(ts, dateFormatString)}{' '}
{timeHourMinute(ts, hour24Clock)}
>
@@ -62,16 +64,17 @@ function DeviceActiveTime({ ts }: { ts: number }) {
}
function DeviceDetails({ device }: { device: IMyDevice }) {
+ const { t } = useTranslation();
return (
<>
{typeof device.device_id === 'string' && (
- Device ID: {device.device_id}
+ {t('Settings.device_id')}{device.device_id}
)}
{typeof device.last_seen_ip === 'string' && (
- IP Address: {device.last_seen_ip}
+ {t('Settings.ip_address')}{device.last_seen_ip}
)}
>
@@ -82,6 +85,7 @@ type DeviceKeyDetailsProps = {
crypto: CryptoApi;
};
export function DeviceKeyDetails({ crypto }: DeviceKeyDetailsProps) {
+ const { t } = useTranslation();
const [keysState, loadKeys] = useAsyncCallback(
useCallback(() => {
const keys = crypto.getOwnDeviceKeys();
@@ -97,8 +101,8 @@ export function DeviceKeyDetails({ crypto }: DeviceKeyDetailsProps) {
return (
- Device Key:{' '}
- {keysState.status === AsyncStatus.Success ? keysState.data.ed25519 : 'loading...'}
+ {t('Settings.device_key')}
+ {keysState.status === AsyncStatus.Success ? keysState.data.ed25519 : t('Settings.loading')}
);
}
@@ -110,6 +114,7 @@ type DeviceRenameProps = {
refreshDeviceList: () => Promise;
};
function DeviceRename({ device, onCancel, onRename, refreshDeviceList }: DeviceRenameProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const [renameState, rename] = useAsyncCallback(
@@ -145,7 +150,7 @@ function DeviceRename({ device, onCancel, onRename, refreshDeviceList }: DeviceR
return (
- Device Name
+ {t('Settings.device_name')}
}
>
- Save
+ {t('Settings.save')}
@@ -189,13 +194,14 @@ function DeviceRename({ device, onCancel, onRename, refreshDeviceList }: DeviceR
{renameState.error.message}
) : (
- Device names are visible to public.
+ {t('Settings.device_name_public')}
)}
);
}
export function DeviceLogoutBtn() {
+ const { t } = useTranslation();
const [prompt, setPrompt] = useState(false);
const handleClose = () => setPrompt(false);
@@ -203,7 +209,7 @@ export function DeviceLogoutBtn() {
return (
<>
setPrompt(true)}>
- Logout
+ {t('Settings.logout')}
{prompt && (
}>
@@ -236,6 +242,7 @@ export function DeviceDeleteBtn({
onDeleteToggle,
disabled,
}: DeviceDeleteBtnProps) {
+ const { t } = useTranslation();
return deleted ? (
onDeleteToggle(deviceId)}
disabled={disabled}
>
- Undo
+ {t('Settings.undo')}
) : (
setEdit(true)}
disabled={disabled}
>
- Edit
+ {t('Settings.edit')}
)}
diff --git a/src/app/features/settings/devices/Devices.tsx b/src/app/features/settings/devices/Devices.tsx
index c957ab31..83a9e8d9 100644
--- a/src/app/features/settings/devices/Devices.tsx
+++ b/src/app/features/settings/devices/Devices.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { useTranslation } from 'react-i18next';
import { Box, Text, IconButton, Icon, Icons, Scroll } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { SequenceCard } from '../../../components/sequence-card';
@@ -40,6 +41,7 @@ type DevicesProps = {
requestClose: () => void;
};
export function Devices({ requestClose }: DevicesProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const crypto = mx.getCrypto();
const crossSigningActive = useCrossSigningActive();
@@ -70,7 +72,7 @@ export function Devices({ requestClose }: DevicesProps) {
- Devices
+ {t('Settings.devices_title')}
@@ -85,7 +87,7 @@ export function Devices({ requestClose }: DevicesProps) {
- Security
+ {t('Settings.security')}
@@ -113,7 +115,7 @@ export function Devices({ requestClose }: DevicesProps) {
- Current
+ {t('Settings.current')}
{currentDevice ? (
(
<>
- New Password
+ {t('Settings.new_password')}
- Confirm Password
+ {t('Settings.confirm_password')}
: undefined}
>
- Export
+ {t('Settings.export')}
@@ -122,13 +124,14 @@ function ExportKeys() {
}
function ExportKeysTile() {
+ const { t } = useTranslation();
const [expand, setExpand] = useState(false);
return (
<>
@@ -160,6 +163,7 @@ type ImportKeysProps = {
onDone?: () => void;
};
function ImportKeys({ file, onDone }: ImportKeysProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const alive = useAlive();
@@ -209,7 +213,7 @@ function ImportKeys({ file, onDone }: ImportKeysProps) {
- Password
+ {t('Settings.password')}
: undefined}
>
- Decrypt
+ {t('Settings.decrypt')}
@@ -246,6 +250,7 @@ function ImportKeys({ file, onDone }: ImportKeysProps) {
}
function ImportKeysTile() {
+ const { t } = useTranslation();
const [file, setFile] = useState();
const pickFile = useFilePicker(setFile);
@@ -256,8 +261,8 @@ function ImportKeysTile() {
return (
<>
{file ? (
@@ -288,7 +293,7 @@ function ImportKeysTile() {
before={}
>
- Import
+ {t('Settings.import')}
)}
@@ -301,9 +306,10 @@ function ImportKeysTile() {
}
export function LocalBackup() {
+ const { t } = useTranslation();
return (
- Local Backup
+ {t('Settings.local_backup')}
0 ? (
<>
- Others
+ {t('Settings.others')}
{authMetadata && (
- Open
+ {t('Settings.open')}
}
/>
@@ -198,11 +200,11 @@ export function OtherDevices({ devices, refreshDeviceList, showVerification }: O
{deleteError ? (
- Failed to logout devices! Please try again. {deleteError.message}
+ {t('Settings.delete_devices_error', { message: deleteError.message })}
) : (
- Logout from selected devices. ({deleted.size} selected)
+ {t('Settings.delete_devices_confirm', { count: deleted.size })}
)}
{authData && (
@@ -210,7 +212,7 @@ export function OtherDevices({ devices, refreshDeviceList, showVerification }: O
authData={authData}
unsupported={() => (
- Authentication steps to perform this action are not supported by client.
+ {t('Settings.delete_devices_unsupported')}
)}
>
@@ -234,7 +236,7 @@ export function OtherDevices({ devices, refreshDeviceList, showVerification }: O
disabled={deleting}
onClick={handleCancelDelete}
>
- Cancel
+ {t('Settings.cancel')}
}
onClick={() => deleteDevices()}
>
- Logout
+ {t('Settings.logout')}
diff --git a/src/app/features/settings/devices/Verification.tsx b/src/app/features/settings/devices/Verification.tsx
index 6c7eab17..a7b3211c 100644
--- a/src/app/features/settings/devices/Verification.tsx
+++ b/src/app/features/settings/devices/Verification.tsx
@@ -19,6 +19,7 @@ import {
MenuItem,
} from 'folds';
import FocusTrap from 'focus-trap-react';
+import { useTranslation } from 'react-i18next';
import { CryptoApi, VerificationRequest } from 'matrix-js-sdk/lib/crypto-api';
import { VerificationStatus } from '../../../hooks/useDeviceVerificationStatus';
import { InfoCard } from '../../../components/info-card';
@@ -44,6 +45,7 @@ export function VerificationStatusBadge({
verificationStatus,
otherUnverifiedCount,
}: VerificationStatusBadgeProps) {
+ const { t } = useTranslation();
if (
verificationStatus === VerificationStatus.Unknown ||
typeof otherUnverifiedCount !== 'number'
@@ -53,7 +55,7 @@ export function VerificationStatusBadge({
if (verificationStatus === VerificationStatus.Unverified) {
return (
- Unverified
+ {t('Settings.unverified')}
);
}
@@ -61,36 +63,37 @@ export function VerificationStatusBadge({
if (otherUnverifiedCount > 0) {
return (
- {otherUnverifiedCount} Unverified
+ {t('Settings.unverified_count', { count: otherUnverifiedCount })}
);
}
return (
- Verified
+ {t('Settings.verified')}
);
}
function LearnStartVerificationFromOtherDevice() {
+ const { t } = useTranslation();
return (
- Steps to verify from other device.
+ {t('Settings.verify_steps_title')}
- - Open your other verified device.
+ - {t('Settings.verify_step_1')}
-
- Open Settings.
+ Open {t('Settings.verify_step_2_settings')}.
-
- Find this device in Devices/Sessions section.
+ Find this device in {t('Settings.verify_step_3_section')} section.
- - Initiate verification.
+ - {t('Settings.verify_step_4')}
- If you do not have any verified device press the "Verify Manually" button.
+ {t('Settings.verify_no_device')}
);
@@ -104,6 +107,7 @@ export function VerifyCurrentDeviceTile({
secretStorageKeyId,
secretStorageKeyContent,
}: VerifyCurrentDeviceTileProps) {
+ const { t } = useTranslation();
const [learnMore, setLearnMore] = useState(false);
const [manualVerification, setManualVerification] = useState(false);
@@ -113,12 +117,12 @@ export function VerifyCurrentDeviceTile({
<>
- Start verification from other device or verify manually.{' '}
+ {t('Settings.verify_current_desc')}{' '}
setLearnMore(!learnMore)}>
- {learnMore ? 'View Less' : 'Learn More'}
+ {learnMore ? t('Settings.view_less') : t('Settings.learn_more')}
>
}
@@ -133,7 +137,7 @@ export function VerifyCurrentDeviceTile({
onClick={() => setManualVerification(true)}
>
- Verify Manually
+ {t('Settings.verify_manually')}
)
@@ -167,6 +171,7 @@ type VerifyOtherDeviceTileProps = {
deviceId: string;
};
export function VerifyOtherDeviceTile({ crypto, deviceId }: VerifyOtherDeviceTileProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const [requestState, setRequestState] = useState>({
status: AsyncStatus.Idle,
@@ -190,8 +195,8 @@ export function VerifyOtherDeviceTile({ crypto, deviceId }: VerifyOtherDeviceTil
return (
- Verify
+ {t('Settings.verify')}
}
@@ -221,6 +226,7 @@ type EnableVerificationProps = {
visible: boolean;
};
export function EnableVerification({ visible }: EnableVerificationProps) {
+ const { t } = useTranslation();
const [open, setOpen] = useState(false);
const handleCancel = useCallback(() => setOpen(false), []);
@@ -230,7 +236,7 @@ export function EnableVerification({ visible }: EnableVerificationProps) {
{visible && (
)}
@@ -254,6 +260,7 @@ export function EnableVerification({ visible }: EnableVerificationProps) {
}
export function DeviceVerificationOptions() {
+ const { t } = useTranslation();
const [menuCords, setMenuCords] = useState();
const authMetadata = useAuthMetadata();
const accountManagementActions = useAccountManagementActions();
@@ -324,7 +331,7 @@ export function DeviceVerificationOptions() {
fill="None"
>
- Reset
+ {t('Settings.reset')}
diff --git a/src/app/features/settings/emojis-stickers/EmojisStickers.tsx b/src/app/features/settings/emojis-stickers/EmojisStickers.tsx
index 93715120..5bb84b37 100644
--- a/src/app/features/settings/emojis-stickers/EmojisStickers.tsx
+++ b/src/app/features/settings/emojis-stickers/EmojisStickers.tsx
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
import { Box, Text, IconButton, Icon, Icons, Scroll } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { GlobalPacks } from './GlobalPacks';
@@ -10,6 +11,7 @@ type EmojisStickersProps = {
requestClose: () => void;
};
export function EmojisStickers({ requestClose }: EmojisStickersProps) {
+ const { t } = useTranslation();
const [imagePack, setImagePack] = useState();
const handleImagePackViewClose = () => {
@@ -26,7 +28,7 @@ export function EmojisStickers({ requestClose }: EmojisStickersProps) {
- Emojis & Stickers
+ {t('Settings.emojis_stickers_title')}
diff --git a/src/app/features/settings/emojis-stickers/GlobalPacks.tsx b/src/app/features/settings/emojis-stickers/GlobalPacks.tsx
index a9288728..29536ac4 100644
--- a/src/app/features/settings/emojis-stickers/GlobalPacks.tsx
+++ b/src/app/features/settings/emojis-stickers/GlobalPacks.tsx
@@ -1,4 +1,5 @@
import React, { MouseEventHandler, useCallback, useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
import {
Box,
Text,
@@ -53,6 +54,7 @@ function GlobalPackSelector({
useAuthentication: boolean;
onSelect: (addresses: PackAddress[]) => void;
}) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const roomToPacks = useMemo(() => {
const rToP = new Map();
@@ -107,7 +109,7 @@ function GlobalPackSelector({
- Room Packs
+ {t('Settings.room_packs')}
@@ -117,7 +119,7 @@ function GlobalPackSelector({
outlined={hasSelected}
onClick={() => onSelect(selected)}
>
- {hasSelected ? 'Save' : 'Close'}
+ {hasSelected ? t('Settings.save') : t('Settings.close')}
@@ -162,7 +164,7 @@ function GlobalPackSelector({
addSelected(roomPackAddresses);
}}
>
- {allSelected ? 'Unselect All' : 'Select All'}
+ {allSelected ? t('Settings.unselect_all') : t('Settings.select_all')}
@@ -184,7 +186,7 @@ function GlobalPackSelector({
gap="400"
>
{pack.meta.attribution}}
before={
@@ -232,10 +234,10 @@ function GlobalPackSelector({
}}
>
- No Packs
+ {t('Settings.no_packs')}
- Pack from rooms will appear here. You do not have any room with packs yet.
+ {t('Settings.no_packs_desc')}
@@ -251,6 +253,7 @@ type GlobalPacksProps = {
onViewPack: (imagePack: ImagePack) => void;
};
export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication();
const globalPacks = useGlobalImagePacks();
@@ -360,7 +363,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
- {pack.meta.name ?? 'Unknown'}
+ {pack.meta.name ?? t('Settings.unknown')}
}
description={{pack.meta.attribution}}
@@ -408,7 +411,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
outlined
onClick={() => onViewPack(pack)}
>
- View
+ {t('Settings.view')}
)
}
@@ -420,7 +423,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
return (
<>
- Favorite Packs
+ {t('Settings.favorite_packs')}
{applyState.status === AsyncStatus.Error ? (
- Failed to apply changes! Please try again.
+ {t('Settings.apply_error')}
) : (
- Changes saved! Apply when ready.
+ {t('Settings.apply_ready')}
)}
@@ -519,7 +522,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
disabled={applyingChanges}
onClick={resetChanges}
>
- Reset
+ {t('Settings.reset')}
}
onClick={applyChanges}
>
- Apply Changes
+ {t('Settings.apply_changes')}
diff --git a/src/app/features/settings/emojis-stickers/UserPack.tsx b/src/app/features/settings/emojis-stickers/UserPack.tsx
index c41c8e18..33e8fa7f 100644
--- a/src/app/features/settings/emojis-stickers/UserPack.tsx
+++ b/src/app/features/settings/emojis-stickers/UserPack.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { useTranslation } from 'react-i18next';
import { Avatar, AvatarFallback, AvatarImage, Box, Button, Icon, Icons, Text } from 'folds';
import { useUserImagePack } from '../../../hooks/useImagePacks';
import { SequenceCard } from '../../../components/sequence-card';
@@ -13,6 +14,7 @@ type UserPackProps = {
onViewPack: (imagePack: ImagePack) => void;
};
export function UserPack({ onViewPack }: UserPackProps) {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication();
@@ -31,7 +33,7 @@ export function UserPack({ onViewPack }: UserPackProps) {
return (
- Default Pack
+ {t('Settings.default_pack')}
@@ -61,7 +63,7 @@ export function UserPack({ onViewPack }: UserPackProps) {
outlined
onClick={handleView}
>
- View
+ {t('Settings.view')}
}
/>
diff --git a/src/app/features/settings/general/General.tsx b/src/app/features/settings/general/General.tsx
index b861a060..a775f605 100644
--- a/src/app/features/settings/general/General.tsx
+++ b/src/app/features/settings/general/General.tsx
@@ -28,6 +28,7 @@ import {
toRem,
} from 'folds';
import { isKeyHotkey } from 'is-hotkey';
+import { useTranslation } from 'react-i18next';
import FocusTrap from 'focus-trap-react';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { SequenceCard } from '../../../components/sequence-card';
@@ -139,6 +140,7 @@ function SelectTheme({ disabled }: { disabled?: boolean }) {
}
function SystemThemePreferences() {
+ const { t } = useTranslation();
const themeKind = useSystemThemeKind();
const themeNames = useThemeNames();
const themes = useThemes();
@@ -174,7 +176,7 @@ function SystemThemePreferences() {
return (
- Appearance
+ {t('Settings.appearance')}
}
/>
{systemTheme && }
@@ -327,28 +330,28 @@ function Appearance() {
}
/>
}
/>
}
/>
- } />
+ } />
);
@@ -359,6 +362,7 @@ type DateHintProps = {
handleReset: () => void;
};
function DateHint({ hasChanges, handleReset }: DateHintProps) {
+ const { t } = useTranslation();
const [anchor, setAnchor] = useState();
const categoryPadding = { padding: config.space.S200, paddingTop: 0 };
@@ -381,26 +385,26 @@ function DateHint({ hasChanges, handleReset }: DateHintProps) {
>
@@ -591,11 +596,12 @@ type PresetDateFormatProps = {
onChange: (format: string) => void;
};
function PresetDateFormat({ value, onChange }: PresetDateFormatProps) {
+ const { t } = useTranslation();
const [menuCords, setMenuCords] = useState();
const dateFormatItems = useDateFormatItems();
const getDisplayDate = (format: string): string =>
- format !== '' ? dayjs().format(format) : 'Custom';
+ format !== '' ? dayjs().format(format) : t('Settings.custom');
const handleMenu: MouseEventHandler = (evt) => {
setMenuCords(evt.currentTarget.getBoundingClientRect());
@@ -662,6 +668,7 @@ function PresetDateFormat({ value, onChange }: PresetDateFormatProps) {
}
function SelectDateFormat() {
+ const { t } = useTranslation();
const [dateFormatString, setDateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const [selectedDateFormat, setSelectedDateFormat] = useState(dateFormatString);
const customDateFormat = selectedDateFormat === '';
@@ -676,7 +683,7 @@ function SelectDateFormat() {
return (
<>
}
/>
@@ -688,14 +695,15 @@ function SelectDateFormat() {
}
function DateAndTime() {
+ const { t } = useTranslation();
const [hour24Clock, setHour24Clock] = useSetting(settingsAtom, 'hour24Clock');
return (
- Date & Time
+ {t('Settings.date_time')}
}
/>
@@ -708,32 +716,31 @@ function DateAndTime() {
}
function Editor() {
+ const { t } = useTranslation();
const [enterForNewline, setEnterForNewline] = useSetting(settingsAtom, 'enterForNewline');
const [isMarkdown, setIsMarkdown] = useSetting(settingsAtom, 'isMarkdown');
const [hideActivity, setHideActivity] = useSetting(settingsAtom, 'hideActivity');
return (
- Editor
+ {t('Settings.editor')}
}
/>
}
/>
}
/>
@@ -880,6 +887,7 @@ function SelectMessageSpacing() {
}
function Messages() {
+ const { t } = useTranslation();
const [legacyUsernameColor, setLegacyUsernameColor] = useSetting(
settingsAtom,
'legacyUsernameColor'
@@ -899,16 +907,16 @@ function Messages() {
return (
- Messages
+ {t('Settings.messages')}
- } />
+ } />
- } />
+ } />
}
/>
}
/>
}
@@ -982,13 +990,14 @@ type GeneralProps = {
requestClose: () => void;
};
export function General({ requestClose }: GeneralProps) {
+ const { t } = useTranslation();
return (
- General
+ {t('Settings.general_title')}
diff --git a/src/app/features/settings/notifications/AllMessages.tsx b/src/app/features/settings/notifications/AllMessages.tsx
index 301cb9a7..ed28fb40 100644
--- a/src/app/features/settings/notifications/AllMessages.tsx
+++ b/src/app/features/settings/notifications/AllMessages.tsx
@@ -1,4 +1,5 @@
import React, { useCallback, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
import { Badge, Box, Text } from 'folds';
import { ConditionKind, IPushRules, PushRuleCondition, PushRuleKind, RuleId } from 'matrix-js-sdk';
import { useAccountData } from '../../../hooks/useAccountData';
@@ -73,6 +74,7 @@ function AllMessagesModeSwitcher({
}
export function AllMessagesNotifications() {
+ const { t } = useTranslation();
const pushRulesEvt = useAccountData(AccountDataEvent.PushRules);
const pushRules = useMemo(
() => pushRulesEvt?.getContent() ?? { global: {} },
@@ -82,9 +84,9 @@ export function AllMessagesNotifications() {
return (
- All Messages
+ {t('Settings.all_messages')}
- Badge:
+ {t('Settings.badge')}
1
@@ -97,7 +99,7 @@ export function AllMessagesNotifications() {
gap="400"
>
}
/>
@@ -108,7 +110,7 @@ export function AllMessagesNotifications() {
gap="400"
>
}
/>
@@ -137,7 +139,7 @@ export function AllMessagesNotifications() {
gap="400"
>
('');
@@ -97,7 +99,7 @@ function KeywordInput() {
disabled={addingKeyword}
>
{addingKeyword && }
- Save
+ {t('Settings.save')}
);
@@ -146,6 +148,7 @@ function KeywordModeSwitcher({ pushRule }: PushRulesProps) {
}
export function KeywordMessagesNotifications() {
+ const { t } = useTranslation();
const pushRulesEvt = useAccountData(AccountDataEvent.PushRules);
const pushRules = useMemo(
() => pushRulesEvt?.getContent() ?? { global: {} },
@@ -162,9 +165,9 @@ export function KeywordMessagesNotifications() {
return (
- Keyword Messages
+ {t('Settings.keyword_messages')}
- Badge:
+ {t('Settings.badge')}
1
@@ -177,8 +180,8 @@ export function KeywordMessagesNotifications() {
gap="400"
>
diff --git a/src/app/features/settings/notifications/NotificationModeSwitcher.tsx b/src/app/features/settings/notifications/NotificationModeSwitcher.tsx
index fe008390..5987ff62 100644
--- a/src/app/features/settings/notifications/NotificationModeSwitcher.tsx
+++ b/src/app/features/settings/notifications/NotificationModeSwitcher.tsx
@@ -13,6 +13,7 @@ import {
} from 'folds';
import { IPushRule } from 'matrix-js-sdk';
import React, { MouseEventHandler, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
import FocusTrap from 'focus-trap-react';
import { NotificationMode, useNotificationActionsMode } from '../../../hooks/useNotificationMode';
import { stopPropagation } from '../../../utils/keyboard';
@@ -21,15 +22,17 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
export const useNotificationModes = (): NotificationMode[] =>
useMemo(() => [NotificationMode.NotifyLoud, NotificationMode.Notify, NotificationMode.OFF], []);
-const useNotificationModeStr = (): Record =>
- useMemo(
+const useNotificationModeStr = (): Record => {
+ const { t } = useTranslation();
+ return useMemo(
() => ({
- [NotificationMode.OFF]: 'Disable',
- [NotificationMode.Notify]: 'Notify Silent',
- [NotificationMode.NotifyLoud]: 'Notify Loud',
+ [NotificationMode.OFF]: t('Settings.notif_disable'),
+ [NotificationMode.Notify]: t('Settings.notif_silent'),
+ [NotificationMode.NotifyLoud]: t('Settings.notif_loud'),
}),
- []
+ [t]
);
+};
type NotificationModeSwitcherProps = {
pushRule: IPushRule;
diff --git a/src/app/features/settings/notifications/Notifications.tsx b/src/app/features/settings/notifications/Notifications.tsx
index 095a9bba..2ef2dcbb 100644
--- a/src/app/features/settings/notifications/Notifications.tsx
+++ b/src/app/features/settings/notifications/Notifications.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { useTranslation } from 'react-i18next';
import { Box, Text, IconButton, Icon, Icons, Scroll } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { SystemNotification } from './SystemNotification';
@@ -13,13 +14,14 @@ type NotificationsProps = {
requestClose: () => void;
};
export function Notifications({ requestClose }: NotificationsProps) {
+ const { t } = useTranslation();
return (
- Notifications
+ {t('Settings.notifications_title')}
@@ -38,7 +40,7 @@ export function Notifications({ requestClose }: NotificationsProps) {
- Block Messages
+ {t('Settings.block_messages')}
Block Users" section.'}
+ description={t('Settings.block_messages_moved')}
/>
diff --git a/src/app/features/settings/notifications/SpecialMessages.tsx b/src/app/features/settings/notifications/SpecialMessages.tsx
index cbebf648..7ab38017 100644
--- a/src/app/features/settings/notifications/SpecialMessages.tsx
+++ b/src/app/features/settings/notifications/SpecialMessages.tsx
@@ -1,4 +1,5 @@
import React, { useCallback, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
import { ConditionKind, IPushRules, PushRuleKind, RuleId } from 'matrix-js-sdk';
import { Box, Text, Badge } from 'folds';
import { useAccountData } from '../../../hooks/useAccountData';
@@ -112,6 +113,7 @@ function MentionModeSwitcher({ ruleId, pushRules, defaultPushRuleData }: PushRul
}
export function SpecialMessagesNotifications() {
+ const { t } = useTranslation();
const mx = useMatrixClient();
const userId = mx.getUserId()!;
const { displayName } = useUserProfile(userId);
@@ -124,9 +126,9 @@ export function SpecialMessagesNotifications() {
return (
- Special Messages
+ {t('Settings.special_messages')}
- Badge:
+ {t('Settings.badge')}
1
@@ -139,7 +141,7 @@ export function SpecialMessagesNotifications() {
gap="400"
>
{result && !result.email && (
- Your account does not have any email attached.
+ {t('Settings.email_no_email')}
)}
- {result && result.email && <>Send notification to your email. {`("${result.email}")`}>}
+ {result && result.email && t('Settings.email_send_notif_to', { email: result.email })}
{result === null && (
- Unexpected Error!
+ {t('Settings.unexpected_error')}
)}
- {result === undefined && 'Send notification to your email.'}
+ {result === undefined && t('Settings.email_send_notif')}
>
}
after={
@@ -85,6 +87,7 @@ function EmailNotification() {
}
export function SystemNotification() {
+ const { t } = useTranslation();
const notifPermission = usePermissionState('notifications', getNotificationState());
const [showNotifications, setShowNotifications] = useSetting(settingsAtom, 'showNotifications');
const [isNotificationSounds, setIsNotificationSounds] = useSetting(
@@ -98,7 +101,7 @@ export function SystemNotification() {
return (
- System
+ {t('Settings.system')}
{'Notification' in window
- ? 'Notification permission is blocked. Please allow notification permission from browser address bar.'
- : 'Notifications are not supported by the system.'}
+ ? t('Settings.notif_permission_blocked')
+ : t('Settings.notif_not_supported')}
) : (
- Show desktop notifications when message arrive.
+ {t('Settings.notif_show_desktop')}
)
}
after={
notifPermission === 'prompt' ? (
) : (
}
/>
diff --git a/src/app/pages/auth/register/PasswordRegisterForm.tsx b/src/app/pages/auth/register/PasswordRegisterForm.tsx
index 6c7eeaba..d1af9bde 100644
--- a/src/app/pages/auth/register/PasswordRegisterForm.tsx
+++ b/src/app/pages/auth/register/PasswordRegisterForm.tsx
@@ -374,7 +374,10 @@ export function PasswordRegisterForm({
}}
+ components={{
+ // eslint-disable-next-line jsx-a11y/anchor-has-content, jsx-a11y/control-has-associated-label -- Trans fills content at runtime
+ termsLink: ,
+ }}
/>