Add more translations (#9733)

This commit is contained in:
Félix Malfait
2025-01-18 17:38:05 +01:00
committed by GitHub
parent 152902d1be
commit 052331685f
35 changed files with 2172 additions and 185 deletions

View File

@ -12,6 +12,7 @@ import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/st
import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer';
import { MainNavigationDrawerItems } from '@/navigation/components/MainNavigationDrawerItems';
import { useLingui } from '@lingui/react/macro';
import { AdvancedSettingsToggle } from 'twenty-ui';
export type AppNavigationDrawerProps = {
@ -28,9 +29,11 @@ export const AppNavigationDrawer = ({
isAdvancedModeEnabledState,
);
const { t } = useLingui();
const drawerProps: NavigationDrawerProps = isSettingsDrawer
? {
title: 'Exit Settings',
title: t`'Exit Settings'`,
children: <SettingsNavigationDrawerItems />,
footer: (
<AdvancedSettingsToggle

View File

@ -11,6 +11,7 @@ import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { AppPath } from '@/types/AppPath';
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { i18nFrontDecorator } from '~/testing/decorators/i18nFrontDecorator';
import {
AppNavigationDrawer,
AppNavigationDrawerProps,
@ -54,6 +55,7 @@ const meta: Meta<StoryArgs> = {
decorators: [
IconsProviderDecorator,
ObjectMetadataItemsDecorator,
i18nFrontDecorator,
(Story, { args }) => (
<MemoryRouter initialEntries={[args.routePath]}>
<Story />

View File

@ -9,8 +9,11 @@ import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsAccountsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsBlocklistInput';
import { SettingsAccountsBlocklistTable } from '@/settings/accounts/components/SettingsAccountsBlocklistTable';
import { useLingui } from '@lingui/react/macro';
export const SettingsAccountsBlocklistSection = () => {
const { t } = useLingui();
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { records: blocklist } = useFindManyRecords<BlocklistItem>({
@ -40,8 +43,8 @@ export const SettingsAccountsBlocklistSection = () => {
return (
<Section>
<H2Title
title="Blocklist"
description="Exclude the following people and domains from my email sync"
title={t`Blocklist`}
description={t`Exclude the following people and domains from my email sync`}
/>
<SettingsAccountsBlocklistInput
blockedEmailOrDomainList={blocklist.map((item) => item.handle)}

View File

@ -11,6 +11,7 @@ import {
import { SettingsCard } from '@/settings/components/SettingsCard';
import { SettingsPath } from '@/types/SettingsPath';
import { useTheme } from '@emotion/react';
import { useLingui } from '@lingui/react/macro';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledCardsContainer = styled.div`
@ -24,12 +25,13 @@ const StyledCardsContainer = styled.div`
`;
export const SettingsAccountsSettingsSection = () => {
const { t } = useLingui();
const theme = useTheme();
return (
<Section>
<H2Title
title="Settings"
description="Configure your emails and calendar settings."
title={t`Settings`}
description={t`Configure your emails and calendar settings.`}
/>
<StyledCardsContainer>
<UndecoratedLink to={getSettingsPath(SettingsPath.AccountsEmails)}>
@ -40,8 +42,8 @@ export const SettingsAccountsSettingsSection = () => {
stroke={theme.icon.stroke.sm}
/>
}
title="Emails"
description="Set email visibility, manage your blocklist and more."
title={t`Emails`}
description={t`Set email visibility, manage your blocklist and more.`}
/>
</UndecoratedLink>
<UndecoratedLink to={getSettingsPath(SettingsPath.AccountsCalendars)}>
@ -52,8 +54,8 @@ export const SettingsAccountsSettingsSection = () => {
stroke={theme.icon.stroke.sm}
/>
}
title="Calendar"
description="Configure and customize your calendar preferences."
title={t`Calendar`}
description={t`Configure and customize your calendar preferences.`}
/>
</UndecoratedLink>
</StyledCardsContainer>

View File

@ -1,15 +1,16 @@
import { H2Title, Section } from 'twenty-ui';
import { SettingsAccountsListEmptyStateCard } from '@/settings/accounts/components/SettingsAccountsListEmptyStateCard';
import { t } from '@lingui/core/macro';
export const SettingsNewAccountSection = () => {
return (
<Section>
<H2Title
title="New account"
description="Connect a new account to your workspace"
title={t`New account`}
description={t`Connect a new account to your workspace`}
/>
<SettingsAccountsListEmptyStateCard label="Connect a Google account" />
<SettingsAccountsListEmptyStateCard label={t`Connect a Google account`} />
</Section>
);
};

View File

@ -4,9 +4,12 @@ import { Button, H2Title } from 'twenty-ui';
import { currentUserState } from '@/auth/states/currentUserState';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { useLingui } from '@lingui/react/macro';
import { useEmailPasswordResetLinkMutation } from '~/generated/graphql';
export const ChangePassword = () => {
const { t } = useLingui();
const { enqueueSnackBar } = useSnackBar();
const currentUser = useRecoilValue(currentUserState);
@ -15,7 +18,7 @@ export const ChangePassword = () => {
const handlePasswordResetClick = async () => {
if (!currentUser?.email) {
enqueueSnackBar('Invalid email', {
enqueueSnackBar(t`Invalid email`, {
variant: SnackBarVariant.Error,
});
return;
@ -28,11 +31,11 @@ export const ChangePassword = () => {
},
});
if (data?.emailPasswordResetLink?.success === true) {
enqueueSnackBar('Password reset link has been sent to the email', {
enqueueSnackBar(t`Password reset link has been sent to the email`, {
variant: SnackBarVariant.Success,
});
} else {
enqueueSnackBar('There was some issue', {
enqueueSnackBar(t`There was an issue`, {
variant: SnackBarVariant.Error,
});
}
@ -46,13 +49,13 @@ export const ChangePassword = () => {
return (
<>
<H2Title
title="Change Password"
description="Receive an email containing password update link"
title={t`Change Password`}
description={t`Receive an email containing password update link`}
/>
<Button
onClick={handlePasswordResetClick}
variant="secondary"
title="Change Password"
title={t`Change Password`}
/>
</>
);

View File

@ -5,9 +5,11 @@ import { Button, H2Title } from 'twenty-ui';
import { useAuth } from '@/auth/hooks/useAuth';
import { currentUserState } from '@/auth/states/currentUserState';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useLingui } from '@lingui/react/macro';
import { useDeleteUserAccountMutation } from '~/generated/graphql';
export const DeleteAccount = () => {
const { t } = useLingui();
const [isDeleteAccountModalOpen, setIsDeleteAccountModalOpen] =
useState(false);
@ -24,15 +26,15 @@ export const DeleteAccount = () => {
return (
<>
<H2Title
title="Danger zone"
description="Delete account and all the associated data"
title={t`Danger zone`}
description={t`Delete account and all the associated data`}
/>
<Button
accent="danger"
onClick={() => setIsDeleteAccountModalOpen(true)}
variant="secondary"
title="Delete account"
title={t`Delete account`}
/>
<ConfirmationModal
@ -40,7 +42,7 @@ export const DeleteAccount = () => {
confirmationPlaceholder={userEmail ?? ''}
isOpen={isDeleteAccountModalOpen}
setIsOpen={setIsDeleteAccountModalOpen}
title="Account Deletion"
title={t`Account Deletion`}
subtitle={
<>
This action cannot be undone. This will permanently delete your
@ -48,7 +50,7 @@ export const DeleteAccount = () => {
</>
}
onConfirmClick={deleteAccount}
deleteButtonText="Delete account"
deleteButtonText={t`Delete account`}
/>
</>
);

View File

@ -12,6 +12,7 @@ import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/Snac
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import isPropValid from '@emotion/is-prop-valid';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useRecoilState, useRecoilValue } from 'recoil';
import { IconKey } from 'twenty-ui';
import { useListSsoIdentityProvidersByWorkspaceIdQuery } from '~/generated/graphql';
@ -29,6 +30,8 @@ export const SettingsSSOIdentitiesProvidersListCard = () => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const { t } = useLingui();
const [SSOIdentitiesProviders, setSSOIdentitiesProviders] = useRecoilState(
SSOIdentitiesProvidersState,
);
@ -53,7 +56,7 @@ export const SettingsSSOIdentitiesProvidersListCard = () => {
isDisabled={currentWorkspace?.hasValidEntrepriseKey !== true}
>
<SettingsCard
title="Add SSO Identity Provider"
title={t`Add SSO Identity Provider`}
disabled={currentWorkspace?.hasValidEntrepriseKey !== true}
Icon={<IconKey />}
/>

View File

@ -5,6 +5,7 @@ import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdent
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useRecoilState, useRecoilValue } from 'recoil';
import { capitalize } from 'twenty-shared';
import {
@ -24,6 +25,8 @@ const StyledSettingsSecurityOptionsList = styled.div`
`;
export const SettingsSecurityOptionsList = () => {
const { t } = useLingui();
const { enqueueSnackBar } = useSnackBar();
const SSOIdentitiesProviders = useRecoilValue(SSOIdentitiesProvidersState);
const authProviders = useRecoilValue(authProvidersState);
@ -45,13 +48,13 @@ export const SettingsSecurityOptionsList = () => {
authProvider: keyof Omit<AuthProviders, '__typename' | 'magicLink' | 'sso'>,
) => {
if (!currentWorkspace?.id) {
throw new Error('User is not logged in');
throw new Error(t`User is not logged in`);
}
const key = `is${capitalize(authProvider)}AuthEnabled`;
if (!isValidAuthProvider(key)) {
throw new Error('Invalid auth provider');
throw new Error(t`Invalid auth provider`);
}
const allAuthProvidersEnabled = [
@ -67,7 +70,7 @@ export const SettingsSecurityOptionsList = () => {
1
) {
return enqueueSnackBar(
'At least one authentication method must be enabled',
t`At least one authentication method must be enabled`,
{
variant: SnackBarVariant.Error,
},
@ -100,7 +103,7 @@ export const SettingsSecurityOptionsList = () => {
const handleChange = async (value: boolean) => {
try {
if (!currentWorkspace?.id) {
throw new Error('User is not logged in');
throw new Error(t`User is not logged in`);
}
await updateWorkspace({
variables: {
@ -129,7 +132,7 @@ export const SettingsSecurityOptionsList = () => {
<SettingsOptionCardContentToggle
Icon={IconGoogle}
title="Google"
description="Allow logins through Google's single sign-on functionality."
description={t`Allow logins through Google's single sign-on functionality.`}
checked={currentWorkspace.isGoogleAuthEnabled}
advancedMode
divider
@ -140,7 +143,7 @@ export const SettingsSecurityOptionsList = () => {
<SettingsOptionCardContentToggle
Icon={IconMicrosoft}
title="Microsoft"
description="Allow logins through Microsoft's single sign-on functionality."
description={t`Allow logins through Microsoft's single sign-on functionality.`}
checked={currentWorkspace.isMicrosoftAuthEnabled}
advancedMode
divider
@ -150,8 +153,8 @@ export const SettingsSecurityOptionsList = () => {
{authProviders.password === true && (
<SettingsOptionCardContentToggle
Icon={IconPassword}
title="Password"
description="Allow users to sign in with an email and password."
title={t`Password`}
description={t`Allow users to sign in with an email and password.`}
checked={currentWorkspace.isPasswordAuthEnabled}
advancedMode
onChange={() => toggleAuthMethod('password')}
@ -161,8 +164,8 @@ export const SettingsSecurityOptionsList = () => {
<Card rounded>
<SettingsOptionCardContentToggle
Icon={IconLink}
title="Invite by Link"
description="Allow the invitation of new users by sharing an invite link."
title={t`Invite by Link`}
description={t`Allow the invitation of new users by sharing an invite link.`}
checked={currentWorkspace.isPublicInviteLinkEnabled}
advancedMode
onChange={() =>

View File

@ -1,7 +1,7 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
import { i18nDecoratorFront } from '~/testing/decorators/i18nDecoratorFront';
import { i18nFrontDecorator } from '~/testing/decorators/i18nFrontDecorator';
import { workspaceLogoUrl } from '~/testing/mock-data/users';
import { ImageInput } from '../ImageInput';
@ -9,7 +9,7 @@ import { ImageInput } from '../ImageInput';
const meta: Meta<typeof ImageInput> = {
title: 'UI/Input/ImageInput/ImageInput',
component: ImageInput,
decorators: [ComponentDecorator, i18nDecoratorFront],
decorators: [ComponentDecorator, i18nFrontDecorator],
};
export default meta;