Merge pull request #1908 from vector-im/t3chguy/localazy/2

Switch from Weblate to Localazy
This commit is contained in:
Robin
2023-11-20 16:55:58 -05:00
committed by GitHub
68 changed files with 2680 additions and 2162 deletions

View File

@@ -21,6 +21,7 @@ import app from "../../public/locales/en-GB/app.json";
declare module "i18next" {
interface CustomTypeOptions {
defaultNS: "app";
keySeparator: ".";
resources: {
app: typeof app;
};

View File

@@ -257,9 +257,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
"message",
useCallback(() => {
initClientState?.client.stopClient();
setAlreadyOpenedErr(
translatedError("This application has been opened in another tab.", t),
);
setAlreadyOpenedErr(translatedError("application_opened_another_tab", t));
}, [initClientState?.client, setAlreadyOpenedErr, t]),
);

View File

@@ -45,7 +45,7 @@ export const DisconnectedBanner: FC<Props> = ({
{shouldShowBanner && (
<div className={classNames(styles.banner, className)} {...rest}>
{children}
{t("Connectivity to the server has been lost.")}
{t("disconnected_banner")}
</div>
)}
</>

View File

@@ -85,7 +85,7 @@ export const ErrorView: FC<ErrorViewProps> = ({ error }) => {
className={styles.homeLink}
onPress={onReload}
>
{t("Return to home screen")}
{t("return_home_button")}
</Button>
) : (
<LinkButton
@@ -94,7 +94,7 @@ export const ErrorView: FC<ErrorViewProps> = ({ error }) => {
className={styles.homeLink}
to="/"
>
{t("Return to home screen")}
{t("return_home_button")}
</LinkButton>
)}
</FullScreenView>
@@ -110,11 +110,11 @@ export const CrashView: FC = () => {
return (
<FullScreenView>
<Trans>
<Trans i18nKey="full_screen_view_h1">
<h1>Oops, something's gone wrong.</h1>
</Trans>
{Config.get().rageshake?.submit_url && (
<Trans>
<Trans i18nKey="full_screen_view_description">
<p>Submitting debug logs will help us track down the problem.</p>
</Trans>
)}
@@ -126,7 +126,7 @@ export const CrashView: FC = () => {
className={styles.wideButton}
onPress={onReload}
>
{t("Return to home screen")}
{t("return_home_button")}
</Button>
</FullScreenView>
);
@@ -137,7 +137,7 @@ export const LoadingView: FC = () => {
return (
<FullScreenView>
<h1>{t("Loading")}</h1>
<h1>{t("common.loading")}</h1>
</FullScreenView>
);
};

View File

@@ -105,7 +105,7 @@ export const HeaderLogo: FC<HeaderLogoProps> = ({ className }) => {
<Link
className={classNames(styles.headerLogo, className)}
to="/"
aria-label={t("Element Call Home")}
aria-label={t("header_label")}
>
<Logo />
</Link>
@@ -155,10 +155,10 @@ export const RoomHeaderInfo: FC<RoomHeaderInfoProps> = ({
<UserProfileIcon
width={20}
height={20}
aria-label={t("Participants")}
aria-label={t("header_participants_label")}
/>
<Text as="span" size="sm" weight="medium">
{t("{{count, number}}", { count: participantCount })}
{t("participant_count", { count: participantCount })}
</Text>
</div>
)}

View File

@@ -136,7 +136,7 @@ export const Modal: FC<Props> = ({
<DialogClose
className={styles.close}
data-testid="modal_close"
aria-label={t("Close")}
aria-label={t("action.close")}
>
<CloseIcon width={20} height={20} />
</DialogClose>

View File

@@ -66,13 +66,13 @@ export const UserMenu: FC<Props> = ({
arr.push({
key: "settings",
icon: SettingsIcon,
label: t("Settings"),
label: "common.settings",
});
if (isPasswordlessUser && !preventNavigation) {
arr.push({
key: "login",
label: t("Sign in"),
label: t("action.sign_in"),
icon: LoginIcon,
dataTestid: "usermenu_login",
});
@@ -81,7 +81,7 @@ export const UserMenu: FC<Props> = ({
if (!isPasswordlessUser && !preventNavigation) {
arr.push({
key: "logout",
label: t("Sign out"),
label: t("action.sign_out"),
icon: LogoutIcon,
dataTestid: "usermenu_logout",
});
@@ -91,7 +91,7 @@ export const UserMenu: FC<Props> = ({
return arr;
}, [isAuthenticated, isPasswordlessUser, displayName, preventNavigation, t]);
const tooltip = useCallback(() => t("Profile"), [t]);
const tooltip = useCallback(() => t("common.profile"), [t]);
if (!isAuthenticated) {
return (
@@ -124,7 +124,7 @@ export const UserMenu: FC<Props> = ({
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(props: any): ReactNode => (
<Menu {...props} label={t("User menu")} onAction={onAction}>
<Menu {...props} label={t("a11y.user_menu")} onAction={onAction}>
{items.map(({ key, icon: Icon, label, dataTestid }) => (
<Item key={key} textValue={label}>
<Icon

View File

@@ -20,7 +20,7 @@ import { Trans } from "react-i18next";
import { Link } from "../typography/Typography";
export const AnalyticsNotice: FC = () => (
<Trans>
<Trans i18nKey="analytics_notice">
By participating in this beta, you consent to the collection of anonymous
data, which we use to improve the product. You can find more information
about which data we track in our{" "}

View File

@@ -30,7 +30,7 @@ import { Config } from "../config/Config";
export const LoginPage: FC = () => {
const { t } = useTranslation();
usePageTitle(t("Login"));
usePageTitle(t("login_title"));
const { setClient } = useClient();
const login = useInteractiveLogin();
@@ -97,8 +97,8 @@ export const LoginPage: FC = () => {
<InputField
type="text"
ref={usernameRef}
placeholder={t("Username")}
label={t("Username")}
placeholder={t("common.username")}
label={t("common.username")}
autoCorrect="off"
autoCapitalize="none"
prefix="@"
@@ -110,8 +110,8 @@ export const LoginPage: FC = () => {
<InputField
type="password"
ref={passwordRef}
placeholder={t("Password")}
label={t("Password")}
placeholder={t("common.password")}
label={t("common.password")}
data-testid="login_password"
/>
</FieldRow>
@@ -126,7 +126,7 @@ export const LoginPage: FC = () => {
disabled={loading}
data-testid="login_login"
>
{loading ? t("Logging in") : t("Login")}
{loading ? t("logging_in") : t("login_title")}
</Button>
</FieldRow>
</form>
@@ -134,7 +134,7 @@ export const LoginPage: FC = () => {
<div className={styles.authLinks}>
<p>Not registered yet?</p>
<p>
<Trans>
<Trans i18nKey="login_auth_links">
<Link to="/register">Create an account</Link>
{" Or "}
<Link to="/">Access as a guest</Link>

View File

@@ -44,7 +44,7 @@ import { Config } from "../config/Config";
export const RegisterPage: FC = () => {
const { t } = useTranslation();
usePageTitle(t("Register"));
usePageTitle(t("action.register"));
const { loading, authenticated, passwordlessUser, client, setClient } =
useClientLegacy();
@@ -140,7 +140,9 @@ export const RegisterPage: FC = () => {
useEffect(() => {
if (password && passwordConfirmation && password !== passwordConfirmation) {
confirmPasswordRef.current?.setCustomValidity(t("Passwords must match"));
confirmPasswordRef.current?.setCustomValidity(
t("register.passwords_must_match"),
);
} else {
confirmPasswordRef.current?.setCustomValidity("");
}
@@ -170,8 +172,8 @@ export const RegisterPage: FC = () => {
<InputField
type="text"
name="userName"
placeholder={t("Username")}
label={t("Username")}
placeholder={t("common.username")}
label={t("common.username")}
autoCorrect="off"
autoCapitalize="none"
prefix="@"
@@ -188,8 +190,8 @@ export const RegisterPage: FC = () => {
setPassword(e.target.value)
}
value={password}
placeholder={t("Password")}
label={t("Password")}
placeholder={t("common.password")}
label={t("common.password")}
data-testid="register_password"
/>
</FieldRow>
@@ -202,14 +204,14 @@ export const RegisterPage: FC = () => {
setPasswordConfirmation(e.target.value)
}
value={passwordConfirmation}
placeholder={t("Confirm password")}
label={t("Confirm password")}
placeholder={t("register_confirm_password_label")}
label={t("register_confirm_password_label")}
ref={confirmPasswordRef}
data-testid="register_confirm_password"
/>
</FieldRow>
<Caption>
<Trans>
<Trans i18nKey="recaptcha_caption">
This site is protected by ReCAPTCHA and the Google{" "}
<Link href="https://www.google.com/policies/privacy/">
Privacy Policy
@@ -237,14 +239,16 @@ export const RegisterPage: FC = () => {
disabled={registering}
data-testid="register_register"
>
{registering ? t("Registering…") : t("Register")}
{registering
? t("register.registering")
: t("action.register")}
</Button>
</FieldRow>
<div id={recaptchaId} />
</form>
</div>
<div className={styles.authLinks}>
<Trans>
<Trans i18nKey="register_auth_links">
<p>Already have an account?</p>
<p>
<Link to="/login">Log in</Link>

View File

@@ -80,14 +80,14 @@ export function useRecaptcha(sitekey?: string): {
if (!window.grecaptcha) {
logger.log("Recaptcha not loaded");
return Promise.reject(translatedError("Recaptcha not loaded", t));
return Promise.reject(translatedError("recaptcha_not_loaded", t));
}
return new Promise((resolve, reject) => {
const observer = new MutationObserver((mutationsList) => {
for (const item of mutationsList) {
if ((item.target as HTMLElement)?.style?.visibility !== "visible") {
reject(translatedError("Recaptcha dismissed", t));
reject(translatedError("recaptcha_dismissed", t));
observer.disconnect();
return;
}

View File

@@ -142,7 +142,9 @@ export const MicButton: FC<{
}> = ({ muted, ...rest }) => {
const { t } = useTranslation();
const Icon = muted ? MicOffSolidIcon : MicOnSolidIcon;
const label = muted ? t("Unmute microphone") : t("Mute microphone");
const label = muted
? t("unmute_microphone_button_label")
: t("mute_microphone_button_label");
return (
<Tooltip label={label}>
@@ -160,7 +162,9 @@ export const VideoButton: FC<{
}> = ({ muted, ...rest }) => {
const { t } = useTranslation();
const Icon = muted ? VideoCallOffSolidIcon : VideoCallSolidIcon;
const label = muted ? t("Start video") : t("Stop video");
const label = muted
? t("start_video_button_label")
: t("stop_video_button_label");
return (
<Tooltip label={label}>
@@ -178,7 +182,9 @@ export const ScreenshareButton: FC<{
[index: string]: unknown;
}> = ({ enabled, className, ...rest }) => {
const { t } = useTranslation();
const label = enabled ? t("Sharing screen") : t("Share screen");
const label = enabled
? t("stop_screenshare_button_label")
: t("screenshare_button_label");
return (
<Tooltip label={label}>
@@ -197,13 +203,13 @@ export const HangupButton: FC<{
const { t } = useTranslation();
return (
<Tooltip label={t("End call")}>
<Tooltip label={t("hangup_button_label")}>
<Button
variant="toolbar"
className={classNames(styles.hangupButton, className)}
{...rest}
>
<EndCallIcon aria-label={t("End call")} />
<EndCallIcon aria-label={t("hangup_button_label")} />
</Button>
</Tooltip>
);
@@ -217,9 +223,9 @@ export const SettingsButton: FC<{
const { t } = useTranslation();
return (
<Tooltip label={t("Settings")}>
<Tooltip label={t("common.settings")}>
<Button variant="toolbar" {...rest}>
<SettingsSolidIcon aria-label={t("Settings")} />
<SettingsSolidIcon aria-label={t("common.settings")} />
</Button>
</Tooltip>
);
@@ -236,9 +242,9 @@ export const AudioButton: FC<AudioButtonProps> = ({ volume, ...rest }) => {
const { t } = useTranslation();
return (
<Tooltip label={t("Local volume")}>
<Tooltip label={t("local_volume_label")}>
<Button variant="icon" {...rest}>
<VolumeIcon volume={volume} aria-label={t("Local volume")} />
<VolumeIcon volume={volume} aria-label={t("local_volume_label")} />
</Button>
</Tooltip>
);
@@ -254,7 +260,9 @@ export const FullscreenButton: FC<FullscreenButtonProps> = ({
}) => {
const { t } = useTranslation();
const Icon = fullscreen ? FullscreenExit : Fullscreen;
const label = fullscreen ? t("Exit full screen") : t("Full screen");
const label = fullscreen
? t("exit_fullscreen_button_label")
: t("fullscreen_button_label");
return (
<Tooltip label={label}>

View File

@@ -49,11 +49,13 @@ export const CopyButton: FC<Props> = ({
className={className}
onPress={setCopied}
iconStyle={isCopied ? "stroke" : "fill"}
aria-label={t("Copy")}
aria-label={t("action.copy")}
>
{isCopied ? (
<>
{variant !== "icon" && <span>{copiedMessage || t("Copied!")}</span>}
{variant !== "icon" && (
<span>{copiedMessage || t("common.copied")}</span>
)}
<CheckIcon />
</>
) : (

View File

@@ -25,7 +25,7 @@ export const InviteButton: FC<
const { t } = useTranslation();
return (
<Button kind="secondary" size="sm" Icon={UserAddIcon} {...props}>
{t("Invite")}
{t("action.invite")}
</Button>
);
};

View File

@@ -25,7 +25,7 @@ import { usePageTitle } from "../usePageTitle";
export const HomePage: FC = () => {
const { t } = useTranslation();
usePageTitle(t("Home"));
usePageTitle(t("common.home"));
const clientState = useClientState();

View File

@@ -37,12 +37,16 @@ export const JoinExistingCallModal: FC<Props> = ({
const { t } = useTranslation();
return (
<Modal title={t("Join existing call?")} open={open} onDismiss={onDismiss}>
<p>{t("This call already exists, would you like to join?")}</p>
<Modal
title={t("join_existing_call_modal.title")}
open={open}
onDismiss={onDismiss}
>
<p>{t("join_existing_call_modal.text")}</p>
<FieldRow rightAlign className={styles.buttons}>
<Button onPress={onDismiss}>{t("No")}</Button>
<Button onPress={onDismiss}>{t("action.no")}</Button>
<Button onPress={onJoin} data-testid="home_joinExistingRoom">
{t("Yes, join call")}
{t("join_existing_call_modal.join_button")}
</Button>
</FieldRow>
</Modal>

View File

@@ -125,15 +125,15 @@ export const RegisteredView: FC<Props> = ({ client }) => {
<main className={commonStyles.main}>
<HeaderLogo className={commonStyles.logo} />
<Heading size="lg" weight="semibold">
{t("Start new call")}
{t("start_new_call")}
</Heading>
<Form className={styles.form} onSubmit={onSubmit}>
<FieldRow className={styles.fieldRow}>
<InputField
id="callName"
name="callName"
label={t("Name of call")}
placeholder={t("Name of call")}
label={t("call_name")}
placeholder={t("call_name")}
type="text"
required
autoComplete="off"
@@ -147,7 +147,7 @@ export const RegisteredView: FC<Props> = ({ client }) => {
disabled={loading}
data-testid="home_go"
>
{loading ? t("Loading") : t("Go")}
{loading ? t("common.loading") : t("action.go")}
</Button>
</FieldRow>
{optInAnalytics === null && (

View File

@@ -158,15 +158,15 @@ export const UnauthenticatedView: FC = () => {
<main className={commonStyles.main}>
<HeaderLogo className={commonStyles.logo} />
<Heading size="lg" weight="semibold">
{t("Start new call")}
{t("start_new_call")}
</Heading>
<Form className={styles.form} onSubmit={onSubmit}>
<FieldRow>
<InputField
id="callName"
name="callName"
label={t("Name of call")}
placeholder={t("Name of call")}
label={t("call_name")}
placeholder={t("call_name")}
type="text"
required
autoComplete="off"
@@ -177,8 +177,8 @@ export const UnauthenticatedView: FC = () => {
<InputField
id="displayName"
name="displayName"
label={t("Display name")}
placeholder={t("Display name")}
label={t("common.display_name")}
placeholder={t("common.display_name")}
type="text"
required
data-testid="home_displayName"
@@ -191,7 +191,7 @@ export const UnauthenticatedView: FC = () => {
</Caption>
)}
<Caption className={styles.notice}>
<Trans>
<Trans i18nKey="unauthenticated_view_eula_caption">
By clicking "Go", you agree to our{" "}
<Link href={Config.get().eula}>
End User Licensing Agreement (EULA)
@@ -209,7 +209,7 @@ export const UnauthenticatedView: FC = () => {
disabled={loading}
data-testid="home_go"
>
{loading ? t("Loading") : t("Go")}
{loading ? t("common.loading") : t("action.go")}
</Button>
<div id={recaptchaId} />
</Form>
@@ -217,11 +217,11 @@ export const UnauthenticatedView: FC = () => {
<footer className={styles.footer}>
<Body className={styles.mobileLoginLink}>
<Link color="primary" to="/login" data-testid="home_login">
{t("Login to your account")}
{t("unauthenticated_view_login_button")}
</Link>
</Body>
<Body>
<Trans>
<Trans i18nKey="unauthenticated_view_body">
Not registered yet?{" "}
<Link color="primary" to="/register" data-testid="home_register">
Create an account

View File

@@ -72,7 +72,7 @@ export class Initializer {
.init({
fallbackLng: "en-GB",
defaultNS: "app",
keySeparator: false,
keySeparator: ".",
nsSeparator: false,
pluralSeparator: "_",
contextSeparator: "|",

View File

@@ -115,7 +115,7 @@ export const AvatarInputField = forwardRef<HTMLInputElement, Props>(
variant="icon"
onPress={onPressRemoveAvatar}
>
{t("Remove")}
{t("action.remove")}
</Button>
)}
</div>

View File

@@ -58,7 +58,7 @@ export function SelectInput(props: Props): JSX.Element {
<span {...valueProps} className={styles.selectedItem}>
{state.selectedItem
? state.selectedItem.rendered
: t("Select an option")}
: t("select_input_unset_button")}
</span>
<ArrowDownIcon />
</button>

View File

@@ -62,7 +62,7 @@ export function StarRatingInput({
id={"starInvisibleLabel" + String(index)}
htmlFor={"starInput" + String(index)}
>
{t("{{count}} stars", {
{t("star_rating_input_label", {
count: index,
})}
</label>

View File

@@ -76,15 +76,19 @@ export const AppSelectionModal: FC<Props> = ({ roomId }) => {
}, [roomId, roomSharedKey]);
return (
<Modal className={styles.modal} title={t("Select app")} open={open}>
<Modal
className={styles.modal}
title={t("app_selection_modal.title")}
open={open}
>
<Text size="md" weight="semibold">
{t("Ready to join?")}
{t("app_selection_modal.text")}
</Text>
<Button kind="secondary" onClick={onBrowserClick}>
{t("Continue in browser")}
{t("app_selection_modal.continue_in_browser")}
</Button>
<Button as="a" href={appUrl} Icon={PopOutIcon}>
{t("Open in the app")}
{t("app_selection_modal.open_in_app")}
</Button>
</Modal>
);

View File

@@ -88,7 +88,7 @@ export const CallEndedView: FC<Props> = ({
const createAccountDialog = isPasswordlessUser && (
<div className={styles.callEndedContent}>
<Trans>
<Trans i18nKey="call_ended_view.create_account_prompt">
<p>Why not finish by setting up a password to keep your account?</p>
<p>
You'll be able to keep your name and set an avatar for use on future
@@ -101,14 +101,14 @@ export const CallEndedView: FC<Props> = ({
variant="default"
to="/register"
>
{t("Create account")}
{t("call_ended_view.create_account_button")}
</LinkButton>
</div>
);
const qualitySurveyDialog = (
<div className={styles.callEndedContent}>
<Trans>
<Trans i18nKey="call_ended_view.feedback_prompt">
<p>
We'd love to hear your feedback so we can improve your experience.
</p>
@@ -122,14 +122,14 @@ export const CallEndedView: FC<Props> = ({
className={feedbackStyle.feedback}
id="feedbackText"
name="feedbackText"
label={t("Your feedback")}
placeholder={t("Your feedback")}
label={t("settings.feedback_tab_description_label")}
placeholder={t("settings.feedback_tab_description_label")}
type="textarea"
/>
</FieldRow>{" "}
<FieldRow>
{submitDone ? (
<Trans>
<Trans i18nKey="call_ended_view.feedback_done">
<p>Thanks for your feedback!</p>
</Trans>
) : (
@@ -140,7 +140,7 @@ export const CallEndedView: FC<Props> = ({
variant="default"
data-testid="home_go"
>
{submitting ? t("Submitting") : t("Submit")}
{submitting ? t("submitting") : t("action.submit")}
</Button>
)}
</FieldRow>
@@ -154,11 +154,13 @@ export const CallEndedView: FC<Props> = ({
<>
<main className={styles.main}>
<Headline className={styles.headline}>
<Trans>You were disconnected from the call</Trans>
<Trans i18nKey="call_ended_view.body">
You were disconnected from the call
</Trans>
</Headline>
<div className={styles.disconnectedButtons}>
<Button size="lg" variant="default" onClick={reconnect}>
{t("Reconnect")}
{t("call_ended_view.reconnect_button")}
</Button>
<div className={styles.rageshakeButton}>
<RageshakeButton description="***Call disconnected***" />
@@ -168,7 +170,7 @@ export const CallEndedView: FC<Props> = ({
{!confineToRoom && (
<Body className={styles.footer}>
<Link color="primary" to="/">
{t("Return to home screen")}
{t("return_home_button")}
</Link>
</Body>
)}
@@ -180,14 +182,14 @@ export const CallEndedView: FC<Props> = ({
<main className={styles.main}>
<Headline className={styles.headline}>
{surveySubmitted
? t("{{displayName}}, your call has ended.", {
? t("call_ended_view.headline", {
displayName,
})
: t("{{displayName}}, your call has ended.", {
: t("call_ended_view.headline", {
displayName,
}) +
"\n" +
t("How did it go?")}
t("call_ended_view.survey_prompt")}
</Headline>
{(!surveySubmitted || confineToRoom) &&
PosthogAnalytics.instance.isEnabled()
@@ -197,7 +199,7 @@ export const CallEndedView: FC<Props> = ({
{!confineToRoom && (
<Body className={styles.footer}>
<Link color="primary" to="/">
{t("Not now, return to home screen")}
{t("call_ended_view.not_now_button")}
</Link>
</Body>
)}

View File

@@ -32,7 +32,7 @@ export const EncryptionLock: FC<Props> = ({ encrypted }) => {
return (
<Tooltip
label={encrypted ? t("Encrypted") : t("Not encrypted")}
label={encrypted ? t("common.encrypted") : t("common.unencrypted")}
side="right"
>
<Icon

View File

@@ -54,7 +54,7 @@ export function GroupCallLoader({
case "loading":
return (
<FullScreenView>
<h1>{t("Loading")}</h1>
<h1>{t("common.loading")}</h1>
</FullScreenView>
);
case "loaded":
@@ -63,16 +63,12 @@ export function GroupCallLoader({
if ((groupCallState.error as MatrixError).errcode === "M_NOT_FOUND") {
return (
<FullScreenView>
<Heading>{t("Call not found")}</Heading>
<Text>
{t(
"Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key.",
)}
</Text>
<Heading>{t("group_call_loader_failed_heading")}</Heading>
<Text>{t("group_call_loader_failed_text")}</Text>
{/* XXX: A 'create it for me' button would be the obvious UX here. Two screens already have
dupes of this flow, let's make a common component and put it here. */}
<Link href="/" onClick={onHomeClick}>
{t("Home")}
{t("common.home")}
</Link>
</FullScreenView>
);

View File

@@ -303,13 +303,9 @@ export const GroupCallView: FC<Props> = ({
return (
<FullScreenView>
<Heading>Incompatible Browser</Heading>
<Text>
{t(
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117",
)}
</Text>
<Text>{t("browser_media_e2ee_unsupported")}</Text>
<Link href="/" onClick={onHomeClick}>
{t("Home")}
{t("common.home")}
</Link>
</FullScreenView>
);

View File

@@ -276,7 +276,7 @@ export const InCallView: FC<InCallViewProps> = ({
if (items.length === 0) {
return (
<div className={styles.centerMessage}>
<p>{t("Waiting for other participants")}</p>
<p>{t("waiting_for_participants")}</p>
</div>
);
}

View File

@@ -58,7 +58,7 @@ export const InviteModal: FC<Props> = ({ room, open, onDismiss }) => {
return (
<>
<Modal title={t("Invite to this call")} open={open} onDismiss={onDismiss}>
<Modal title={t("invite_modal.title")} open={open} onDismiss={onDismiss}>
<Text className={styles.url} size="sm" weight="semibold">
{url}
</Text>
@@ -68,7 +68,7 @@ export const InviteModal: FC<Props> = ({ room, open, onDismiss }) => {
onClick={onButtonClick}
data-testid="modal_inviteLink"
>
{t("Copy link")}
{t("action.copy_link")}
</Button>
</Modal>
<Toast
@@ -77,7 +77,7 @@ export const InviteModal: FC<Props> = ({ room, open, onDismiss }) => {
autoDismiss={2000}
Icon={CheckIcon}
>
{t("Link copied to clipboard")}
{t("invite_modal.link_copied_toast")}
</Toast>
</>
);

View File

@@ -52,9 +52,9 @@ export const LayoutToggle: FC<Props> = ({ layout, setLayout, className }) => {
checked={layout === "spotlight"}
onChange={onChange}
/>
<Tooltip label={t("Spotlight")}>
<Tooltip label={t("layout_spotlight_label")}>
<label htmlFor={spotlightId}>
<SpotlightIcon aria-label={t("Spotlight")} />
<SpotlightIcon aria-label={t("layout_spotlight_label")} />
</label>
</Tooltip>
<input
@@ -65,9 +65,9 @@ export const LayoutToggle: FC<Props> = ({ layout, setLayout, className }) => {
checked={layout === "grid"}
onChange={onChange}
/>
<Tooltip label={t("Grid")}>
<Tooltip label={t("layout_grid_label")}>
<label htmlFor={gridId}>
<GridIcon aria-label={t("Grid")} />
<GridIcon aria-label={t("layout_grid_label")} />
</label>
</Tooltip>
</div>

View File

@@ -87,7 +87,7 @@ export const LobbyView: FC<Props> = ({
const recentsButtonInFooter = useMediaQuery("(max-height: 500px)");
const recentsButton = !confineToRoom && (
<Link className={styles.recents} href="#" onClick={onLeaveClick}>
{t("Back to recents")}
{t("lobby.leave_button")}
</Link>
);
@@ -120,7 +120,7 @@ export const LobbyView: FC<Props> = ({
onClick={onEnter}
data-testid="lobby_joinCall"
>
{t("Join call")}
{t("lobby.join_button")}
</Button>
</VideoPreview>
{!recentsButtonInFooter && recentsButton}

View File

@@ -44,12 +44,12 @@ export const RageshakeRequestModal: FC<Props> = ({
}, [sent, onDismiss]);
return (
<Modal title={t("Debug log request")} open={open} onDismiss={onDismiss}>
<Body>
{t(
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.",
)}
</Body>
<Modal
title={t("rageshake_request_modal.title")}
open={open}
onDismiss={onDismiss}
>
<Body>{t("rageshake_request_modal.body")}</Body>
<FieldRow>
<Button
onPress={(): void =>
@@ -61,7 +61,7 @@ export const RageshakeRequestModal: FC<Props> = ({
}
disabled={sending}
>
{sending ? t("Sending debug logs") : t("Send debug logs")}
{sending ? t("rageshake_sending_logs") : t("rageshake_send_logs")}
</Button>
</FieldRow>
{error && (

View File

@@ -70,14 +70,16 @@ export const RoomAuthView: FC = () => {
</Header>
<div className={styles.container}>
<main className={styles.main}>
<Headline className={styles.headline}>{t("Join call")}</Headline>
<Headline className={styles.headline}>
{t("lobby.join_button")}
</Headline>
<Form className={styles.form} onSubmit={onSubmit}>
<FieldRow>
<InputField
id="displayName"
name="displayName"
label={t("Display name")}
placeholder={t("Display name")}
label={t("common.display_name")}
placeholder={t("common.display_name")}
data-testid="joincall_displayName"
type="text"
required
@@ -85,7 +87,7 @@ export const RoomAuthView: FC = () => {
/>
</FieldRow>
<Caption>
<Trans>
<Trans i18nKey="room_auth_view_eula_caption">
By clicking "Join call now", you agree to our{" "}
<Link href={Config.get().eula}>
End User Licensing Agreement (EULA)
@@ -103,13 +105,13 @@ export const RoomAuthView: FC = () => {
disabled={loading}
data-testid="joincall_joincall"
>
{loading ? t("Loading") : t("Join call now")}
{loading ? t("common.loading") : t("room_auth_view_join_button")}
</Button>
<div id={recaptchaId} />
</Form>
</main>
<Body className={styles.footer}>
<Trans>
<Trans i18nKey="unauthenticated_view_body">
Not registered yet?{" "}
<Link
color="primary"

View File

@@ -62,32 +62,28 @@ export const FeedbackSettingsTab: FC<Props> = ({ roomId }) => {
return (
<div>
<h4 className={styles.label}>{t("Submit feedback")}</h4>
<Body>
{t(
"If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
)}
</Body>
<h4 className={styles.label}>{t("settings.feedback_tab_h4")}</h4>
<Body>{t("settings.feedback_tab_body")}</Body>
<form onSubmit={onSubmitFeedback}>
<FieldRow>
<InputField
className={feedbackStyles.feedback}
id="description"
name="description"
label={t("Your feedback")}
placeholder={t("Your feedback")}
label={t("settings.feedback_tab_description_label")}
placeholder={t("settings.feedback_tab_description_label")}
type="textarea"
disabled={sending || sent}
/>
</FieldRow>
{sent ? (
<Body> {t("Thanks, we received your feedback!")}</Body>
<Body> {t("settings.feedback_tab_thank_you")}</Body>
) : (
<FieldRow>
<InputField
id="sendLogs"
name="sendLogs"
label={t("Include debug logs")}
label={t("settings.feedback_tab_send_logs_label")}
type="checkbox"
defaultChecked
/>
@@ -97,7 +93,7 @@ export const FeedbackSettingsTab: FC<Props> = ({ roomId }) => {
</FieldRow>
)}
<Button type="submit" disabled={sending}>
{sending ? t("Submitting") : t("Submit")}
{sending ? t("submitting") : "action.submit"}
</Button>
</FieldRow>
)}

View File

@@ -82,7 +82,7 @@ export const ProfileSettingsTab: FC<Props> = ({ client }) => {
<AvatarInputField
id="avatar"
name="avatar"
label={t("Avatar")}
label={t("common.avatar")}
avatarUrl={avatarUrl}
userId={userId}
displayName={displayName}
@@ -94,7 +94,7 @@ export const ProfileSettingsTab: FC<Props> = ({ client }) => {
<InputField
id="userId"
name="userId"
label={t("Username")}
label={t("common.username")}
type="text"
disabled
value={client.getUserId()!}
@@ -104,11 +104,11 @@ export const ProfileSettingsTab: FC<Props> = ({ client }) => {
<InputField
id="displayName"
name="displayName"
label={t("Display name")}
label={t("common.display_name")}
type="text"
required
autoComplete="off"
placeholder={t("Display name")}
placeholder={t("common.display_name")}
defaultValue={displayName}
data-testid="profile_displayname"
/>

View File

@@ -41,13 +41,13 @@ export const RageshakeButton: FC<Props> = ({ description }) => {
let logsComponent: JSX.Element | null = null;
if (sending) {
logsComponent = <span>{t("Sending")}</span>;
logsComponent = <span>{t("rageshake_sending")}</span>;
} else if (sent) {
logsComponent = <div>{t("Thanks!")}</div>;
logsComponent = <div>{t("rageshake_sent")}</div>;
} else {
let caption = t("Send debug logs");
let caption = t("rageshake_send_logs");
if (error) {
caption = t("Retry sending logs");
caption = t("rageshake_button_error_caption");
}
logsComponent = (

View File

@@ -103,7 +103,7 @@ export const SettingsModal: FC<Props> = (props) => {
const optInDescription = (
<Caption>
<Trans>
<Trans i18nKey="settings.opt_in_description">
<AnalyticsNotice />
<br />
You may withdraw consent by unchecking this box. If you are currently in
@@ -121,13 +121,16 @@ export const SettingsModal: FC<Props> = (props) => {
title={
<>
<AudioIcon width={16} height={16} />
<span className={styles.tabLabel}>{t("Audio")}</span>
<span className={styles.tabLabel}>{t("common.audio")}</span>
</>
}
>
{generateDeviceSelection(devices.audioInput, t("Microphone"))}
{generateDeviceSelection(devices.audioInput, t("common.microphone"))}
{!isFirefox() &&
generateDeviceSelection(devices.audioOutput, t("Speaker"))}
generateDeviceSelection(
devices.audioOutput,
t("settings.speaker_device_selection_label"),
)}
</TabItem>
);
@@ -137,11 +140,11 @@ export const SettingsModal: FC<Props> = (props) => {
title={
<>
<VideoIcon width={16} height={16} />
<span>{t("Video")}</span>
<span>{t("common.video")}</span>
</>
}
>
{generateDeviceSelection(devices.videoInput, t("Camera"))}
{generateDeviceSelection(devices.videoInput, t("common.camera"))}
</TabItem>
);
@@ -151,7 +154,7 @@ export const SettingsModal: FC<Props> = (props) => {
title={
<>
<UserIcon width={15} height={15} />
<span>{t("Profile")}</span>
<span>{t("common.profile")}</span>
</>
}
>
@@ -165,7 +168,7 @@ export const SettingsModal: FC<Props> = (props) => {
title={
<>
<FeedbackIcon width={16} height={16} />
<span>{t("Feedback")}</span>
<span>{t("settings.feedback_tab_title")}</span>
</>
}
>
@@ -179,7 +182,7 @@ export const SettingsModal: FC<Props> = (props) => {
title={
<>
<OverflowIcon width={16} height={16} />
<span>{t("More")}</span>
<span>{t("settings.more_tab_title")}</span>
</>
}
>
@@ -190,8 +193,8 @@ export const SettingsModal: FC<Props> = (props) => {
id="developerSettingsTab"
type="checkbox"
checked={developerSettingsTab}
label={t("Developer Settings")}
description={t("Expose developer settings in the settings window.")}
label={t("settings.developer_settings_label")}
description={t("settings.developer_settings_label_description")}
onChange={(event: ChangeEvent<HTMLInputElement>): void =>
setDeveloperSettingsTab(event.target.checked)
}
@@ -218,13 +221,13 @@ export const SettingsModal: FC<Props> = (props) => {
title={
<>
<DeveloperIcon width={16} height={16} />
<span>{t("Developer")}</span>
<span>{t("settings.developer_tab_title")}</span>
</>
}
>
<FieldRow>
<Body className={styles.fieldRowText}>
{t("Version: {{version}}", {
{t("version", {
version: import.meta.env.VITE_APP_VERSION || "dev",
})}
</Body>
@@ -233,7 +236,7 @@ export const SettingsModal: FC<Props> = (props) => {
<InputField
id="showConnectionStats"
name="connection-stats"
label={t("Show connection stats")}
label={t("settings.show_connection_stats_label")}
type="checkbox"
checked={showConnectionStats}
onChange={(e: ChangeEvent<HTMLInputElement>): void =>
@@ -251,7 +254,7 @@ export const SettingsModal: FC<Props> = (props) => {
return (
<Modal
title={t("Settings")}
title={t("common.settings")}
className={styles.settingsModal}
open={props.open}
onDismiss={props.onDismiss}

View File

@@ -193,18 +193,20 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>(
)}
{content === TileContent.ScreenShare ? (
<div className={styles.presenterLabel}>
<span>{t("{{displayName}} is presenting", { displayName })}</span>
<span>{t("video_tile.presenter_label", { displayName })}</span>
</div>
) : (
<div className={styles.nameTag}>
<MicIcon
width={20}
height={20}
aria-label={muted ? t("Microphone off") : t("Microphone on")}
aria-label={muted ? t("microphone_off") : t("microphone_on")}
data-muted={muted}
/>
<Text as="span" size="sm" weight="medium">
{sfuParticipant.isLocal ? t("You") : displayName}
{sfuParticipant.isLocal
? t("video_tile.sfu_participant_local")
: displayName}
</Text>
{showConnectionStats && (
<ConnectionQualityIndicator participant={sfuParticipant} />

View File

@@ -82,7 +82,7 @@ export const VideoTileSettingsModal: FC<Props> = ({
return (
<Modal
className={styles.videoTileSettingsModal}
title={t("Local volume")}
title={t("local_volume_label")}
open={open}
onDismiss={onDismiss}
>