Add missing translations (#10414)

As per title, add ~200 missing translations in different places of app.
Most places are now available for translation with AI but still some
aren't available - some enums (like in MenuItemSelectColor.tsx) or
values in complex types (like in
SettingsNonCompositeFieldTypeConfigs.ts) or values where are injected
some variables (like in SettingsDataModelFieldNumberForm.tsx)

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
BOHEUS
2025-02-23 22:35:03 +00:00
committed by GitHub
parent 2162538b8b
commit ff001d9def
135 changed files with 24834 additions and 311 deletions

View File

@ -5,6 +5,7 @@ import { TableBody } from '@/ui/layout/table/components/TableBody';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
type SettingsAccountsBlocklistTableProps = {
blocklist: BlocklistItem[];
@ -31,8 +32,8 @@ export const SettingsAccountsBlocklistTable = ({
gridAutoColumns="200px 1fr 20px"
mobileGridAutoColumns="120px 1fr 20px"
>
<TableHeader>Email/Domain</TableHeader>
<TableHeader>Added to blocklist</TableHeader>
<TableHeader>{t`Email/Domain`}</TableHeader>
<TableHeader>{t`Added to blocklist`}</TableHeader>
<TableHeader></TableHeader>
</TableRow>
<StyledTableBody>

View File

@ -7,6 +7,7 @@ import styled from '@emotion/styled';
import { Section } from '@react-email/components';
import { Card, H2Title, IconUserPlus } from 'twenty-ui';
import { CalendarChannelVisibility } from '~/generated-metadata/graphql';
import { t } from '@lingui/core/macro';
const StyledDetailsContainer = styled.div`
display: flex;
@ -50,8 +51,8 @@ export const SettingsAccountsCalendarChannelDetails = ({
<StyledDetailsContainer>
<Section>
<H2Title
title="Event visibility"
description="Define what will be visible to other users in your workspace"
title={t`Event visibility`}
description={t`Define what will be visible to other users in your workspace`}
/>
<SettingsAccountsEventVisibilitySettingsCard
value={calendarChannel.visibility}
@ -60,14 +61,14 @@ export const SettingsAccountsCalendarChannelDetails = ({
</Section>
<Section>
<H2Title
title="Contact auto-creation"
description="Automatically create contacts for people you've participated in an event with."
title={t`Contact auto-creation`}
description={t`Automatically create contacts for people you've participated in an event with.`}
/>
<Card rounded>
<SettingsOptionCardContentToggle
Icon={IconUserPlus}
title="Auto-creation"
description="Automatically create contacts for people."
title={t`Auto-creation`}
description={t`Automatically create contacts for people.`}
checked={calendarChannel.isContactAutoCreationEnabled}
onChange={() => {
handleContactAutoCreationToggle(

View File

@ -11,6 +11,7 @@ import {
CalendarChannelVisibility,
TimelineCalendarEvent,
} from '~/generated/graphql';
import { t } from '@lingui/core/macro';
const StyledGeneralContainer = styled.div`
display: flex;
@ -65,15 +66,15 @@ export const SettingsAccountsCalendarChannelsGeneral = () => {
<StyledGeneralContainer>
<Section>
<H2Title
title="Display"
description="Configure how we should display your events in your calendar"
title={t`Display`}
description={t`Configure how we should display your events in your calendar`}
/>
<SettingsAccountsCalendarDisplaySettings />
</Section>
<Section>
<H2Title
title="Color code"
description="Events you participated in are displayed in red."
title={t`Color code`}
description={t`Events you participated in are displayed in red.`}
/>
<CalendarContext.Provider
value={{

View File

@ -2,6 +2,7 @@ import styled from '@emotion/styled';
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
import { SettingsAccountsVisibilityIcon } from '@/settings/accounts/components/SettingsAccountsVisibilityIcon';
import { msg } from '@lingui/core/macro';
import { CalendarChannelVisibility } from '~/generated/graphql';
type SettingsAccountsEventVisibilitySettingsCardProps = {
@ -15,14 +16,14 @@ const StyledCardMedia = styled(SettingsAccountsVisibilityIcon)`
const eventSettingsVisibilityOptions = [
{
title: 'Everything',
description: 'The whole event details will be shared with your team.',
title: msg`Everything`,
description: msg`The whole event details will be shared with your team.`,
value: CalendarChannelVisibility.SHARE_EVERYTHING,
cardMedia: <StyledCardMedia subject="active" body="active" />,
},
{
title: 'Metadata',
description: 'Only date & participants will be shared with your team.',
title: msg`Metadata`,
description: msg`Only date & participants will be shared with your team.`,
value: CalendarChannelVisibility.METADATA,
cardMedia: <StyledCardMedia subject="active" body="inactive" />,
},

View File

@ -7,6 +7,7 @@ import { SettingsPath } from '@/types/SettingsPath';
import { SettingsAccountsConnectedAccountsRowRightContainer } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { SettingsListCard } from '../../components/SettingsListCard';
import { useLingui } from '@lingui/react/macro';
const ProviderIcons: { [k: string]: IconComponent } = {
google: IconGoogle,
@ -21,6 +22,7 @@ export const SettingsAccountsConnectedAccountsListCard = ({
loading?: boolean;
}) => {
const navigate = useNavigateSettings();
const { t } = useLingui();
if (!accounts.length) {
return <SettingsAccountsListEmptyStateCard />;
@ -36,7 +38,7 @@ export const SettingsAccountsConnectedAccountsListCard = ({
<SettingsAccountsConnectedAccountsRowRightContainer account={account} />
)}
hasFooter={true}
footerButtonLabel="Add account"
footerButtonLabel={t`Add account`}
onFooterButtonClick={() => navigate(SettingsPath.NewAccount)}
/>
);

View File

@ -4,6 +4,7 @@ import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
import { computeSyncStatus } from '@/settings/accounts/utils/computeSyncStatus';
import { Status } from 'twenty-ui';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
const StyledRowRightContainer = styled.div`
align-items: center;
@ -27,18 +28,18 @@ export const SettingsAccountsConnectedAccountsRowRightContainer = ({
return (
<StyledRowRightContainer>
{status === SyncStatus.FAILED && (
<Status color="red" text="Sync failed" weight="medium" />
<Status color="red" text={t`Sync failed`} weight="medium" />
)}
{status === SyncStatus.SYNCED && (
<Status color="green" text="Synced" weight="medium" />
<Status color="green" text={t`Synced`} weight="medium" />
)}
{status === SyncStatus.NOT_SYNCED && (
<Status color="orange" text="Not synced" weight="medium" />
<Status color="orange" text={t`Not synced`} weight="medium" />
)}
{status === SyncStatus.IMPORTING && (
<Status
color="turquoise"
text="Importing"
text={t`Importing`}
weight="medium"
isLoaderVisible
/>

View File

@ -1,6 +1,7 @@
import { MessageChannelContactAutoCreationPolicy } from '@/accounts/types/MessageChannel';
import { SettingsAccountsMessageAutoCreationIcon } from '@/settings/accounts/components/SettingsAccountsMessageAutoCreationIcon';
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
import { msg } from '@lingui/core/macro';
type SettingsAccountsMessageAutoCreationCardProps = {
onChange: (nextValue: MessageChannelContactAutoCreationPolicy) => void;
@ -9,22 +10,22 @@ type SettingsAccountsMessageAutoCreationCardProps = {
const autoCreationOptions = [
{
title: 'Sent and Received',
description: 'People Ive sent emails to and received emails from.',
title: msg`Sent and Received`,
description: msg`People Ive sent emails to and received emails from.`,
value: MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED,
cardMedia: (
<SettingsAccountsMessageAutoCreationIcon isSentActive isReceivedActive />
),
},
{
title: 'Sent',
description: 'People Ive sent emails to.',
title: msg`Sent`,
description: msg`People Ive sent emails to.`,
value: MessageChannelContactAutoCreationPolicy.SENT,
cardMedia: <SettingsAccountsMessageAutoCreationIcon isSentActive />,
},
{
title: 'None',
description: 'Dont auto-create contacts.',
title: msg`None`,
description: msg`Dont auto-create contacts.`,
value: MessageChannelContactAutoCreationPolicy.NONE,
cardMedia: (
<SettingsAccountsMessageAutoCreationIcon

View File

@ -11,6 +11,7 @@ import { SettingsAccountsMessageAutoCreationCard } from '@/settings/accounts/com
import { SettingsAccountsMessageVisibilityCard } from '@/settings/accounts/components/SettingsAccountsMessageVisibilityCard';
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
import { MessageChannelVisibility } from '~/generated-metadata/graphql';
import { t } from '@lingui/core/macro';
type SettingsAccountsMessageChannelDetailsProps = {
messageChannel: Pick<
@ -79,8 +80,8 @@ export const SettingsAccountsMessageChannelDetails = ({
<StyledDetailsContainer>
<Section>
<H2Title
title="Visibility"
description="Define what will be visible to other users in your workspace"
title={t`Visibility`}
description={t`Define what will be visible to other users in your workspace`}
/>
<SettingsAccountsMessageVisibilityCard
value={messageChannel.visibility}
@ -89,8 +90,8 @@ export const SettingsAccountsMessageChannelDetails = ({
</Section>
<Section>
<H2Title
title="Contact auto-creation"
description="Automatically create People records when receiving or sending emails"
title={t`Contact auto-creation`}
description={t`Automatically create People records when receiving or sending emails`}
/>
<SettingsAccountsMessageAutoCreationCard
value={messageChannel.contactAutoCreationPolicy}
@ -101,8 +102,8 @@ export const SettingsAccountsMessageChannelDetails = ({
<Card rounded>
<SettingsOptionCardContentToggle
Icon={IconBriefcase}
title="Exclude non-professional emails"
description="Dont create contacts from/to Gmail, Outlook emails"
title={t`Exclude non-professional emails`}
description={t`Dont create contacts from/to Gmail, Outlook emails`}
divider
checked={messageChannel.excludeNonProfessionalEmails}
onChange={() => {
@ -113,8 +114,8 @@ export const SettingsAccountsMessageChannelDetails = ({
/>
<SettingsOptionCardContentToggle
Icon={IconUsers}
title="Exclude group emails"
description="Dont sync emails from team@ support@ noreply@..."
title={t`Exclude group emails`}
description={t`Dont sync emails from team@ support@ noreply@...`}
checked={messageChannel.excludeGroupEmails}
onChange={() =>
handleIsGroupEmailExcludedToggle(

View File

@ -1,5 +1,6 @@
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
import { SettingsAccountsVisibilityIcon } from '@/settings/accounts/components/SettingsAccountsVisibilityIcon';
import { msg } from '@lingui/core/macro';
import { MessageChannelVisibility } from '~/generated/graphql';
type SettingsAccountsMessageVisibilityCardProps = {
@ -9,8 +10,8 @@ type SettingsAccountsMessageVisibilityCardProps = {
const inboxSettingsVisibilityOptions = [
{
title: 'Everything',
description: 'Subject, body and attachments will be shared with your team.',
title: msg`Everything`,
description: msg`Subject, body and attachments will be shared with your team.`,
value: MessageChannelVisibility.SHARE_EVERYTHING,
cardMedia: (
<SettingsAccountsVisibilityIcon
@ -21,8 +22,8 @@ const inboxSettingsVisibilityOptions = [
),
},
{
title: 'Subject and metadata',
description: 'Subject and metadata will be shared with your team.',
title: msg`Subject and metadata`,
description: msg`Subject and metadata will be shared with your team.`,
value: MessageChannelVisibility.SUBJECT,
cardMedia: (
<SettingsAccountsVisibilityIcon
@ -33,8 +34,8 @@ const inboxSettingsVisibilityOptions = [
),
},
{
title: 'Metadata',
description: 'Timestamp and participants will be shared with your team.',
title: msg`Metadata`,
description: msg`Timestamp and participants will be shared with your team.`,
value: MessageChannelVisibility.METADATA,
cardMedia: (
<SettingsAccountsVisibilityIcon

View File

@ -1,4 +1,6 @@
import styled from '@emotion/styled';
import { MessageDescriptor } from '@lingui/core';
import { Trans } from '@lingui/react';
import { ReactNode } from 'react';
import { Card, CardContent, Radio } from 'twenty-ui';
@ -40,8 +42,8 @@ const StyledRadio = styled(Radio)`
export const SettingsAccountsRadioSettingsCard = <
Option extends {
cardMedia: ReactNode;
description: string;
title: string;
description: MessageDescriptor;
title: MessageDescriptor;
value: string;
},
>({
@ -59,8 +61,12 @@ export const SettingsAccountsRadioSettingsCard = <
>
{option.cardMedia}
<div>
<StyledTitle>{option.title}</StyledTitle>
<StyledDescription>{option.description}</StyledDescription>
<StyledTitle>
<Trans id={option.title.id} />
</StyledTitle>
<StyledDescription>
<Trans id={option.description.id} />
</StyledDescription>
</div>
<StyledRadio
name={name}

View File

@ -19,6 +19,7 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { Trans, useLingui } from '@lingui/react/macro';
type SettingsAccountsRowDropdownMenuProps = {
account: ConnectedAccount;
@ -28,7 +29,7 @@ export const SettingsAccountsRowDropdownMenu = ({
account,
}: SettingsAccountsRowDropdownMenuProps) => {
const dropdownId = `settings-account-row-${account.id}`;
const { t } = useLingui();
const [isDeleteAccountModalOpen, setIsDeleteAccountModalOpen] =
useState(false);
@ -59,7 +60,7 @@ export const SettingsAccountsRowDropdownMenu = ({
<DropdownMenuItemsContainer>
<MenuItem
LeftIcon={IconMail}
text="Emails settings"
text={t`Emails settings`}
onClick={() => {
navigate(SettingsPath.AccountsEmails);
closeDropdown();
@ -67,7 +68,7 @@ export const SettingsAccountsRowDropdownMenu = ({
/>
<MenuItem
LeftIcon={IconCalendarEvent}
text="Calendar settings"
text={t`Calendar settings`}
onClick={() => {
navigate(SettingsPath.AccountsCalendars);
closeDropdown();
@ -76,7 +77,7 @@ export const SettingsAccountsRowDropdownMenu = ({
{account.authFailedAt && (
<MenuItem
LeftIcon={IconRefresh}
text="Reconnect"
text={t`Reconnect`}
onClick={() => {
triggerApisOAuth(account.provider);
closeDropdown();
@ -86,7 +87,7 @@ export const SettingsAccountsRowDropdownMenu = ({
<MenuItem
accent="danger"
LeftIcon={IconTrash}
text="Remove account"
text={t`Remove account`}
onClick={() => {
setIsDeleteAccountModalOpen(true);
closeDropdown();
@ -98,12 +99,14 @@ export const SettingsAccountsRowDropdownMenu = ({
<ConfirmationModal
isOpen={isDeleteAccountModalOpen}
setIsOpen={setIsDeleteAccountModalOpen}
title="Data deletion"
title={t`Data deletion`}
subtitle={
<>All emails and events linked to this account will be deleted</>
<Trans>
All emails and events linked to this account will be deleted
</Trans>
}
onConfirmClick={deleteAccount}
deleteButtonText="Delete account"
deleteButtonText={t`Delete account`}
/>
</>
);

View File

@ -4,6 +4,7 @@ import { SETTINGS_ADMIN_TABS_ID } from '@/settings/admin-panel/constants/Setting
import { TabList } from '@/ui/layout/tab/components/TabList';
import styled from '@emotion/styled';
import { IconHeart, IconSettings2, IconVariable } from 'twenty-ui';
import { t } from '@lingui/core/macro';
const StyledTabListContainer = styled.div`
align-items: center;
@ -17,17 +18,17 @@ export const SettingsAdminContent = () => {
const tabs = [
{
id: SETTINGS_ADMIN_TABS.GENERAL,
title: 'General',
title: t`General`,
Icon: IconSettings2,
},
{
id: SETTINGS_ADMIN_TABS.ENV_VARIABLES,
title: 'Env Variables',
title: t`Env Variables`,
Icon: IconVariable,
},
{
id: SETTINGS_ADMIN_TABS.HEALTH_STATUS,
title: 'Health Status',
title: t`Health Status`,
Icon: IconHeart,
},
];

View File

@ -24,6 +24,7 @@ import {
} from 'twenty-ui';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { useUserLookupAdminPanelMutation } from '~/generated/graphql';
import { t } from '@lingui/core/macro';
import packageJson from '../../../../../package.json';
@ -120,7 +121,7 @@ export const SettingsAdminGeneral = () => {
return (
<>
<Section>
<H2Title title="About" description="Version of the application" />
<H2Title title={t`About`} description={t`Version of the application`} />
<GithubVersionLink version={packageJson.version} />
</Section>
@ -128,13 +129,13 @@ export const SettingsAdminGeneral = () => {
<H2Title
title={
canManageFeatureFlags
? 'Feature Flags & Impersonation'
: 'User Impersonation'
? t`Feature Flags & Impersonation`
: t`User Impersonation`
}
description={
canManageFeatureFlags
? 'Look up users and manage their workspace feature flags or impersonate them.'
: 'Look up users to impersonate them.'
? t`Look up users and manage their workspace feature flags or impersonate them.`
: t`Look up users to impersonate them.`
}
/>
@ -143,7 +144,7 @@ export const SettingsAdminGeneral = () => {
value={userIdentifier}
onChange={setUserIdentifier}
onInputEnter={handleSearch}
placeholder="Enter user ID or email address"
placeholder={t`Enter user ID or email address`}
fullWidth
disabled={isUserLookupLoading}
/>
@ -151,7 +152,7 @@ export const SettingsAdminGeneral = () => {
Icon={IconSearch}
variant="primary"
accent="blue"
title="Search"
title={t`Search`}
onClick={handleSearch}
disabled={!userIdentifier.trim() || isUserLookupLoading}
/>
@ -161,16 +162,22 @@ export const SettingsAdminGeneral = () => {
{isDefined(userLookupResult) && (
<Section>
<StyledUserInfo>
<H1Title title="User Info" fontColor={H1TitleFontColor.Primary} />
<H2Title title={userFullName} description="User Name" />
<H1Title
title={t`User Info`}
fontColor={H1TitleFontColor.Primary}
/>
<H2Title title={userFullName} description={t`User Name`} />
<H2Title
title={userLookupResult.user.email}
description="User Email"
description={t`User Email`}
/>
<H2Title
title={userLookupResult.user.id}
description={t`User ID`}
/>
<H2Title title={userLookupResult.user.id} description="User ID" />
</StyledUserInfo>
<H1Title title="Workspaces" fontColor={H1TitleFontColor.Primary} />
<H1Title title={t`Workspaces`} fontColor={H1TitleFontColor.Primary} />
<StyledTabListContainer>
<TabList
tabs={tabs}

View File

@ -119,19 +119,19 @@ export const SettingsAdminWorkspaceContent = ({
return (
<>
<H2Title title={activeWorkspace.name} description={'Workspace Name'} />
<H2Title title={activeWorkspace.name} description={t`Workspace Name`} />
<H2Title
title={`${activeWorkspace.totalUsers} ${
activeWorkspace.totalUsers > 1 ? 'Users' : 'User'
activeWorkspace.totalUsers > 1 ? t`Users` : t`User`
}`}
description={'Total Users'}
description={t`Total Users`}
/>
{currentUser?.canImpersonate && (
<Button
Icon={IconUser}
variant="primary"
accent="blue"
title={'Impersonate'}
title={t`Impersonate`}
onClick={() => handleImpersonate(activeWorkspace.id)}
disabled={
isImpersonateLoading || activeWorkspace.allowImpersonation === false
@ -146,8 +146,8 @@ export const SettingsAdminWorkspaceContent = ({
gridAutoColumns="1fr 100px"
mobileGridAutoColumns="1fr 80px"
>
<TableHeader>Feature Flag</TableHeader>
<TableHeader align="right">Status</TableHeader>
<TableHeader>{t`Feature Flag`}</TableHeader>
<TableHeader align="right">{t`Status`}</TableHeader>
</TableRow>
{activeWorkspace.featureFlags.map((flag) => (

View File

@ -1,4 +1,5 @@
import { Button, IconDeviceFloppy } from 'twenty-ui';
import { t } from '@lingui/core/macro';
type SaveButtonProps = {
onSave?: () => void;
@ -8,7 +9,7 @@ type SaveButtonProps = {
export const SaveButton = ({ onSave, disabled }: SaveButtonProps) => {
return (
<Button
title="Save"
title={t`Save`}
variant="primary"
size="small"
accent="blue"

View File

@ -10,6 +10,7 @@ import { useLocation, useParams, useSearchParams } from 'react-router-dom';
import { isDefined } from 'twenty-shared';
import { Button, IconChevronDown, MenuItem } from 'twenty-ui';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { t } from '@lingui/core/macro';
const StyledContainer = styled.div`
align-items: center;
@ -100,9 +101,9 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
<StyledButtonContainer>
<StyledDownChevron size={theme.icon.size.md} />
{isConfigureStep ? (
<StyledButton variant="tertiary" title="2. Configure" />
<StyledButton variant="tertiary" title={t`2. Configure`} />
) : (
<StyledButton variant="tertiary" title="1. Type" />
<StyledButton variant="tertiary" title={t`1. Type`} />
)}
</StyledButtonContainer>
}
@ -111,14 +112,14 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
<DropdownMenuItemsContainer>
<StyledMenuItemWrapper>
<StyledMenuItem
text="1. Type"
text={t`1. Type`}
onClick={() => handleClick('select')}
selected={!isConfigureStep}
/>
</StyledMenuItemWrapper>
<StyledMenuItemWrapper disabled={!isDefined(fieldType)}>
<StyledMenuItem
text="2. Configure"
text={t`2. Configure`}
onClick={() => handleClick('configure')}
selected={isConfigureStep}
disabled={!isDefined(fieldType)}

View File

@ -9,6 +9,7 @@ import { IconCircleOff, IconComponentProps, IconMap } from 'twenty-ui';
import { z } from 'zod';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
import { useLingui } from '@lingui/react/macro';
type SettingsDataModelFieldAddressFormProps = {
disabled?: boolean;
defaultCountry?: string;
@ -30,6 +31,7 @@ export const SettingsDataModelFieldAddressForm = ({
disabled,
fieldMetadataItem,
}: SettingsDataModelFieldAddressFormProps) => {
const { t } = useLingui();
const { control } = useFormContext<SettingsDataModelFieldTextFormValues>();
const countries = [
{
@ -71,8 +73,8 @@ export const SettingsDataModelFieldAddressForm = ({
return (
<SettingsOptionCardContentSelect
Icon={IconMap}
title="Default Country"
description="The default country for new addresses"
title={t`Default Country`}
description={t`The default country for new addresses`}
>
<Select<string>
dropdownWidth={220}

View File

@ -6,6 +6,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { useBooleanSettingsFormInitialValues } from '@/settings/data-model/fields/forms/boolean/hooks/useBooleanSettingsFormInitialValues';
import { Select } from '@/ui/input/components/Select';
import { useLingui } from '@lingui/react/macro';
export const settingsDataModelFieldBooleanFormSchema = z.object({
defaultValue: z.boolean(),
@ -22,6 +23,7 @@ type SettingsDataModelFieldBooleanFormProps = {
export const SettingsDataModelFieldBooleanForm = ({
fieldMetadataItem,
}: SettingsDataModelFieldBooleanFormProps) => {
const { t } = useLingui();
const { control } = useFormContext<SettingsDataModelFieldBooleanFormValues>();
const { initialDefaultValue } = useBooleanSettingsFormInitialValues({
@ -36,8 +38,8 @@ export const SettingsDataModelFieldBooleanForm = ({
render={({ field: { onChange, value } }) => (
<SettingsOptionCardContentSelect
Icon={IconCheck}
title="Default Value"
description="Select the default value for this boolean field"
title={t`Default Value`}
description={t`Select the default value for this boolean field`}
>
<Select<boolean>
value={value}
@ -48,12 +50,12 @@ export const SettingsDataModelFieldBooleanForm = ({
options={[
{
value: true,
label: 'True',
label: t`True`,
Icon: IconCheck,
},
{
value: false,
label: 'False',
label: t`False`,
Icon: IconX,
},
]}

View File

@ -5,6 +5,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema';
import { TextArea } from '@/ui/input/components/TextArea';
import { t } from '@lingui/core/macro';
export const settingsDataModelFieldDescriptionFormSchema = () => {
return fieldMetadataItemSchema([]).pick({
@ -35,7 +36,7 @@ export const SettingsDataModelFieldDescriptionForm = ({
defaultValue={fieldMetadataItem?.description}
render={({ field: { onChange, value } }) => (
<TextArea
placeholder="Write a description"
placeholder={t`Write a description`}
minRows={4}
value={value ?? undefined}
onChange={onChange}

View File

@ -20,6 +20,7 @@ import { H2Title, IconSearch, UndecoratedLink } from 'twenty-ui';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { SettingsDataModelFieldTypeFormValues } from '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldSelect';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { t } from '@lingui/core/macro';
type SettingsObjectNewFieldSelectorProps = {
className?: string;
@ -107,7 +108,7 @@ export const SettingsObjectNewFieldSelector = ({
<Section>
<StyledSearchInput
LeftIcon={IconSearch}
placeholder="Search a type"
placeholder={t`Search a type`}
value={searchQuery}
onChange={setSearchQuery}
/>

View File

@ -5,6 +5,7 @@ import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsO
import { Select } from '@/ui/input/components/Select';
import { IconTextWrap } from 'twenty-ui';
import { z } from 'zod';
import { t } from '@lingui/core/macro';
type SettingsDataModelFieldTextFormProps = {
disabled?: boolean;
@ -45,8 +46,8 @@ export const SettingsDataModelFieldTextForm = ({
<>
<SettingsOptionCardContentSelect
Icon={IconTextWrap}
title="Wrap on record pages"
description="Display text on multiple lines"
title={t`Wrap on record pages`}
description={t`Display text on multiple lines`}
>
<Select<number>
dropdownId="text-wrap"
@ -55,23 +56,23 @@ export const SettingsDataModelFieldTextForm = ({
disabled={disabled}
options={[
{
label: 'Deactivated',
label: t`Deactivated`,
value: 0,
},
{
label: 'First 2 lines',
label: t`First 2 lines`,
value: 2,
},
{
label: 'First 5 lines',
label: t`First 5 lines`,
value: 5,
},
{
label: 'First 10 lines',
label: t`First 10 lines`,
value: 10,
},
{
label: 'All lines',
label: t`All lines`,
value: 99,
},
]}

View File

@ -9,6 +9,7 @@ import { useCurrencySettingsFormInitialValues } from '@/settings/data-model/fiel
import { Select } from '@/ui/input/components/Select';
import { IconCurrencyDollar } from 'twenty-ui';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
import { useLingui } from '@lingui/react/macro';
export const settingsDataModelFieldCurrencyFormSchema = z.object({
defaultValue: currencyFieldDefaultValueSchema,
@ -35,6 +36,7 @@ export const SettingsDataModelFieldCurrencyForm = ({
disabled,
fieldMetadataItem,
}: SettingsDataModelFieldCurrencyFormProps) => {
const { t } = useLingui();
const { control } =
useFormContext<SettingsDataModelFieldCurrencyFormValues>();
@ -56,8 +58,8 @@ export const SettingsDataModelFieldCurrencyForm = ({
render={({ field: { onChange, value } }) => (
<SettingsOptionCardContentSelect
Icon={IconCurrencyDollar}
title="Default Value"
description="Choose the default currency that will apply"
title={t`Default Value`}
description={t`Choose the default currency that will apply`}
>
<Select<string>
dropdownWidth={220}

View File

@ -9,6 +9,7 @@ import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsO
import { Select } from '@/ui/input/components/Select';
import { IconDecimal, IconEye, IconNumber9, IconPercentage } from 'twenty-ui';
import { DEFAULT_DECIMAL_VALUE } from '~/utils/format/number';
import { t } from '@lingui/core/macro';
export const settingsDataModelFieldNumberFormSchema = z.object({
settings: numberFieldDefaultValueSchema,
@ -49,8 +50,8 @@ export const SettingsDataModelFieldNumberForm = ({
<>
<SettingsOptionCardContentSelect
Icon={IconEye}
title="Number type"
description="Display as a plain number or a percentage"
title={t`Number type`}
description={t`Display as a plain number or a percentage`}
>
<Select<string>
selectSizeVariant="small"
@ -63,12 +64,12 @@ export const SettingsDataModelFieldNumberForm = ({
options={[
{
Icon: IconNumber9,
label: 'Number',
label: t`Number`,
value: 'number',
},
{
Icon: IconPercentage,
label: 'Percentage',
label: t`Percentage`,
value: 'percentage',
},
]}
@ -77,7 +78,7 @@ export const SettingsDataModelFieldNumberForm = ({
<Separator />
<SettingsOptionCardContentCounter
Icon={IconDecimal}
title="Number of decimals"
title={t`Number of decimals`}
description={`E.g. ${(type === 'percentage' ? 99 : 1000).toFixed(count)}${type === 'percentage' ? '%' : ''} for ${count} decimal${count > 1 ? 's' : ''}`}
value={count}
onChange={(value) => onChange({ type: type, decimals: value })}

View File

@ -11,6 +11,7 @@ import { IconCircleOff, IconComponentProps, IconMap } from 'twenty-ui';
import { z } from 'zod';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
import { useLingui } from '@lingui/react/macro';
type SettingsDataModelFieldPhonesFormProps = {
disabled?: boolean;
@ -35,10 +36,11 @@ export const SettingsDataModelFieldPhonesForm = ({
disabled,
fieldMetadataItem,
}: SettingsDataModelFieldPhonesFormProps) => {
const { t } = useLingui();
const { control } = useFormContext<SettingsDataModelFieldTextFormValues>();
const countries = [
{ label: 'No country', value: '', Icon: IconCircleOff },
{ label: t`No country`, value: '', Icon: IconCircleOff },
...useCountries()
.sort((a, b) => a.countryName.localeCompare(b.countryName))
.map((country) => ({
@ -68,8 +70,8 @@ export const SettingsDataModelFieldPhonesForm = ({
return (
<SettingsOptionCardContentSelect
Icon={IconMap}
title="Default Country Code"
description="The default country code for new phone numbers."
title={t`Default Country Code`}
description={t`The default country code for new phone numbers.`}
>
<Select<string>
dropdownWidth={'auto'}

View File

@ -17,6 +17,7 @@ import { Select } from '@/ui/input/components/Select';
import { TextInput } from '@/ui/input/components/TextInput';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { RelationDefinitionType } from '~/generated-metadata/graphql';
import { useLingui } from '@lingui/react/macro';
export const settingsDataModelFieldRelationFormSchema = z.object({
relation: z.object({
@ -93,6 +94,7 @@ export const SettingsDataModelFieldRelationForm = ({
fieldMetadataItem,
objectMetadataItem,
}: SettingsDataModelFieldRelationFormProps) => {
const { t } = useLingui();
const { control, watch: watchFormValue } =
useFormContext<SettingsDataModelFieldRelationFormValues>();
const { getIcon } = useIcons();
@ -133,7 +135,7 @@ export const SettingsDataModelFieldRelationForm = ({
defaultValue={initialRelationType}
render={({ field: { onChange, value } }) => (
<Select
label="Relation type"
label={t`Relation type`}
dropdownId="relation-type-select"
fullWidth
disabled={disableRelationEdition}
@ -149,7 +151,7 @@ export const SettingsDataModelFieldRelationForm = ({
defaultValue={initialRelationObjectMetadataItem.id}
render={({ field: { onChange, value } }) => (
<Select
label="Object destination"
label={t`Object destination`}
dropdownId="object-destination-select"
fullWidth
disabled={disableRelationEdition}
@ -194,7 +196,7 @@ export const SettingsDataModelFieldRelationForm = ({
render={({ field: { onChange, value } }) => (
<TextInput
disabled={disableFieldEdition}
placeholder="Field name"
placeholder={t`Field name`}
value={value}
onChange={onChange}
fullWidth

View File

@ -32,6 +32,7 @@ import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsW
import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
import { useRecoilValue } from 'recoil';
import { SettingsDataModelFieldSelectFormOptionRow } from './SettingsDataModelFieldSelectFormOptionRow';
import { t } from '@lingui/core/macro';
export const settingsDataModelFieldSelectFormSchema = z.object({
defaultValue: selectFieldDefaultValueSchema(),
@ -259,13 +260,13 @@ export const SettingsDataModelFieldSelectForm = ({
fill={MAIN_COLORS.yellow}
/>
</StyledIconContainer>
<StyledApiKey>API values</StyledApiKey>
<StyledApiKey>{t`API values`}</StyledApiKey>
</StyledApiKeyContainer>
</AdvancedSettingsWrapper>
<StyledOptionsLabel
isAdvancedModeEnabled={isAdvancedModeEnabled}
>
Options
{t`Options`}
</StyledOptionsLabel>
</StyledLabelContainer>
<DraggableList
@ -331,7 +332,7 @@ export const SettingsDataModelFieldSelectForm = ({
</StyledContainer>
<StyledFooter>
<StyledButton
title="Add option"
title={t`Add option`}
Icon={IconPlus}
onClick={handleAddOption}
/>

View File

@ -21,6 +21,7 @@ import {
MenuItemSelectColor,
} from 'twenty-ui';
import { computeOptionValueFromLabel } from '~/pages/settings/data-model/utils/compute-option-value-from-label.utils';
import { t } from '@lingui/core/macro';
type SettingsDataModelFieldSelectFormOptionRowProps = {
className?: string;
@ -168,7 +169,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
{isDefault ? (
<MenuItem
LeftIcon={IconX}
text="Remove as default"
text={t`Remove as default`}
onClick={() => {
onRemoveAsDefault?.();
closeActionsDropdown();
@ -177,7 +178,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
) : (
<MenuItem
LeftIcon={IconCheck}
text="Set as default"
text={t`Set as default`}
onClick={() => {
onSetAsDefault?.();
closeActionsDropdown();
@ -188,7 +189,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
<MenuItem
accent="danger"
LeftIcon={IconTrash}
text="Remove option"
text={t`Remove option`}
onClick={() => {
onRemove();
closeActionsDropdown();

View File

@ -12,6 +12,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { t } from '@lingui/core/macro';
type SettingsObjectFieldInactiveActionDropdownProps = {
isCustomField?: boolean;
@ -64,18 +65,18 @@ export const SettingsObjectFieldInactiveActionDropdown = ({
dropdownComponents={
<DropdownMenuItemsContainer>
<MenuItem
text={isCustomField ? 'Edit' : 'View'}
text={isCustomField ? t`Edit` : t`View`}
LeftIcon={isCustomField ? IconPencil : IconEye}
onClick={handleEdit}
/>
<MenuItem
text="Activate"
text={t`Activate`}
LeftIcon={IconArchiveOff}
onClick={handleActivate}
/>
{isDeletable && (
<MenuItem
text="Delete"
text={t`Delete`}
accent="danger"
LeftIcon={IconTrash}
onClick={handleDelete}

View File

@ -1,5 +1,4 @@
import { Tag } from 'twenty-ui';
import { ObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
type SettingsDataModelObjectTypeTagProps = {

View File

@ -147,7 +147,7 @@ export const SettingsDataModelObjectAboutForm = ({
<>
<StyledInputsContainer>
<StyledInputContainer>
<StyledLabel>Icon</StyledLabel>
<StyledLabel>{t`Icon`}</StyledLabel>
<Controller
name="icon"
control={control}
@ -171,7 +171,7 @@ export const SettingsDataModelObjectAboutForm = ({
defaultValue={objectMetadataItem?.labelSingular}
render={({ field: { onChange, value } }) => (
<TextInput
label={'Singular'}
label={t`Singular`}
placeholder={'Listing'}
value={value}
onChange={(value) => {

View File

@ -9,6 +9,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems';
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
import { Select, SelectOption } from '@/ui/input/components/Select';
import { t } from '@lingui/core/macro';
export const settingsDataModelObjectIdentifiersFormSchema =
objectMetadataItemSchema.pick({
@ -68,13 +69,13 @@ export const SettingsDataModelObjectIdentifiersForm = ({
<StyledContainer>
{[
{
label: 'Record label',
label: t`Record label`,
fieldName: LABEL_IDENTIFIER_FIELD_METADATA_ID,
options: labelIdentifierFieldOptions,
defaultValue: objectMetadataItem.labelIdentifierFieldMetadataId,
},
{
label: 'Record image',
label: t`Record image`,
fieldName: IMAGE_IDENTIFIER_FIELD_METADATA_ID,
options: imageIdentifierFieldOptions,
defaultValue: null,

View File

@ -5,6 +5,7 @@ import { Button, IconCopy } from 'twenty-ui';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { TextInput } from '@/ui/input/components/TextInput';
import { useLingui } from '@lingui/react/macro';
const StyledContainer = styled.div`
display: flex;
@ -30,7 +31,7 @@ export const ApiKeyInput = ({ apiKey }: ApiKeyInputProps) => {
</StyledLinkContainer>
<Button
Icon={IconCopy}
title="Copy"
title={t`Copy`}
onClick={() => {
enqueueSnackBar(t`API Key copied to clipboard`, {
variant: SnackBarVariant.Success,

View File

@ -10,6 +10,7 @@ import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import styled from '@emotion/styled';
import { MOBILE_VIEWPORT } from 'twenty-ui';
import { Trans } from '@lingui/react/macro';
const StyledTableBody = styled(TableBody)`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
@ -38,8 +39,12 @@ export const SettingsApiKeysTable = () => {
return (
<Table>
<StyledTableRow>
<TableHeader>Name</TableHeader>
<TableHeader>Expiration</TableHeader>
<TableHeader>
<Trans>Name</Trans>
</TableHeader>
<TableHeader>
<Trans>Expiration</Trans>
</TableHeader>
<TableHeader></TableHeader>
</StyledTableRow>
{!!apiKeys.length && (

View File

@ -27,7 +27,7 @@ export const SettingsWebhooksTable = () => {
return (
<Table>
<StyledTableRow>
<TableHeader>Url</TableHeader>
<TableHeader>URL</TableHeader>
<TableHeader></TableHeader>
</StyledTableRow>
{!!webhooks.length && (

View File

@ -1,3 +1,4 @@
import { useLingui } from '@lingui/react/macro';
import { useEffect, useState } from 'react';
import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil';
@ -29,6 +30,7 @@ export const NameFields = ({
onFirstNameUpdate,
onLastNameUpdate,
}: NameFieldsProps) => {
const { t } = useLingui();
const currentUser = useRecoilValue(currentUserState);
const [currentWorkspaceMember, setCurrentWorkspaceMember] = useRecoilState(
currentWorkspaceMemberState,
@ -110,14 +112,14 @@ export const NameFields = ({
return (
<StyledComboInputContainer>
<TextInput
label="First Name"
label={t`First Name`}
value={firstName}
onChange={setFirstName}
placeholder="Tim"
fullWidth
/>
<TextInput
label="Last Name"
label={t`Last Name`}
value={lastName}
onChange={setLastName}
placeholder="Cook"

View File

@ -11,6 +11,7 @@ import { ReactElement, useMemo } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { H2Title, IconComponent, IconKey, Section } from 'twenty-ui';
import { IdentityProviderType } from '~/generated/graphql';
import { t } from '@lingui/core/macro';
const StyledInputsContainer = styled.div`
display: grid;
@ -79,7 +80,7 @@ export const SettingsSSOIdentitiesProvidersForm = () => {
return (
<SettingsPageContainer>
<Section>
<H2Title title="Name" description="The name of your connection" />
<H2Title title={t`Name`} description={t`The name of your connection`} />
<StyledInputsContainer>
<Controller
name="name"
@ -87,7 +88,7 @@ export const SettingsSSOIdentitiesProvidersForm = () => {
render={({ field: { onChange, value } }) => (
<TextInput
autoComplete="off"
label="Name"
label={t`Name`}
value={value}
onChange={onChange}
fullWidth
@ -99,8 +100,8 @@ export const SettingsSSOIdentitiesProvidersForm = () => {
</Section>
<Section>
<H2Title
title="Type"
description="Choose between OIDC and SAML protocols"
title={t`Type`}
description={t`Choose between OIDC and SAML protocols`}
/>
<StyledInputsContainer>
<Controller

View File

@ -53,7 +53,7 @@ export const SettingsSSOOIDCForm = () => {
<StyledLinkContainer>
<TextInput
readOnly={true}
label="Authorized URI"
label={t`Authorized URI`}
value={authorizedUrl}
fullWidth
/>
@ -63,7 +63,7 @@ export const SettingsSSOOIDCForm = () => {
Icon={IconCopy}
title={t`Copy`}
onClick={() => {
enqueueSnackBar('Authorized Url copied to clipboard', {
enqueueSnackBar(t`Authorized URL copied to clipboard`, {
variant: SnackBarVariant.Success,
icon: <IconCopy size={theme.icon.size.md} />,
duration: 2000,
@ -111,7 +111,7 @@ export const SettingsSSOOIDCForm = () => {
render={({ field: { onChange, value } }) => (
<TextInput
autoComplete="off"
label="Client ID"
label={t`Client ID`}
value={value}
onChange={onChange}
fullWidth
@ -126,7 +126,7 @@ export const SettingsSSOOIDCForm = () => {
<TextInput
autoComplete="off"
type="password"
label="Client Secret"
label={t`Client Secret`}
value={value}
onChange={onChange}
fullWidth
@ -140,7 +140,7 @@ export const SettingsSSOOIDCForm = () => {
render={({ field: { onChange, value } }) => (
<TextInput
autoComplete="off"
label="Issuer URI"
label={t`Issuer URI`}
value={value}
onChange={onChange}
fullWidth