setup localization for twenty-emails (#9806)

One of the steps to address #8128 

How to test:
Please change the locale in the settings and click on change password
button. A password reset email in the preferred locale will be sent.


![image](https://github.com/user-attachments/assets/2b0c2f81-5c4d-4e49-b021-8ee76e7872f2)

![image](https://github.com/user-attachments/assets/0453e321-e5aa-42ea-beca-86e2e97dbee2)

Todo:
- Remove the hardcoded locales for invitation, warn suspended workspace
email, clean suspended workspace emails
- Need to test invitation, email verification, warn suspended workspace
email, clean suspended workspace emails
- The duration variable `5 minutes` is always in english. Do we need to
do something about that? It does seems odd in case of chinese
translations.

Notes:
- Only tested the password reset , password update notify templates.
- Cant test email verification due to error during sign up `Internal
server error: New workspace setup is disabled`

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Anne Deepa Prasanna
2025-02-03 01:31:34 +05:30
committed by GitHub
parent 4b9414a002
commit 39e7f6cec3
58 changed files with 1752 additions and 344 deletions

View File

@ -44,8 +44,8 @@
"@octokit/graphql": "^7.0.2",
"@ptc-org/nestjs-query-core": "^4.2.0",
"@ptc-org/nestjs-query-typeorm": "4.2.1-alpha.2",
"@react-email/components": "0.0.12",
"@react-email/render": "0.0.10",
"@react-email/components": "0.0.32",
"@react-email/render": "0.0.17",
"@sentry/node": "^8",
"@sentry/profiling-node": "^8",
"@sentry/react": "^8",

View File

@ -0,0 +1,18 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"jsc": {
"experimental": {
"plugins": [
[
"@lingui/swc-plugin",
{
"runtimeModules": {
"i18n": ["@lingui/core", "i18n"],
"trans": ["@lingui/react", "Trans"]
}
}
]
]
}
}
}

View File

@ -0,0 +1,30 @@
import { defineConfig } from '@lingui/cli';
import { APP_LOCALES } from 'twenty-shared';
export default defineConfig({
sourceLocale: 'en',
locales: Object.values(APP_LOCALES),
pseudoLocale: 'pseudo-en',
fallbackLocales: {
'pseudo-en': 'en',
},
extractorParserOptions: {
tsExperimentalDecorators: true,
},
catalogs: [
{
path: '<rootDir>/src/locales/{locale}',
include: ['src'],
},
],
catalogsMergePath: '<rootDir>/src/locales/generated/{locale}',
compileNamespace: 'ts',
...(process.env.TRANSLATION_IO_API_KEY_EMAILS
? {
service: {
name: 'TranslationIO',
apiKey: process.env.TRANSLATION_IO_API_KEY_EMAILS,
},
}
: {}),
});

View File

@ -12,7 +12,8 @@
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"engines": {

View File

@ -30,6 +30,20 @@
"configurations": {
"fix": {}
}
},
"lingui:extract": {
"executor": "nx:run-commands",
"options": {
"cwd": "{projectRoot}",
"command": "lingui extract --overwrite"
}
},
"lingui:compile": {
"executor": "nx:run-commands",
"options": {
"cwd": "{projectRoot}",
"command": "lingui compile --typescript"
}
}
}
}

View File

@ -1,21 +1,56 @@
import { PropsWithChildren } from 'react';
import { i18n } from '@lingui/core';
import { I18nProvider } from '@lingui/react';
import { Container, Html } from '@react-email/components';
import { PropsWithChildren } from 'react';
import { BaseHead } from 'src/components/BaseHead';
import { Logo } from 'src/components/Logo';
import { APP_LOCALES } from 'twenty-shared';
import { messages as deMessages } from '../locales/generated/de';
import { messages as enMessages } from '../locales/generated/en';
import { messages as esMessages } from '../locales/generated/es';
import { messages as frMessages } from '../locales/generated/fr';
import { messages as itMessages } from '../locales/generated/it';
import { messages as jaMessages } from '../locales/generated/ja';
import { messages as koMessages } from '../locales/generated/ko';
import { messages as pseudoEnMessages } from '../locales/generated/pseudo-en';
import { messages as ptBRMessages } from '../locales/generated/pt-BR';
import { messages as ptPTMessages } from '../locales/generated/pt-PT';
import { messages as zhHansMessages } from '../locales/generated/zh-Hans';
import { messages as zhHantMessages } from '../locales/generated/zh-Hant';
type BaseEmailProps = PropsWithChildren<{
width?: number;
locale: keyof typeof APP_LOCALES;
}>;
export const BaseEmail = ({ children, width }: BaseEmailProps) => {
i18n.load('en', enMessages);
i18n.load('fr', frMessages);
i18n.load('pseudo-en', pseudoEnMessages);
i18n.load('ko', koMessages);
i18n.load('de', deMessages);
i18n.load('it', itMessages);
i18n.load('es', esMessages);
i18n.load('ja', jaMessages);
i18n.load('pt-PT', ptPTMessages);
i18n.load('pt-BR', ptBRMessages);
i18n.load('zh-Hans', zhHansMessages);
i18n.load('zh-Hant', zhHantMessages);
i18n.activate('en');
export const BaseEmail = ({ children, width, locale }: BaseEmailProps) => {
i18n.activate(locale);
return (
<Html lang="en">
<BaseHead />
<Container width={width || 290}>
<Logo />
{children}
</Container>
</Html>
<I18nProvider i18n={i18n}>
<Html lang={locale}>
<BaseHead />
<Container width={width || 290}>
<Logo />
{children}
</Container>
</Html>
</I18nProvider>
);
};

View File

@ -1,3 +1,4 @@
import { Trans } from '@lingui/react/macro';
import { BaseEmail } from 'src/components/BaseEmail';
import { CallToAction } from 'src/components/CallToAction';
import { MainText } from 'src/components/MainText';
@ -17,20 +18,24 @@ export const CleanSuspendedWorkspaceEmail = ({
const helloString = userName?.length > 1 ? `Hello ${userName}` : 'Hello';
return (
<BaseEmail width={333}>
<BaseEmail width={333} locale="en">
<Title value="Deleted Workspace 🥺" />
<MainText>
{helloString},
<br />
<br />
Your workspace <b>{workspaceDisplayName}</b> has been deleted as your
subscription expired {inactiveDaysBeforeDelete} days ago.
<Trans>
Your workspace <b>{workspaceDisplayName}</b> has been deleted as your
subscription expired {inactiveDaysBeforeDelete} days ago.
</Trans>
<br />
<br />
All data in this workspace has been permanently deleted.
<Trans>All data in this workspace has been permanently deleted.</Trans>
<br />
<br />
If you wish to use Twenty again, you can create a new workspace.
<Trans>
If you wish to use Twenty again, you can create a new workspace.
</Trans>
</MainText>
<CallToAction
href="https://app.twenty.com/"

View File

@ -1,25 +1,32 @@
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { BaseEmail } from 'src/components/BaseEmail';
import { CallToAction } from 'src/components/CallToAction';
import { Link } from 'src/components/Link';
import { MainText } from 'src/components/MainText';
import { Title } from 'src/components/Title';
import { APP_LOCALES } from 'twenty-shared';
type PasswordResetLinkEmailProps = {
duration: string;
link: string;
locale: keyof typeof APP_LOCALES;
};
export const PasswordResetLinkEmail = ({
duration,
link,
locale,
}: PasswordResetLinkEmailProps) => {
return (
<BaseEmail>
<Title value="Reset your password 🗝" />
<CallToAction href={link} value="Reset" />
<BaseEmail locale={locale}>
<Title value={t`Reset your password 🗝`} />
<CallToAction href={link} value={t`Reset`} />
<MainText>
This link is only valid for the next {duration}. If link does not work,
you can use the login verification link directly:
<Trans>
This link is only valid for the next {duration}. If the link does not
work, you can use the login verification link directly:
</Trans>
<br />
<Link href={link} value={link} />
</MainText>

View File

@ -1,38 +1,49 @@
import { format } from 'date-fns';
import { i18n } from '@lingui/core';
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { BaseEmail } from 'src/components/BaseEmail';
import { CallToAction } from 'src/components/CallToAction';
import { MainText } from 'src/components/MainText';
import { Title } from 'src/components/Title';
import { APP_LOCALES } from 'twenty-shared';
type PasswordUpdateNotifyEmailProps = {
userName: string;
email: string;
link: string;
locale: keyof typeof APP_LOCALES;
};
export const PasswordUpdateNotifyEmail = ({
userName,
email,
link,
locale,
}: PasswordUpdateNotifyEmailProps) => {
const helloString = userName?.length > 1 ? `Dear ${userName}` : 'Dear';
const helloString = userName?.length > 1 ? t`Dear ${userName}` : t`Hello`;
const formattedDate = i18n.date(new Date());
return (
<BaseEmail>
<Title value="Password updated" />
<BaseEmail locale={locale}>
<Title value={t`Password updated`} />
<MainText>
{helloString},
<br />
<br />
This is a confirmation that password for your account ({email}) was
successfully changed on {format(new Date(), 'MMMM d, yyyy')}.
<Trans>
This is a confirmation that password for your account ({email}) was
successfully changed on {formattedDate}.
</Trans>
<br />
<br />
If you did not initiate this change, please contact your workspace owner
immediately.
<Trans>
If you did not initiate this change, please contact your workspace
owner immediately.
</Trans>
<br />
</MainText>
<CallToAction value="Connect to Twenty" href={link} />
<CallToAction value={t`Connect to Twenty`} href={link} />
</BaseEmail>
);
};

View File

@ -1,26 +1,34 @@
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { BaseEmail } from 'src/components/BaseEmail';
import { CallToAction } from 'src/components/CallToAction';
import { Footer } from 'src/components/Footer';
import { MainText } from 'src/components/MainText';
import { Title } from 'src/components/Title';
import { APP_LOCALES } from 'twenty-shared';
type SendEmailVerificationLinkEmailProps = {
link: string;
locale: keyof typeof APP_LOCALES;
};
export const SendEmailVerificationLinkEmail = ({
link,
locale,
}: SendEmailVerificationLinkEmailProps) => {
return (
<BaseEmail width={333}>
<Title value="Confirm your email address" />
<CallToAction href={link} value="Verify Email" />
<BaseEmail width={333} locale={locale}>
<Title value={t`Confirm your email address`} />
<CallToAction href={link} value={t`Verify Email`} />
<br />
<br />
<MainText>
Thanks for registering for an account on Twenty! Before we get started,
we just need to confirm that this is you. Click above to verify your
email address.
<Trans>
Thanks for registering for an account on Twenty! Before we get
started, we just need to confirm that this is you. Click above to
verify your email address.
</Trans>
</MainText>
<Footer />
</BaseEmail>

View File

@ -1,3 +1,5 @@
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Img } from '@react-email/components';
import { emailTheme } from 'src/common-style';
@ -10,7 +12,7 @@ import { MainText } from 'src/components/MainText';
import { Title } from 'src/components/Title';
import { WhatIsTwenty } from 'src/components/WhatIsTwenty';
import { capitalize } from 'src/utils/capitalize';
import { getImageAbsoluteURI } from 'twenty-shared';
import { APP_LOCALES, getImageAbsoluteURI } from 'twenty-shared';
type SendInviteLinkEmailProps = {
link: string;
@ -21,6 +23,7 @@ type SendInviteLinkEmailProps = {
lastName: string;
};
serverUrl: string;
locale: keyof typeof APP_LOCALES;
};
export const SendInviteLinkEmail = ({
@ -28,14 +31,15 @@ export const SendInviteLinkEmail = ({
workspace,
sender,
serverUrl,
locale,
}: SendInviteLinkEmailProps) => {
const workspaceLogo = workspace.logo
? getImageAbsoluteURI({ imageUrl: workspace.logo, baseUrl: serverUrl })
: null;
return (
<BaseEmail width={333}>
<Title value="Join your team on Twenty" />
<BaseEmail width={333} locale={locale}>
<Title value={t`Join your team on Twenty`} />
<MainText>
{capitalize(sender.firstName)} (
<Link
@ -43,13 +47,14 @@ export const SendInviteLinkEmail = ({
value={sender.email}
color={emailTheme.font.colors.blue}
/>
) has invited you to join a workspace called <b>{workspace.name}</b>
)<Trans>has invited you to join a workspace called </Trans>
<b>{workspace.name}</b>
<br />
</MainText>
<HighlightedContainer>
{workspaceLogo && <Img src={workspaceLogo} width={40} height={40} />}
{workspace.name && <HighlightedText value={workspace.name} />}
<CallToAction href={link} value="Accept invite" />
<CallToAction href={link} value={t`Accept invite`} />
</HighlightedContainer>
<WhatIsTwenty />
</BaseEmail>

View File

@ -1,3 +1,5 @@
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { BaseEmail } from 'src/components/BaseEmail';
import { CallToAction } from 'src/components/CallToAction';
import { MainText } from 'src/components/MainText';
@ -23,26 +25,32 @@ export const WarnSuspendedWorkspaceEmail = ({
const helloString = userName?.length > 1 ? `Hello ${userName}` : 'Hello';
return (
<BaseEmail width={333}>
<BaseEmail width={333} locale="en">
<Title value="Suspended Workspace 😴" />
<MainText>
{helloString},
<br />
<br />
It appears that your workspace <b>{workspaceDisplayName}</b> has been
suspended for {daysSinceInactive} days.
<Trans>
It appears that your workspace <b>{workspaceDisplayName}</b> has been
suspended for {daysSinceInactive} days.
</Trans>
<br />
<br />
The workspace will be deactivated in {remainingDays} {dayOrDays}, and
all its data will be deleted.
<Trans>
The workspace will be deactivated in {remainingDays} {dayOrDays}, and
all its data will be deleted.
</Trans>
<br />
<br />
If you wish to continue using Twenty, please update your subscription
within the next {remainingDays} {dayOrDays}.
<Trans>
If you wish to continue using Twenty, please update your subscription
within the next {remainingDays} {dayOrDays}.
</Trans>
</MainText>
<CallToAction
href="https://app.twenty.com/settings/billing"
value="Update your subscription"
value={t`Update your subscription`}
/>
</BaseEmail>
);

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: de\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Einladung annehmen"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "Alle Daten in diesem Arbeitsbereich wurden endgültig gelöscht."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Bestätigen Sie Ihre E-Mail Adresse"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Verbindung zu Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Sehr geehrter {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Hallo"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "Wenn Sie diese Änderung nicht veranlasst haben, wenden Sie sich bitte umgehend an den Eigentümer Ihres Arbeitsbereichs."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Wenn Sie Twenty weiterhin nutzen möchten, aktualisieren Sie Ihr Abonnement bitte innerhalb der nächsten {remainingDays} {dayOrDays}."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Wenn Sie Twenty wieder verwenden möchten, können Sie einen neuen Arbeitsbereich erstellen."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "Es scheint, dass Ihr Arbeitsbereich <0>{workspaceDisplayName}</0> für {daysSinceInactive} Tage gesperrt wurde."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Verbinden Sie Ihr Team auf Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Passwort aktualisiert"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Zurücksetzen"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Ihr Passwort zurücksetzen 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Vielen Dank, dass Sie sich für ein Konto bei Twenty registriert haben! Bevor wir loslegen, müssen wir nur bestätigen, dass Sie es sind. Klicken Sie oben, um Ihre E-Mail-Adresse zu bestätigen."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "Der Arbeitsbereich wird in {remainingDays} {dayOrDays} deaktiviert, und alle seine Daten werden gelöscht."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "Dies ist eine Bestätigung, dass das Passwort für Ihr Konto ({email}) erfolgreich am {formattedDate} geändert wurde."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "Dieser Link ist nur für den nächsten {duration} gültig. Wenn der Link nicht funktioniert, können Sie direkt den Link zur Überprüfung der Anmeldung verwenden:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Aktualisieren Sie Ihr Abonnement"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "E-Mail verifizieren"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "Ihr Arbeitsbereich <0>{workspaceDisplayName}</0> wurde gelöscht, da Ihr Abonnement vor {inactiveDaysBeforeDelete} Tagen abgelaufen ist."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "hat Sie eingeladen, an einem Arbeitsbereich namens "

View File

@ -0,0 +1,114 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 18:53+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Accept invite"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "All data in this workspace has been permanently deleted."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Confirm your email address"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Connect to Twenty"
#: src/emails/password-update-notify.email.tsx:24
#~ msgid "Dear"
#~ msgstr "Dear"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Dear {userName}"
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "has invited you to join a workspace called "
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Hello"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "If you did not initiate this change, please contact your workspace owner immediately."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "If you wish to use Twenty again, you can create a new workspace."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Join your team on Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Password updated"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Reset"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Reset your password 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
#: src/emails/password-update-notify.email.tsx:36
#~ msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}.<0/><1/>If you did not initiate this change, please contact your workspace owner immediately."
#~ msgstr "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}.<0/><1/>If you did not initiate this change, please contact your workspace owner immediately."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
#: src/emails/password-reset-link.email.tsx:28
#~ msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:<0/>"
#~ msgstr "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:<0/>"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Update your subscription"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "Verify Email"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: es\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Aceptar invitación"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "Todos los datos de este espacio de trabajo se han eliminado permanentemente."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Confirma tu dirección de correo electrónico"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Conectarse a Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Estimado/a {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Hola"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "Si usted no ha iniciado este cambio, póngase en contacto inmediatamente con el propietario de su espacio de trabajo."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Si desea seguir utilizando Twenty, actualice su suscripción en los próximos {remainingDays} {dayOrDays}."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Si deseas volver a utilizar Twenty, puedes crear un nuevo espacio de trabajo."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "Parece que su espacio de trabajo <0>{workspaceDisplayName}</0> ha sido suspendido durante {daysSinceInactive} días."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Únete a tu equipo en Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Contraseña actualizada"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Restablecer"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Restablece tu contraseña 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "¡Gracias por registrarte en Twenty! Antes de comenzar, solo necesitamos confirmar que eres tú. Haz clic arriba para verificar tu dirección de correo electrónico."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "El espacio de trabajo se desactivará en {remainingDays} {dayOrDays} y se borrarán todos sus datos."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "Esto es una confirmación de que la contraseña de su cuenta ({email}) se ha cambiado correctamente en {formattedDate}."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "Este enlace sólo es válido para el próximo {duration}. Si el enlace no funciona, puede utilizar directamente el enlace de verificación de inicio de sesión:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Actualice su suscripción"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "Verificar correo electrónico"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "Su espacio de trabajo <0>{workspaceDisplayName}</0> se ha eliminado porque su suscripción caducó hace {inactiveDaysBeforeDelete} días."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "te ha invitado a unirte a un espacio de trabajo llamado "

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fr\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Accepter l'invitation"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "Toutes les données de cet espace de travail ont été définitivement supprimées."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Confirmez votre adresse email"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Connectez-vous à Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Cher(e) {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Bonjour"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "Si vous n'êtes pas à l'origine de ce changement, veuillez contacter immédiatement le propriétaire de votre espace de travail."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Si vous souhaitez continuer à utiliser Twenty, veuillez mettre à jour votre abonnement dans les {remainingDays} {dayOrDays} à venir."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Si vous souhaitez réutiliser Twenty, vous pouvez créer un nouvel espace de travail."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "Il apparaît que votre espace de travail <0>{workspaceDisplayName}</0> a été suspendu pendant {daysSinceInactive} jours."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Rejoignez votre équipe sur Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Mot de passe mis à jour"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Réinitialiser"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Réinitialiser votre mot de passe 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Merci de vous être inscrit sur Twenty! Avant de commencer, nous devons simplement confirmer qu'il s'agit bien de vous. Cliquez ci-dessus pour vérifier votre adresse e-mail."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "L'espace de travail sera désactivé dans {remainingDays} {dayOrDays} et toutes ses données seront supprimées."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "Ceci est une confirmation que le mot de passe de votre compte ({email}) a été modifié avec succès le {formattedDate}."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "Ce lien n'est valable que pour le prochain {duration}. Si le lien ne fonctionne pas, vous pouvez utiliser directement le lien de vérification de la connexion :"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Mise à jour de votre abonnement"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "Vérifier l'e-mail"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "Votre espace de travail <0>{workspaceDisplayName}</0> a été supprimé car votre abonnement a expiré il y a {inactiveDaysBeforeDelete} jours."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "vous a invité à rejoindre un espace de travail appelé"

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Einladung annehmen\"],\"Yxj+Uc\":[\"Alle Daten in diesem Arbeitsbereich wurden endgültig gelöscht.\"],\"RPHFhC\":[\"Bestätigen Sie Ihre E-Mail Adresse\"],\"nvkBPN\":[\"Verbindung zu Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Sehr geehrter \",[\"userName\"]],\"tGme7M\":[\"hat Sie eingeladen, an einem Arbeitsbereich namens \"],\"uzTaYi\":[\"Hallo\"],\"eE1nG1\":[\"Wenn Sie diese Änderung nicht veranlasst haben, wenden Sie sich bitte umgehend an den Eigentümer Ihres Arbeitsbereichs.\"],\"Gz91L8\":[\"Wenn Sie Twenty weiterhin nutzen möchten, aktualisieren Sie Ihr Abonnement bitte innerhalb der nächsten \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"Wenn Sie Twenty wieder verwenden möchten, können Sie einen neuen Arbeitsbereich erstellen.\"],\"7JuhZQ\":[\"Es scheint, dass Ihr Arbeitsbereich <0>\",[\"workspaceDisplayName\"],\"</0> für \",[\"daysSinceInactive\"],\" Tage gesperrt wurde.\"],\"PviVyk\":[\"Verbinden Sie Ihr Team auf Twenty\"],\"ogtYkT\":[\"Passwort aktualisiert\"],\"OfhWJH\":[\"Zurücksetzen\"],\"RE5NiU\":[\"Ihr Passwort zurücksetzen 🗝\"],\"7yDt8q\":[\"Vielen Dank, dass Sie sich für ein Konto bei Twenty registriert haben! Bevor wir loslegen, müssen wir nur bestätigen, dass Sie es sind. Klicken Sie oben, um Ihre E-Mail-Adresse zu bestätigen.\"],\"igorB1\":[\"Der Arbeitsbereich wird in \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" deaktiviert, und alle seine Daten werden gelöscht.\"],\"7OEHy1\":[\"Dies ist eine Bestätigung, dass das Passwort für Ihr Konto (\",[\"email\"],\") erfolgreich am \",[\"formattedDate\"],\" geändert wurde.\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"Dieser Link ist nur für den nächsten \",[\"duration\"],\" gültig. Wenn der Link nicht funktioniert, können Sie direkt den Link zur Überprüfung der Anmeldung verwenden:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Aktualisieren Sie Ihr Abonnement\"],\"wCKkSr\":[\"E-Mail verifizieren\"],\"KFmFrQ\":[\"Ihr Arbeitsbereich <0>\",[\"workspaceDisplayName\"],\"</0> wurde gelöscht, da Ihr Abonnement vor \",[\"inactiveDaysBeforeDelete\"],\" Tagen abgelaufen ist.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Accept invite\"],\"Yxj+Uc\":[\"All data in this workspace has been permanently deleted.\"],\"RPHFhC\":[\"Confirm your email address\"],\"nvkBPN\":[\"Connect to Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Dear \",[\"userName\"]],\"tGme7M\":[\"has invited you to join a workspace called \"],\"uzTaYi\":[\"Hello\"],\"eE1nG1\":[\"If you did not initiate this change, please contact your workspace owner immediately.\"],\"Gz91L8\":[\"If you wish to continue using Twenty, please update your subscription within the next \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"If you wish to use Twenty again, you can create a new workspace.\"],\"7JuhZQ\":[\"It appears that your workspace <0>\",[\"workspaceDisplayName\"],\"</0> has been suspended for \",[\"daysSinceInactive\"],\" days.\"],\"PviVyk\":[\"Join your team on Twenty\"],\"ogtYkT\":[\"Password updated\"],\"OfhWJH\":[\"Reset\"],\"RE5NiU\":[\"Reset your password 🗝\"],\"7yDt8q\":[\"Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address.\"],\"igorB1\":[\"The workspace will be deactivated in \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\", and all its data will be deleted.\"],\"7OEHy1\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Update your subscription\"],\"wCKkSr\":[\"Verify Email\"],\"KFmFrQ\":[\"Your workspace <0>\",[\"workspaceDisplayName\"],\"</0> has been deleted as your subscription expired \",[\"inactiveDaysBeforeDelete\"],\" days ago.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Aceptar invitación\"],\"Yxj+Uc\":[\"Todos los datos de este espacio de trabajo se han eliminado permanentemente.\"],\"RPHFhC\":[\"Confirma tu dirección de correo electrónico\"],\"nvkBPN\":[\"Conectarse a Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Estimado/a \",[\"userName\"]],\"tGme7M\":[\"te ha invitado a unirte a un espacio de trabajo llamado \"],\"uzTaYi\":[\"Hola\"],\"eE1nG1\":[\"Si usted no ha iniciado este cambio, póngase en contacto inmediatamente con el propietario de su espacio de trabajo.\"],\"Gz91L8\":[\"Si desea seguir utilizando Twenty, actualice su suscripción en los próximos \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"Si deseas volver a utilizar Twenty, puedes crear un nuevo espacio de trabajo.\"],\"7JuhZQ\":[\"Parece que su espacio de trabajo <0>\",[\"workspaceDisplayName\"],\"</0> ha sido suspendido durante \",[\"daysSinceInactive\"],\" días.\"],\"PviVyk\":[\"Únete a tu equipo en Twenty\"],\"ogtYkT\":[\"Contraseña actualizada\"],\"OfhWJH\":[\"Restablecer\"],\"RE5NiU\":[\"Restablece tu contraseña 🗝\"],\"7yDt8q\":[\"¡Gracias por registrarte en Twenty! Antes de comenzar, solo necesitamos confirmar que eres tú. Haz clic arriba para verificar tu dirección de correo electrónico.\"],\"igorB1\":[\"El espacio de trabajo se desactivará en \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" y se borrarán todos sus datos.\"],\"7OEHy1\":[\"Esto es una confirmación de que la contraseña de su cuenta (\",[\"email\"],\") se ha cambiado correctamente en \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"Este enlace sólo es válido para el próximo \",[\"duration\"],\". Si el enlace no funciona, puede utilizar directamente el enlace de verificación de inicio de sesión:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Actualice su suscripción\"],\"wCKkSr\":[\"Verificar correo electrónico\"],\"KFmFrQ\":[\"Su espacio de trabajo <0>\",[\"workspaceDisplayName\"],\"</0> se ha eliminado porque su suscripción caducó hace \",[\"inactiveDaysBeforeDelete\"],\" días.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Accepter l'invitation\"],\"Yxj+Uc\":[\"Toutes les données de cet espace de travail ont été définitivement supprimées.\"],\"RPHFhC\":[\"Confirmez votre adresse email\"],\"nvkBPN\":[\"Connectez-vous à Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Cher(e) \",[\"userName\"]],\"tGme7M\":[\"vous a invité à rejoindre un espace de travail appelé\"],\"uzTaYi\":[\"Bonjour\"],\"eE1nG1\":[\"Si vous n'êtes pas à l'origine de ce changement, veuillez contacter immédiatement le propriétaire de votre espace de travail.\"],\"Gz91L8\":[\"Si vous souhaitez continuer à utiliser Twenty, veuillez mettre à jour votre abonnement dans les \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" à venir.\"],\"0weyko\":[\"Si vous souhaitez réutiliser Twenty, vous pouvez créer un nouvel espace de travail.\"],\"7JuhZQ\":[\"Il apparaît que votre espace de travail <0>\",[\"workspaceDisplayName\"],\"</0> a été suspendu pendant \",[\"daysSinceInactive\"],\" jours.\"],\"PviVyk\":[\"Rejoignez votre équipe sur Twenty\"],\"ogtYkT\":[\"Mot de passe mis à jour\"],\"OfhWJH\":[\"Réinitialiser\"],\"RE5NiU\":[\"Réinitialiser votre mot de passe 🗝\"],\"7yDt8q\":[\"Merci de vous être inscrit sur Twenty! Avant de commencer, nous devons simplement confirmer qu'il s'agit bien de vous. Cliquez ci-dessus pour vérifier votre adresse e-mail.\"],\"igorB1\":[\"L'espace de travail sera désactivé dans \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" et toutes ses données seront supprimées.\"],\"7OEHy1\":[\"Ceci est une confirmation que le mot de passe de votre compte (\",[\"email\"],\") a été modifié avec succès le \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"Ce lien n'est valable que pour le prochain \",[\"duration\"],\". Si le lien ne fonctionne pas, vous pouvez utiliser directement le lien de vérification de la connexion :\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Mise à jour de votre abonnement\"],\"wCKkSr\":[\"Vérifier l'e-mail\"],\"KFmFrQ\":[\"Votre espace de travail <0>\",[\"workspaceDisplayName\"],\"</0> a été supprimé car votre abonnement a expiré il y a \",[\"inactiveDaysBeforeDelete\"],\" jours.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Accetta invito\"],\"Yxj+Uc\":[\"Tutti i dati di questa area di lavoro sono stati eliminati in modo permanente.\"],\"RPHFhC\":[\"Conferma il tuo indirizzo email\"],\"nvkBPN\":[\"Connettiti a Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Caro \",[\"userName\"]],\"tGme7M\":[\"ti ha invitato a unirti a uno spazio di lavoro chiamato \"],\"uzTaYi\":[\"Ciao\"],\"eE1nG1\":[\"Se non si è avviata questa modifica, contattare immediatamente il proprietario dello spazio di lavoro.\"],\"Gz91L8\":[\"Se si desidera continuare a utilizzare Twenty, aggiornare l'abbonamento entro il prossimo \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"Se si desidera utilizzare nuovamente Twenty, è possibile creare una nuova area di lavoro.\"],\"7JuhZQ\":[\"Sembra che il vostro spazio di lavoro <0>\",[\"workspaceDisplayName\"],\"</0> sia stato sospeso per \",[\"daysSinceInactive\"],\" giorni.\"],\"PviVyk\":[\"Unisciti al tuo team su Twenty\"],\"ogtYkT\":[\"Password aggiornata\"],\"OfhWJH\":[\"Ripristina\"],\"RE5NiU\":[\"Ripristina la tua password 🗝\"],\"7yDt8q\":[\"Grazie per esserti registrato su Twenty! Prima di iniziare, dobbiamo solo confermare che sei tu. Clicca sopra per verificare il tuo indirizzo email.\"],\"igorB1\":[\"L'area di lavoro viene disattivata in \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" e tutti i suoi dati vengono cancellati.\"],\"7OEHy1\":[\"Questa è la conferma che la password del vostro account (\",[\"email\"],\") è stata modificata con successo in data \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"Questo link è valido solo per il prossimo \",[\"duration\"],\". Se il link non funziona, è possibile utilizzare direttamente il link di verifica del login:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Aggiornare l'abbonamento\"],\"wCKkSr\":[\"Verifica Email\"],\"KFmFrQ\":[\"L'area di lavoro <0>\",[\"workspaceDisplayName\"],\"</0> è stata cancellata perché l'abbonamento è scaduto \",[\"inactiveDaysBeforeDelete\"],\" giorni fa.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"招待を受ける\"],\"Yxj+Uc\":[\"このワークスペースのデータはすべて永久に削除されました。\"],\"RPHFhC\":[\"メールアドレスの確認\"],\"nvkBPN\":[\"トゥエンティに接続\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[[\"userName\"],\"]様\"],\"tGme7M\":[\"というワークスペースに招待された。 \"],\"uzTaYi\":[\"こんにちは\"],\"eE1nG1\":[\"この変更をあなたが行っていない場合は、直ちにワークスペースの所有者に連絡してください。\"],\"Gz91L8\":[\"Twentyのご利用を継続される場合は、次の\",[\"remainingDays\"],\" \",[\"dayOrDays\"],\"以内にサブスクリプションを更新してください。\"],\"0weyko\":[\"再びTwentyを使用したい場合は、新しいワークスペースを作成することができます。\"],\"7JuhZQ\":[\"ワークスペース<0>\",[\"workspaceDisplayName\"],\"</0>が\",[\"daysSinceInactive\"],\"日間中断されたようです。\"],\"PviVyk\":[\"Twentyでチームに参加しよう\"],\"ogtYkT\":[\"パスワード更新\"],\"OfhWJH\":[\"リセット\"],\"RE5NiU\":[\"パスワードをリセットする\"],\"7yDt8q\":[\"Twentyのアカウント登録ありがとうございますアカウント登録の前に、ご本人であることを確認させていただきます。上記をクリックしてメールアドレスを確認してください。\"],\"igorB1\":[\"ワークスペースは\",[\"remainingDays\"],\" \",[\"dayOrDays\"],\"で非アクティブになり、そのデータはすべて削除されます。\"],\"7OEHy1\":[\"これは、あなたのアカウント(\",[\"email\"],\")のパスワードが\",[\"formattedDate\"],\"で正常に変更されたことの確認です。\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"このリンクは次の\",[\"duration\"],\"にのみ有効です。リンクが機能しない場合は、ログイン認証リンクを直接ご利用ください:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"購読の更新\"],\"wCKkSr\":[\"電子メールの確認\"],\"KFmFrQ\":[\"サブスクリプションの有効期限が\",[\"inactiveDaysBeforeDelete\"],\"日前に切れたため、ワークスペース<0>\",[\"workspaceDisplayName\"],\"</0>が削除されました。\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"초대 수락\"],\"Yxj+Uc\":[\"이 작업 공간의 모든 데이터는 영구적으로 삭제되었습니다.\"],\"RPHFhC\":[\"이메일 주소 확인\"],\"nvkBPN\":[\"Twenty에 연결\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[[\"userName\"],\"] 님께\"],\"tGme7M\":[\"라는 작업 공간에 초대되었습니다 \"],\"uzTaYi\":[\"안녕하세요\"],\"eE1nG1\":[\"이 변경을 시작하지 않았다면 즉시 워크스페이스 소유자에게 문의하시기 바랍니다.\"],\"Gz91L8\":[\"Twenty를 계속 사용하시려면 다음 \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" 기간 내에 구독을 업데이트하세요.\"],\"0weyko\":[\"Twenty를 다시 사용하려면 새 워크스페이스를 만들면 됩니다.\"],\"7JuhZQ\":[\"작업 공간 <0>[\",[\"workspaceDisplayName\"],\"</0> ]이 \",[\"daysSinceInactive\"],\" 일 동안 일시 중단된 것 같습니다.\"],\"PviVyk\":[\"Twenty에서 팀에 합류하세요\"],\"ogtYkT\":[\"비밀번호 업데이트\"],\"OfhWJH\":[\"초기화\"],\"RE5NiU\":[\"비밀번호 재설정 🗝\"],\"7yDt8q\":[\"Twenty에 계정을 등록해 주셔서 감사합니다! 시작하기 전에 본인인지 확인해야 합니다. 위를 클릭하여 이메일 주소를 인증하세요.\"],\"igorB1\":[\"워크스페이스는 \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\"에서 비활성화되고 모든 데이터가 삭제됩니다.\"],\"7OEHy1\":[\"계정 비밀번호(\",[\"email\"],\")가 \",[\"formattedDate\"],\"에서 성공적으로 변경되었음을 확인합니다.\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"이 링크는 다음 \",[\"duration\"],\"에만 유효합니다. 링크가 작동하지 않는 경우 로그인 인증 링크를 직접 사용할 수 있습니다:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"구독 업데이트\"],\"wCKkSr\":[\"이메일 확인\"],\"KFmFrQ\":[\"워크스페이스 <0>[\",[\"workspaceDisplayName\"],\"</0> ]는 구독이 만료된 \",[\"inactiveDaysBeforeDelete\"],\" 일 전에 삭제되었습니다.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Àććēƥţ ĩńvĩţē\"],\"Yxj+Uc\":[\"Àĺĺ ďàţà ĩń ţĥĩś ŵōŕķśƥàćē ĥàś ƀēēń ƥēŕḿàńēńţĺŷ ďēĺēţēď.\"],\"RPHFhC\":[\"Ćōńƒĩŕḿ ŷōũŕ ēḿàĩĺ àďďŕēśś\"],\"nvkBPN\":[\"Ćōńńēćţ ţō Ţŵēńţŷ\"],\"JRzgV7\":[\"Ďēàŕ\"],\"Lm5BBI\":[\"Ďēàŕ \",[\"userName\"]],\"tGme7M\":[\"ĥàś ĩńvĩţēď ŷōũ ţō Ĵōĩń à ŵōŕķśƥàćē ćàĺĺēď \"],\"uzTaYi\":[\"Ĥēĺĺō\"],\"eE1nG1\":[\"Ĩƒ ŷōũ ďĩď ńōţ ĩńĩţĩàţē ţĥĩś ćĥàńĝē, ƥĺēàśē ćōńţàćţ ŷōũŕ ŵōŕķśƥàćē ōŵńēŕ ĩḿḿēďĩàţēĺŷ.\"],\"Gz91L8\":[\"Ĩƒ ŷōũ ŵĩśĥ ţō ćōńţĩńũē ũśĩńĝ Ţŵēńţŷ, ƥĺēàśē ũƥďàţē ŷōũŕ śũƀśćŕĩƥţĩōń ŵĩţĥĩń ţĥē ńēxţ \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"Ĩƒ ŷōũ ŵĩśĥ ţō ũśē Ţŵēńţŷ àĝàĩń, ŷōũ ćàń ćŕēàţē à ńēŵ ŵōŕķśƥàćē.\"],\"7JuhZQ\":[\"Ĩţ àƥƥēàŕś ţĥàţ ŷōũŕ ŵōŕķśƥàćē <0>\",[\"workspaceDisplayName\"],\"</0> ĥàś ƀēēń śũśƥēńďēď ƒōŕ \",[\"daysSinceInactive\"],\" ďàŷś.\"],\"PviVyk\":[\"ĵōĩń ŷōũŕ ţēàḿ ōń Ţŵēńţŷ\"],\"ogtYkT\":[\"Ƥàśśŵōŕď ũƥďàţēď\"],\"OfhWJH\":[\"Ŕēśēţ\"],\"RE5NiU\":[\"Ŕēśēţ ŷōũŕ ƥàśśŵōŕď 🗝\"],\"7yDt8q\":[\"Ţĥàńķś ƒōŕ ŕēĝĩśţēŕĩńĝ ƒōŕ àń àććōũńţ ōń Ţŵēńţŷ! ßēƒōŕē ŵē ĝēţ śţàŕţēď, ŵē Ĵũśţ ńēēď ţō ćōńƒĩŕḿ ţĥàţ ţĥĩś ĩś ŷōũ. Ćĺĩćķ àƀōvē ţō vēŕĩƒŷ ŷōũŕ ēḿàĩĺ àďďŕēśś.\"],\"igorB1\":[\"Ţĥē ŵōŕķśƥàćē ŵĩĺĺ ƀē ďēàćţĩvàţēď ĩń \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\", àńď àĺĺ ĩţś ďàţà ŵĩĺĺ ƀē ďēĺēţēď.\"],\"7OEHy1\":[\"Ţĥĩś ĩś à ćōńƒĩŕḿàţĩōń ţĥàţ ƥàśśŵōŕď ƒōŕ ŷōũŕ àććōũńţ (\",[\"email\"],\") ŵàś śũććēśśƒũĺĺŷ ćĥàńĝēď ōń \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"Ţĥĩś ĩś à ćōńƒĩŕḿàţĩōń ţĥàţ ƥàśśŵōŕď ƒōŕ ŷōũŕ àććōũńţ (\",[\"email\"],\") ŵàś śũććēśśƒũĺĺŷ ćĥàńĝēď ōń \",[\"formattedDate\"],\".<0/><1/>Ĩƒ ŷōũ ďĩď ńōţ ĩńĩţĩàţē ţĥĩś ćĥàńĝē, ƥĺēàśē ćōńţàćţ ŷōũŕ ŵōŕķśƥàćē ōŵńēŕ ĩḿḿēďĩàţēĺŷ.\"],\"R4gMjN\":[\"Ţĥĩś ĺĩńķ ĩś ōńĺŷ vàĺĩď ƒōŕ ţĥē ńēxţ \",[\"duration\"],\". Ĩƒ ţĥē ĺĩńķ ďōēś ńōţ ŵōŕķ, ŷōũ ćàń ũśē ţĥē ĺōĝĩń vēŕĩƒĩćàţĩōń ĺĩńķ ďĩŕēćţĺŷ:\"],\"2oA637\":[\"Ţĥĩś ĺĩńķ ĩś ōńĺŷ vàĺĩď ƒōŕ ţĥē ńēxţ \",[\"duration\"],\". Ĩƒ ţĥē ĺĩńķ ďōēś ńōţ ŵōŕķ, ŷōũ ćàń ũśē ţĥē ĺōĝĩń vēŕĩƒĩćàţĩōń ĺĩńķ ďĩŕēćţĺŷ:<0/>\"],\"H0v4yC\":[\"Ũƥďàţē ŷōũŕ śũƀśćŕĩƥţĩōń\"],\"wCKkSr\":[\"Vēŕĩƒŷ Ēḿàĩĺ\"],\"KFmFrQ\":[\"Ŷōũŕ ŵōŕķśƥàćē <0>\",[\"workspaceDisplayName\"],\"</0> ĥàś ƀēēń ďēĺēţēď àś ŷōũŕ śũƀśćŕĩƥţĩōń ēxƥĩŕēď \",[\"inactiveDaysBeforeDelete\"],\" ďàŷś àĝō.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Aceitar convite\"],\"Yxj+Uc\":[\"Todos os dados desse espaço de trabalho foram excluídos permanentemente.\"],\"RPHFhC\":[\"Confirme seu endereço de e-mail\"],\"nvkBPN\":[\"Conecte-se ao Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Prezado \",[\"userName\"]],\"tGme7M\":[\"convidou você para participar de um espaço de trabalho chamado \"],\"uzTaYi\":[\"Olá\"],\"eE1nG1\":[\"Se você não iniciou essa alteração, entre em contato com o proprietário do espaço de trabalho imediatamente.\"],\"Gz91L8\":[\"Se quiser continuar usando o Twenty, atualize sua assinatura nos próximos \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"Se quiser usar o Twenty novamente, você poderá criar um novo espaço de trabalho.\"],\"7JuhZQ\":[\"Parece que seu espaço de trabalho <0>\",[\"workspaceDisplayName\"],\"</0> foi suspenso por \",[\"daysSinceInactive\"],\" dias.\"],\"PviVyk\":[\"Junte-se à sua equipe no Twenty\"],\"ogtYkT\":[\"Senha atualizada\"],\"OfhWJH\":[\"Redefinir\"],\"RE5NiU\":[\"Redefinir sua senha 🗝\"],\"7yDt8q\":[\"Obrigado por registrar uma conta no Twenty! Antes de começarmos, precisamos confirmar que este é você. Clique acima para verificar seu endereço de e-mail.\"],\"igorB1\":[\"O espaço de trabalho será desativado em \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\", e todos os seus dados serão excluídos.\"],\"7OEHy1\":[\"Esta é uma confirmação de que a senha de sua conta (\",[\"email\"],\") foi alterada com sucesso em \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"Esse link é válido somente para o próximo \",[\"duration\"],\". Se o link não funcionar, você poderá usar o link de verificação de login diretamente:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Atualize sua assinatura\"],\"wCKkSr\":[\"Verificar e-mail\"],\"KFmFrQ\":[\"Seu espaço de trabalho <0>\",[\"workspaceDisplayName\"],\"</0> foi excluído porque sua assinatura expirou \",[\"inactiveDaysBeforeDelete\"],\" dias atrás.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"Aceitar convite\"],\"Yxj+Uc\":[\"Todos os dados deste espaço de trabalho foram permanentemente eliminados.\"],\"RPHFhC\":[\"Confirmar o seu endereço de correio eletrónico\"],\"nvkBPN\":[\"Ligar ao Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"Caro \",[\"userName\"]],\"tGme7M\":[\"convidou-o a juntar-se a um espaço de trabalho chamado \"],\"uzTaYi\":[\"Olá\"],\"eE1nG1\":[\"Se não foi você que iniciou esta alteração, contacte imediatamente o proprietário do seu espaço de trabalho.\"],\"Gz91L8\":[\"Se pretender continuar a utilizar o Twenty, actualize a sua subscrição nos próximos \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\".\"],\"0weyko\":[\"Se pretender voltar a utilizar o Twenty, pode criar um novo espaço de trabalho.\"],\"7JuhZQ\":[\"Parece que o seu espaço de trabalho <0>\",[\"workspaceDisplayName\"],\"</0> foi suspenso por \",[\"daysSinceInactive\"],\" dias.\"],\"PviVyk\":[\"Junte-se à sua equipa no Twenty\"],\"ogtYkT\":[\"Palavra-passe actualizada\"],\"OfhWJH\":[\"Reiniciar\"],\"RE5NiU\":[\"Repor a sua palavra-passe 🗝\"],\"7yDt8q\":[\"Obrigado por se ter registado para uma conta no Twenty! Antes de começarmos, só precisamos de confirmar que é você. Clique acima para verificar o seu endereço de e-mail.\"],\"igorB1\":[\"O espaço de trabalho será desativado em \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" e todos os seus dados serão eliminados.\"],\"7OEHy1\":[\"Esta é uma confirmação de que a palavra-passe da sua conta (\",[\"email\"],\") foi alterada com sucesso em \",[\"formattedDate\"],\".\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"Esta hiperligação só é válida para o próximo \",[\"duration\"],\". Se a ligação não funcionar, pode utilizar diretamente a ligação de verificação de início de sessão:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"Atualizar a sua subscrição\"],\"wCKkSr\":[\"Verificar o correio eletrónico\"],\"KFmFrQ\":[\"O seu espaço de trabalho <0>\",[\"workspaceDisplayName\"],\"</0> foi eliminado porque a sua subscrição expirou há \",[\"inactiveDaysBeforeDelete\"],\" dias.\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"接受邀请\"],\"Yxj+Uc\":[\"该工作区中的所有数据已被永久删除。\"],\"RPHFhC\":[\"确认您的电子邮件地址\"],\"nvkBPN\":[\"连接到 Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"亲爱的 \",[\"userName\"]],\"tGme7M\":[\"邀请您加入名为\"],\"uzTaYi\":[\"你好\"],\"eE1nG1\":[\"如果您没有启动此更改,请立即联系您的工作区所有者。\"],\"Gz91L8\":[\"如果您希望继续使用 Twenty请在 \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" 内更新您的订阅。\"],\"0weyko\":[\"如果您想再次使用 Twenty可以创建一个新的工作区。\"],\"7JuhZQ\":[\"您的工作区<0>\",[\"workspaceDisplayName\"],\"</0>已被暂停 \",[\"daysSinceInactive\"],\" 天。\"],\"PviVyk\":[\"加入您的团队使用Twenty\"],\"ogtYkT\":[\"密码已更新\"],\"OfhWJH\":[\"重置\"],\"RE5NiU\":[\"重置您的密码 🗝\"],\"7yDt8q\":[\"感谢您在 Twenty 注册帐户!在开始之前,我们只需要确认是您本人。请点击上方验证您的电子邮件地址。\"],\"igorB1\":[\"工作区将在 \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" 中停用,其所有数据将被删除。\"],\"7OEHy1\":[\"确认您的账户(\",[\"email\"],\")密码已在 \",[\"formattedDate\"],\" 上成功更改。\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"此链接仅对下 \",[\"duration\"],\" 次有效。如果链接无效,您可以直接使用登录验证链接:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"更新您的订阅\"],\"wCKkSr\":[\"验证电子邮件\"],\"KFmFrQ\":[\"您的工作区<0>[\",[\"workspaceDisplayName\"],\"</0>] 已被删除,因为您的订阅已于 \",[\"inactiveDaysBeforeDelete\"],\" 天前过期。\"]}")as Messages;

View File

@ -0,0 +1 @@
/*eslint-disable*/import type{Messages}from"@lingui/core";export const messages=JSON.parse("{\"4WPI3S\":[\"接受邀請\"],\"Yxj+Uc\":[\"该工作区中的所有数据已被永久删除。\"],\"RPHFhC\":[\"確認您的電子郵件地址\"],\"nvkBPN\":[\"連接到 Twenty\"],\"JRzgV7\":[\"Dear\"],\"Lm5BBI\":[\"親愛的 \",[\"userName\"]],\"tGme7M\":[\"已邀請您加入名為\"],\"uzTaYi\":[\"您好\"],\"eE1nG1\":[\"如果您没有启动此更改,请立即联系您的工作区所有者。\"],\"Gz91L8\":[\"如果您希望继续使用 Twenty请在 \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" 内更新您的订阅。\"],\"0weyko\":[\"如果您想再次使用 Twenty可以创建一个新的工作区。\"],\"7JuhZQ\":[\"您的工作区<0>\",[\"workspaceDisplayName\"],\"</0>已被暂停 \",[\"daysSinceInactive\"],\" 天。\"],\"PviVyk\":[\"加入您的團隊,來 Twenty\"],\"ogtYkT\":[\"密碼已更新\"],\"OfhWJH\":[\"重設\"],\"RE5NiU\":[\"重設您的密碼 🗝\"],\"7yDt8q\":[\"感謝您在 Twenty 註冊帳戶!在開始之前,我們需要確認這是您。請點擊以上鏈接以驗證您的電子郵件地址。\"],\"igorB1\":[\"工作区将在 \",[\"remainingDays\"],\" \",[\"dayOrDays\"],\" 中停用,其所有数据将被删除。\"],\"7OEHy1\":[\"确认您的账户(\",[\"email\"],\")密码已在 \",[\"formattedDate\"],\" 上成功更改。\"],\"wSOsS+\":[\"This is a confirmation that password for your account (\",[\"email\"],\") was successfully changed on \",[\"formattedDate\"],\".<0/><1/>If you did not initiate this change, please contact your workspace owner immediately.\"],\"R4gMjN\":[\"此链接仅对下 \",[\"duration\"],\" 次有效。如果链接无效,您可以直接使用登录验证链接:\"],\"2oA637\":[\"This link is only valid for the next \",[\"duration\"],\". If the link does not work, you can use the login verification link directly:<0/>\"],\"H0v4yC\":[\"更新您的订阅\"],\"wCKkSr\":[\"驗證電子郵件\"],\"KFmFrQ\":[\"您的工作区<0>[\",[\"workspaceDisplayName\"],\"</0>] 已被删除,因为您的订阅已于 \",[\"inactiveDaysBeforeDelete\"],\" 天前过期。\"]}")as Messages;

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: it\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Accetta invito"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "Tutti i dati di questa area di lavoro sono stati eliminati in modo permanente."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Conferma il tuo indirizzo email"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Connettiti a Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Caro {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Ciao"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "Se non si è avviata questa modifica, contattare immediatamente il proprietario dello spazio di lavoro."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Se si desidera continuare a utilizzare Twenty, aggiornare l'abbonamento entro il prossimo {remainingDays} {dayOrDays}."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Se si desidera utilizzare nuovamente Twenty, è possibile creare una nuova area di lavoro."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "Sembra che il vostro spazio di lavoro <0>{workspaceDisplayName}</0> sia stato sospeso per {daysSinceInactive} giorni."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Unisciti al tuo team su Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Password aggiornata"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Ripristina"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Ripristina la tua password 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Grazie per esserti registrato su Twenty! Prima di iniziare, dobbiamo solo confermare che sei tu. Clicca sopra per verificare il tuo indirizzo email."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "L'area di lavoro viene disattivata in {remainingDays} {dayOrDays} e tutti i suoi dati vengono cancellati."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "Questa è la conferma che la password del vostro account ({email}) è stata modificata con successo in data {formattedDate}."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "Questo link è valido solo per il prossimo {duration}. Se il link non funziona, è possibile utilizzare direttamente il link di verifica del login:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Aggiornare l'abbonamento"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "Verifica Email"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "L'area di lavoro <0>{workspaceDisplayName}</0> è stata cancellata perché l'abbonamento è scaduto {inactiveDaysBeforeDelete} giorni fa."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "ti ha invitato a unirti a uno spazio di lavoro chiamato "

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ja\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "招待を受ける"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "このワークスペースのデータはすべて永久に削除されました。"
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "メールアドレスの確認"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "トゥエンティに接続"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "{userName}]様"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "こんにちは"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "この変更をあなたが行っていない場合は、直ちにワークスペースの所有者に連絡してください。"
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Twentyのご利用を継続される場合は、次の{remainingDays} {dayOrDays}以内にサブスクリプションを更新してください。"
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "再びTwentyを使用したい場合は、新しいワークスペースを作成することができます。"
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "ワークスペース<0>{workspaceDisplayName}</0>が{daysSinceInactive}日間中断されたようです。"
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Twentyでチームに参加しよう"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "パスワード更新"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "リセット"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "パスワードをリセットする"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Twentyのアカウント登録ありがとうございますアカウント登録の前に、ご本人であることを確認させていただきます。上記をクリックしてメールアドレスを確認してください。"
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "ワークスペースは{remainingDays} {dayOrDays}で非アクティブになり、そのデータはすべて削除されます。"
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "これは、あなたのアカウント({email})のパスワードが{formattedDate}で正常に変更されたことの確認です。"
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "このリンクは次の{duration}にのみ有効です。リンクが機能しない場合は、ログイン認証リンクを直接ご利用ください:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "購読の更新"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "電子メールの確認"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "サブスクリプションの有効期限が{inactiveDaysBeforeDelete}日前に切れたため、ワークスペース<0>{workspaceDisplayName}</0>が削除されました。"
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "というワークスペースに招待された。 "

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ko\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "초대 수락"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "이 작업 공간의 모든 데이터는 영구적으로 삭제되었습니다."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "이메일 주소 확인"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Twenty에 연결"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "{userName}] 님께"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "안녕하세요"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "이 변경을 시작하지 않았다면 즉시 워크스페이스 소유자에게 문의하시기 바랍니다."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Twenty를 계속 사용하시려면 다음 {remainingDays} {dayOrDays} 기간 내에 구독을 업데이트하세요."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Twenty를 다시 사용하려면 새 워크스페이스를 만들면 됩니다."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "작업 공간 <0>[{workspaceDisplayName}</0> ]이 {daysSinceInactive} 일 동안 일시 중단된 것 같습니다."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Twenty에서 팀에 합류하세요"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "비밀번호 업데이트"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "초기화"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "비밀번호 재설정 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Twenty에 계정을 등록해 주셔서 감사합니다! 시작하기 전에 본인인지 확인해야 합니다. 위를 클릭하여 이메일 주소를 인증하세요."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "워크스페이스는 {remainingDays} {dayOrDays}에서 비활성화되고 모든 데이터가 삭제됩니다."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "계정 비밀번호({email})가 {formattedDate}에서 성공적으로 변경되었음을 확인합니다."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "이 링크는 다음 {duration}에만 유효합니다. 링크가 작동하지 않는 경우 로그인 인증 링크를 직접 사용할 수 있습니다:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "구독 업데이트"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "이메일 확인"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "워크스페이스 <0>[{workspaceDisplayName}</0> ]는 구독이 만료된 {inactiveDaysBeforeDelete} 일 전에 삭제되었습니다."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "라는 작업 공간에 초대되었습니다 "

View File

@ -0,0 +1,114 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 18:53+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pseudo-en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr ""
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr ""
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr ""
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr ""
#: src/emails/password-update-notify.email.tsx:24
#~ msgid "Dear"
#~ msgstr ""
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr ""
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr ""
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr ""
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr ""
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr ""
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr ""
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr ""
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr ""
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr ""
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr ""
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr ""
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr ""
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr ""
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr ""
#: src/emails/password-update-notify.email.tsx:36
#~ msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}.<0/><1/>If you did not initiate this change, please contact your workspace owner immediately."
#~ msgstr ""
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr ""
#: src/emails/password-reset-link.email.tsx:28
#~ msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:<0/>"
#~ msgstr ""
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr ""
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr ""
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr ""

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pt-BR\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Aceitar convite"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "Todos os dados desse espaço de trabalho foram excluídos permanentemente."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Confirme seu endereço de e-mail"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Conecte-se ao Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Prezado {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Olá"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "Se você não iniciou essa alteração, entre em contato com o proprietário do espaço de trabalho imediatamente."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Se quiser continuar usando o Twenty, atualize sua assinatura nos próximos {remainingDays} {dayOrDays}."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Se quiser usar o Twenty novamente, você poderá criar um novo espaço de trabalho."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "Parece que seu espaço de trabalho <0>{workspaceDisplayName}</0> foi suspenso por {daysSinceInactive} dias."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Junte-se à sua equipe no Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Senha atualizada"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Redefinir"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Redefinir sua senha 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Obrigado por registrar uma conta no Twenty! Antes de começarmos, precisamos confirmar que este é você. Clique acima para verificar seu endereço de e-mail."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "O espaço de trabalho será desativado em {remainingDays} {dayOrDays}, e todos os seus dados serão excluídos."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "Esta é uma confirmação de que a senha de sua conta ({email}) foi alterada com sucesso em {formattedDate}."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "Esse link é válido somente para o próximo {duration}. Se o link não funcionar, você poderá usar o link de verificação de login diretamente:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Atualize sua assinatura"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "Verificar e-mail"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "Seu espaço de trabalho <0>{workspaceDisplayName}</0> foi excluído porque sua assinatura expirou {inactiveDaysBeforeDelete} dias atrás."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "convidou você para participar de um espaço de trabalho chamado "

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pt-PT\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "Aceitar convite"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "Todos os dados deste espaço de trabalho foram permanentemente eliminados."
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "Confirmar o seu endereço de correio eletrónico"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "Ligar ao Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "Caro {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "Olá"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "Se não foi você que iniciou esta alteração, contacte imediatamente o proprietário do seu espaço de trabalho."
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "Se pretender continuar a utilizar o Twenty, actualize a sua subscrição nos próximos {remainingDays} {dayOrDays}."
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "Se pretender voltar a utilizar o Twenty, pode criar um novo espaço de trabalho."
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "Parece que o seu espaço de trabalho <0>{workspaceDisplayName}</0> foi suspenso por {daysSinceInactive} dias."
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "Junte-se à sua equipa no Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "Palavra-passe actualizada"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "Reiniciar"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "Repor a sua palavra-passe 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "Obrigado por se ter registado para uma conta no Twenty! Antes de começarmos, só precisamos de confirmar que é você. Clique acima para verificar o seu endereço de e-mail."
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "O espaço de trabalho será desativado em {remainingDays} {dayOrDays} e todos os seus dados serão eliminados."
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "Esta é uma confirmação de que a palavra-passe da sua conta ({email}) foi alterada com sucesso em {formattedDate}."
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "Esta hiperligação só é válida para o próximo {duration}. Se a ligação não funcionar, pode utilizar diretamente a ligação de verificação de início de sessão:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "Atualizar a sua subscrição"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "Verificar o correio eletrónico"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "O seu espaço de trabalho <0>{workspaceDisplayName}</0> foi eliminado porque a sua subscrição expirou há {inactiveDaysBeforeDelete} dias."
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "convidou-o a juntar-se a um espaço de trabalho chamado "

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: zh-Hans\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "接受邀请"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "该工作区中的所有数据已被永久删除。"
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "确认您的电子邮件地址"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "连接到 Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "亲爱的 {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "你好"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "如果您没有启动此更改,请立即联系您的工作区所有者。"
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "如果您希望继续使用 Twenty请在 {remainingDays} {dayOrDays} 内更新您的订阅。"
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "如果您想再次使用 Twenty可以创建一个新的工作区。"
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "您的工作区<0>{workspaceDisplayName}</0>已被暂停 {daysSinceInactive} 天。"
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "加入您的团队使用Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "密码已更新"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "重置"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "重置您的密码 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "感谢您在 Twenty 注册帐户!在开始之前,我们只需要确认是您本人。请点击上方验证您的电子邮件地址。"
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "工作区将在 {remainingDays} {dayOrDays} 中停用,其所有数据将被删除。"
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "确认您的账户({email})密码已在 {formattedDate} 上成功更改。"
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "此链接仅对下 {duration} 次有效。如果链接无效,您可以直接使用登录验证链接:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "更新您的订阅"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "验证电子邮件"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "您的工作区<0>[{workspaceDisplayName}</0>] 已被删除,因为您的订阅已于 {inactiveDaysBeforeDelete} 天前过期。"
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "邀请您加入名为"

View File

@ -0,0 +1,96 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-02 20:44+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: zh-Hant\n"
#: src/emails/send-invite-link.email.tsx:57
msgid "Accept invite"
msgstr "接受邀請"
#: src/emails/clean-suspended-workspace.email.tsx:33
msgid "All data in this workspace has been permanently deleted."
msgstr "该工作区中的所有数据已被永久删除。"
#: src/emails/send-email-verification-link.email.tsx:22
msgid "Confirm your email address"
msgstr "確認您的電子郵件地址"
#: src/emails/password-update-notify.email.tsx:46
msgid "Connect to Twenty"
msgstr "連接到 Twenty"
#: src/emails/password-update-notify.email.tsx:24
msgid "Dear {userName}"
msgstr "親愛的 {userName}"
#: src/emails/password-update-notify.email.tsx:24
msgid "Hello"
msgstr "您好"
#: src/emails/password-update-notify.email.tsx:40
msgid "If you did not initiate this change, please contact your workspace owner immediately."
msgstr "如果您没有启动此更改,请立即联系您的工作区所有者。"
#: src/emails/warn-suspended-workspace.email.tsx:46
msgid "If you wish to continue using Twenty, please update your subscription within the next {remainingDays} {dayOrDays}."
msgstr "如果您希望继续使用 Twenty请在 {remainingDays} {dayOrDays} 内更新您的订阅。"
#: src/emails/clean-suspended-workspace.email.tsx:36
msgid "If you wish to use Twenty again, you can create a new workspace."
msgstr "如果您想再次使用 Twenty可以创建一个新的工作区。"
#: src/emails/warn-suspended-workspace.email.tsx:34
msgid "It appears that your workspace <0>{workspaceDisplayName}</0> has been suspended for {daysSinceInactive} days."
msgstr "您的工作区<0>{workspaceDisplayName}</0>已被暂停 {daysSinceInactive} 天。"
#: src/emails/send-invite-link.email.tsx:42
msgid "Join your team on Twenty"
msgstr "加入您的團隊,來 Twenty"
#: src/emails/password-update-notify.email.tsx:29
msgid "Password updated"
msgstr "密碼已更新"
#: src/emails/password-reset-link.email.tsx:24
msgid "Reset"
msgstr "重設"
#: src/emails/password-reset-link.email.tsx:23
msgid "Reset your password 🗝"
msgstr "重設您的密碼 🗝"
#: src/emails/send-email-verification-link.email.tsx:27
msgid "Thanks for registering for an account on Twenty! Before we get started, we just need to confirm that this is you. Click above to verify your email address."
msgstr "感謝您在 Twenty 註冊帳戶!在開始之前,我們需要確認這是您。請點擊以上鏈接以驗證您的電子郵件地址。"
#: src/emails/warn-suspended-workspace.email.tsx:40
msgid "The workspace will be deactivated in {remainingDays} {dayOrDays}, and all its data will be deleted."
msgstr "工作区将在 {remainingDays} {dayOrDays} 中停用,其所有数据将被删除。"
#: src/emails/password-update-notify.email.tsx:34
msgid "This is a confirmation that password for your account ({email}) was successfully changed on {formattedDate}."
msgstr "确认您的账户({email})密码已在 {formattedDate} 上成功更改。"
#: src/emails/password-reset-link.email.tsx:26
msgid "This link is only valid for the next {duration}. If the link does not work, you can use the login verification link directly:"
msgstr "此链接仅对下 {duration} 次有效。如果链接无效,您可以直接使用登录验证链接:"
#: src/emails/warn-suspended-workspace.email.tsx:53
msgid "Update your subscription"
msgstr "更新您的订阅"
#: src/emails/send-email-verification-link.email.tsx:23
msgid "Verify Email"
msgstr "驗證電子郵件"
#: src/emails/clean-suspended-workspace.email.tsx:27
msgid "Your workspace <0>{workspaceDisplayName}</0> has been deleted as your subscription expired {inactiveDaysBeforeDelete} days ago."
msgstr "您的工作区<0>[{workspaceDisplayName}</0>] 已被删除,因为您的订阅已于 {inactiveDaysBeforeDelete} 天前过期。"
#: src/emails/send-invite-link.email.tsx:50
msgid "has invited you to join a workspace called "
msgstr "已邀請您加入名為"

View File

@ -7,10 +7,10 @@
"allowSyntheticDefaultImports": true,
"strict": true,
"types": ["vite/client"],
"baseUrl": "."
"baseUrl": ".",
},
"files": [],
"include": [],
"include": ["vite.config.ts"],
"references": [
{
"path": "./tsconfig.lib.json"

View File

@ -2,6 +2,8 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../.cache/tsc",
"composite": true,
"declaration": true,
"types": [
"node",
"@nx/react/typings/image.d.ts",

View File

@ -1,5 +1,7 @@
import { lingui } from '@lingui/vite-plugin';
import react from '@vitejs/plugin-react-swc';
import * as path from 'path';
import { APP_LOCALES } from 'twenty-shared';
import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
import tsconfigPaths from 'vite-tsconfig-paths';
@ -9,7 +11,12 @@ export default defineConfig({
cacheDir: '../../node_modules/.vite/packages/twenty-emails',
plugins: [
react(),
react({
plugins: [['@lingui/swc-plugin', {}]],
}),
lingui({
configPath: path.resolve(__dirname, './lingui.config.ts'),
}),
tsconfigPaths(),
dts({
entryRoot: 'src',
@ -26,16 +33,20 @@ export default defineConfig({
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
entry: {
index: 'src/index.ts',
...Object.values(APP_LOCALES).reduce(
(acc, locale) => ({
...acc,
[`locales/generated/${locale}`]: `src/locales/generated/${locale}.ts`,
}),
{},
),
},
name: 'twenty-emails',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es', 'cjs'],
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react', 'react-dom', 'react/jsx-runtime'],
},
},

View File

@ -492,6 +492,7 @@ export enum FeatureFlagKey {
IsLocalizationEnabled = 'IsLocalizationEnabled',
IsMicrosoftSyncEnabled = 'IsMicrosoftSyncEnabled',
IsNewRelationEnabled = 'IsNewRelationEnabled',
IsPermissionsEnabled = 'IsPermissionsEnabled',
IsPostgreSQLIntegrationEnabled = 'IsPostgreSQLIntegrationEnabled',
IsRichTextV2Enabled = 'IsRichTextV2Enabled',
IsStripeIntegrationEnabled = 'IsStripeIntegrationEnabled',

View File

@ -1,5 +1,5 @@
import * as Apollo from '@apollo/client';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
@ -217,6 +217,11 @@ export type BooleanFieldComparison = {
isNot?: InputMaybe<Scalars['Boolean']>;
};
export type BuildDraftServerlessFunctionInput = {
/** The id of the function. */
id: Scalars['ID'];
};
export enum CalendarChannelVisibility {
METADATA = 'METADATA',
SHARE_EVERYTHING = 'SHARE_EVERYTHING'
@ -689,6 +694,7 @@ export type Mutation = {
activateWorkflowVersion: Scalars['Boolean'];
activateWorkspace: Workspace;
authorizeApp: AuthorizeApp;
buildDraftServerlessFunction: ServerlessFunction;
checkoutSession: BillingSessionOutput;
computeStepOutputSchema: Scalars['JSON'];
createDraftFromWorkflowVersion: WorkflowVersion;
@ -763,6 +769,11 @@ export type MutationAuthorizeAppArgs = {
};
export type MutationBuildDraftServerlessFunctionArgs = {
input: BuildDraftServerlessFunctionInput;
};
export type MutationCheckoutSessionArgs = {
plan?: BillingPlanKey;
recurringInterval: SubscriptionInterval;
@ -1444,6 +1455,7 @@ export type ServerlessFunctionExecutionResult = {
/** Status of the serverless function execution */
export enum ServerlessFunctionExecutionStatus {
ERROR = 'ERROR',
IDLE = 'IDLE',
SUCCESS = 'SUCCESS'
}
@ -1454,6 +1466,7 @@ export type ServerlessFunctionIdInput = {
/** SyncStatus of the serverlessFunction */
export enum ServerlessFunctionSyncStatus {
BUILDING = 'BUILDING',
NOT_READY = 'NOT_READY',
READY = 'READY'
}

View File

@ -20,7 +20,7 @@ import { clientConfigApiStatusState } from '@/client-config/states/clientConfigA
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
import { supportChatState } from '@/client-config/states/supportChatState';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { isDefined } from 'twenty-shared';
import { APP_LOCALES, isDefined } from 'twenty-shared';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import {
useCheckUserExistsLazyQuery,
@ -280,7 +280,9 @@ export const useAuth = () => {
)
: TimeFormat[detectTimeFormat()],
});
dynamicActivate(workspaceMember.locale ?? 'en');
dynamicActivate(
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? 'en',
);
}
const workspace = user.currentWorkspace ?? null;

View File

@ -16,7 +16,7 @@ import { detectTimeZone } from '@/localization/utils/detectTimeZone';
import { getDateFormatFromWorkspaceDateFormat } from '@/localization/utils/getDateFormatFromWorkspaceDateFormat';
import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTimeFormatFromWorkspaceTimeFormat';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { isDefined } from 'twenty-shared';
import { APP_LOCALES, isDefined } from 'twenty-shared';
import { WorkspaceMember } from '~/generated-metadata/graphql';
import { useGetCurrentUserQuery } from '~/generated/graphql';
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
@ -70,7 +70,7 @@ export const UserProviderEffect = () => {
return {
...workspaceMember,
colorScheme: (workspaceMember.colorScheme as ColorScheme) ?? 'Light',
locale: workspaceMember.locale ?? 'en',
locale: (workspaceMember.locale as keyof typeof APP_LOCALES) ?? 'en',
};
};
@ -93,7 +93,9 @@ export const UserProviderEffect = () => {
: TimeFormat[detectTimeFormat()],
});
dynamicActivate(workspaceMember.locale ?? 'en');
dynamicActivate(
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? 'en',
);
}
if (isDefined(workspaceMembers)) {

View File

@ -51,7 +51,7 @@ export const LocalePicker = () => {
if (!isDefined(currentWorkspaceMember)) return;
const handleLocaleChange = async (value: string) => {
const handleLocaleChange = async (value: keyof typeof APP_LOCALES) => {
setCurrentWorkspaceMember({
...currentWorkspaceMember,
...{ locale: value },
@ -126,7 +126,9 @@ export const LocalePicker = () => {
fullWidth
value={i18n.locale}
options={localeOptions}
onChange={(value) => handleLocaleChange(value)}
onChange={(value) =>
handleLocaleChange(value as keyof typeof APP_LOCALES)
}
/>
</StyledContainer>
);

View File

@ -1,6 +1,7 @@
import { i18n } from '@lingui/core';
import { APP_LOCALES } from 'twenty-shared';
export const dynamicActivate = async (locale: string) => {
export const dynamicActivate = async (locale: keyof typeof APP_LOCALES) => {
const { messages } = await import(`../../locales/generated/${locale}.ts`);
i18n.load(locale, messages);
i18n.activate(locale);

View File

@ -1,5 +1,5 @@
import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { Args, Context, Mutation, Query, Resolver } from '@nestjs/graphql';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
@ -33,6 +33,7 @@ import { TransientTokenService } from 'src/engine/core-modules/auth/token/servic
import { CaptchaGuard } from 'src/engine/core-modules/captcha/captcha.guard';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { EmailVerificationService } from 'src/engine/core-modules/email-verification/services/email-verification.service';
import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { User } from 'src/engine/core-modules/user/user.entity';
@ -336,6 +337,7 @@ export class AuthResolver {
@Mutation(() => EmailPasswordResetLink)
async emailPasswordResetLink(
@Args() emailPasswordResetInput: EmailPasswordResetLinkInput,
@Context() context: I18nContext,
): Promise<EmailPasswordResetLink> {
const resetToken =
await this.resetPasswordService.generatePasswordResetToken(
@ -345,6 +347,7 @@ export class AuthResolver {
return await this.resetPasswordService.sendEmailPasswordResetLink(
resetToken,
emailPasswordResetInput.email,
context.req.headers['x-locale'] || 'en',
);
}
@ -352,13 +355,18 @@ export class AuthResolver {
async updatePasswordViaResetToken(
@Args()
{ passwordResetToken, newPassword }: UpdatePasswordViaResetTokenInput,
@Context() context: I18nContext,
): Promise<InvalidatePassword> {
const { id } =
await this.resetPasswordService.validatePasswordResetToken(
passwordResetToken,
);
await this.authService.updatePassword(id, newPassword);
await this.authService.updatePassword(
id,
newPassword,
context.req.headers['x-locale'] || 'en',
);
return await this.resetPasswordService.invalidatePasswordResetToken(id);
}

View File

@ -3,10 +3,11 @@ import { InjectRepository } from '@nestjs/typeorm';
import crypto from 'node:crypto';
import { render } from '@react-email/components';
import { render } from '@react-email/render';
import { addMilliseconds } from 'date-fns';
import ms from 'ms';
import { PasswordUpdateNotifyEmail } from 'twenty-emails';
import { APP_LOCALES } from 'twenty-shared';
import { Repository } from 'typeorm';
import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface';
@ -379,6 +380,7 @@ export class AuthService {
async updatePassword(
userId: string,
newPassword: string,
locale: keyof typeof APP_LOCALES,
): Promise<UpdatePassword> {
if (!userId) {
throw new AuthException(
@ -415,14 +417,11 @@ export class AuthService {
userName: `${user.firstName} ${user.lastName}`,
email: user.email,
link: this.domainManagerService.getBaseUrl().toString(),
locale,
});
const html = render(emailTemplate, {
pretty: true,
});
const text = render(emailTemplate, {
plainText: true,
});
const html = render(emailTemplate, { pretty: true });
const text = render(emailTemplate, { plainText: true });
this.emailService.send({
from: `${this.environmentService.get(

View File

@ -9,11 +9,11 @@ import {
AppTokenType,
} from 'src/engine/core-modules/app-token/app-token.entity';
import { AuthException } from 'src/engine/core-modules/auth/auth.exception';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { EmailService } from 'src/engine/core-modules/email/email.service';
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { ResetPasswordService } from './reset-password.service';
@ -149,6 +149,7 @@ describe('ResetPasswordService', () => {
const result = await service.sendEmailPasswordResetLink(
mockToken,
'test@example.com',
'en',
);
expect(result.success).toBe(true);
@ -162,6 +163,7 @@ describe('ResetPasswordService', () => {
service.sendEmailPasswordResetLink(
{} as any,
'nonexistent@example.com',
'en',
),
).rejects.toThrow(AuthException);
});

View File

@ -7,6 +7,7 @@ import { render } from '@react-email/render';
import { addMilliseconds, differenceInMilliseconds } from 'date-fns';
import ms from 'ms';
import { PasswordResetLinkEmail } from 'twenty-emails';
import { APP_LOCALES } from 'twenty-shared';
import { IsNull, MoreThan, Repository } from 'typeorm';
import {
@ -106,6 +107,7 @@ export class ResetPasswordService {
async sendEmailPasswordResetLink(
resetToken: PasswordResetToken,
email: string,
locale: keyof typeof APP_LOCALES,
): Promise<EmailPasswordResetLink> {
const user = await this.userRepository.findOneBy({
email,
@ -133,16 +135,13 @@ export class ResetPasswordService {
long: true,
},
),
locale,
};
const emailTemplate = PasswordResetLinkEmail(emailData);
const html = render(emailTemplate, {
pretty: true,
});
const text = render(emailTemplate, {
plainText: true,
});
const html = render(emailTemplate, { pretty: true });
const text = render(emailTemplate, { plainText: true });
this.emailService.send({
from: `${this.environmentService.get(

View File

@ -5,6 +5,7 @@ import { render } from '@react-email/render';
import { addMilliseconds, differenceInMilliseconds } from 'date-fns';
import ms from 'ms';
import { SendEmailVerificationLinkEmail } from 'twenty-emails';
import { APP_LOCALES } from 'twenty-shared';
import { Repository } from 'typeorm';
import {
@ -55,13 +56,12 @@ export class EmailVerificationService {
const emailData = {
link: verificationLink.toString(),
locale: 'en' as keyof typeof APP_LOCALES,
};
const emailTemplate = SendEmailVerificationLinkEmail(emailData);
const html = render(emailTemplate, {
pretty: true,
});
const html = render(emailTemplate);
const text = render(emailTemplate, {
plainText: true,

View File

@ -1,9 +1,9 @@
import { SendMailOptions } from 'nodemailer';
import { EmailSenderService } from 'src/engine/core-modules/email/email-sender.service';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
@Processor(MessageQueue.emailQueue)
export class EmailSenderJob {

View File

@ -2,10 +2,10 @@ import { Injectable } from '@nestjs/common';
import { SendMailOptions } from 'nodemailer';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { EmailSenderJob } from 'src/engine/core-modules/email/email-sender.job';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
@Injectable()
export class EmailService {

View File

@ -7,15 +7,17 @@ import { messages as enMessages } from 'src/engine/core-modules/i18n/locales/gen
import { messages as esMessages } from 'src/engine/core-modules/i18n/locales/generated/es';
import { messages as frMessages } from 'src/engine/core-modules/i18n/locales/generated/fr';
import { messages as itMessages } from 'src/engine/core-modules/i18n/locales/generated/it';
import { messages as jaMessages } from 'src/engine/core-modules/i18n/locales/generated/ja';
import { messages as koMessages } from 'src/engine/core-modules/i18n/locales/generated/ko';
import { messages as pseudoEnMessages } from 'src/engine/core-modules/i18n/locales/generated/pseudo-en';
import { messages as ptBRMessages } from 'src/engine/core-modules/i18n/locales/generated/pt-BR';
import { messages as ptPTMessages } from 'src/engine/core-modules/i18n/locales/generated/pt-PT';
import { messages as zhHansMessages } from 'src/engine/core-modules/i18n/locales/generated/zh-Hans';
import { messages as zhHantMessages } from 'src/engine/core-modules/i18n/locales/generated/zh-Hant';
@Injectable()
export class I18nService implements OnModuleInit {
async onModuleInit() {
async loadTranslations() {
i18n.load('en', enMessages);
i18n.load('fr', frMessages);
i18n.load('pseudo-en', pseudoEnMessages);
@ -23,6 +25,7 @@ export class I18nService implements OnModuleInit {
i18n.load('de', deMessages);
i18n.load('it', itMessages);
i18n.load('es', esMessages);
i18n.load('ja', jaMessages);
i18n.load('pt-PT', ptPTMessages);
i18n.load('pt-BR', ptBRMessages);
i18n.load('zh-Hans', zhHansMessages);
@ -30,4 +33,8 @@ export class I18nService implements OnModuleInit {
i18n.activate('en');
}
async onModuleInit() {
this.loadTranslations();
}
}

View File

@ -7,6 +7,7 @@ import { render } from '@react-email/render';
import { addMilliseconds } from 'date-fns';
import ms from 'ms';
import { SendInviteLinkEmail } from 'twenty-emails';
import { APP_LOCALES } from 'twenty-shared';
import { IsNull, Repository } from 'typeorm';
import {
@ -296,13 +297,11 @@ export class WorkspaceInvitationService {
lastName: sender.lastName,
},
serverUrl: this.environmentService.get('SERVER_URL'),
locale: 'en' as keyof typeof APP_LOCALES,
};
const emailTemplate = SendInviteLinkEmail(emailData);
const html = render(emailTemplate, {
pretty: true,
});
const html = render(emailTemplate);
const text = render(emailTemplate, {
plainText: true,
});

View File

@ -4,7 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { i18n } from '@lingui/core';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import isEmpty from 'lodash.isempty';
import { FieldMetadataType, isDefined } from 'twenty-shared';
import { APP_LOCALES, FieldMetadataType, isDefined } from 'twenty-shared';
import { DataSource, FindOneOptions, Repository } from 'typeorm';
import { v4 as uuidV4, v4 } from 'uuid';
@ -778,7 +778,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
async resolveTranslatableString(
fieldMetadata: FieldMetadataDTO,
labelKey: 'label' | 'description',
locale: string | undefined,
locale: keyof typeof APP_LOCALES | undefined,
): Promise<string> {
if (fieldMetadata.isCustom) {
return fieldMetadata[labelKey] ?? '';

View File

@ -1,7 +1,7 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { render } from '@react-email/components';
import { render } from '@react-email/render';
import {
CleanSuspendedWorkspaceEmail,
WarnSuspendedWorkspaceEmail,
@ -176,12 +176,8 @@ export class CleanerWorkspaceService {
workspaceDisplayName,
};
const emailTemplate = CleanSuspendedWorkspaceEmail(emailData);
const html = render(emailTemplate, {
pretty: true,
});
const text = render(emailTemplate, {
plainText: true,
});
const html = render(emailTemplate, { pretty: true });
const text = render(emailTemplate, { plainText: true });
this.emailService.send({
to: workspaceMember.userEmail,

View File

@ -1,7 +1,7 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import { FieldMetadataType } from 'twenty-shared';
import { APP_LOCALES, FieldMetadataType } from 'twenty-shared';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
@ -109,7 +109,7 @@ export class WorkspaceMemberWorkspaceEntity extends BaseWorkspaceEntity {
icon: 'IconLanguage',
defaultValue: "'en'",
})
locale: string;
locale: keyof typeof APP_LOCALES;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.avatarUrl,

496
yarn.lock
View File

@ -11460,202 +11460,236 @@ __metadata:
languageName: node
linkType: hard
"@react-email/body@npm:0.0.4":
version: 0.0.4
resolution: "@react-email/body@npm:0.0.4"
peerDependencies:
react: 18.2.0
checksum: 10c0/756a184bc1284e8ce1828cd3abc0ea3aa24262e6c677b4e4de48fd6c298717fbc0164e7af7ac4c72262bc3138222ab7fc30c63b0520178315fece2bd78d12f98
languageName: node
linkType: hard
"@react-email/button@npm:0.0.11":
"@react-email/body@npm:0.0.11":
version: 0.0.11
resolution: "@react-email/button@npm:0.0.11"
resolution: "@react-email/body@npm:0.0.11"
peerDependencies:
react: 18.2.0
checksum: 10c0/91de881f33adec7f5ff311dc8259771fff638cbb736a851a6d4a7e634378555177eb112bc38abb18af7e4bc8ccc899f5bce5b20d409e377d289904d37a20c0ce
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/4a86ea8041bf94992acde12efd79cd91f980b3c40a86792f98bd546e0b49f19fbdca1fc87d5d3e472a70535a3195f2738bbec1f9dec862d48c4bc625f599d3d6
languageName: node
linkType: hard
"@react-email/column@npm:0.0.8":
version: 0.0.8
resolution: "@react-email/column@npm:0.0.8"
"@react-email/button@npm:0.0.19":
version: 0.0.19
resolution: "@react-email/button@npm:0.0.19"
peerDependencies:
react: 18.2.0
checksum: 10c0/5a937dbe7a69c1db8078f84cf70b66224be187dafa78e683103ccbbdb5d3ad2267f7b92c4fbd73922e8c8dda2a4372f37c1a7efac38501cb356d20c028a87574
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/e96fe15cb4307c36add3ebaf382cf5f408c29fbbc433ef09b347a4d6488eecdaa23424880f8bdad18f773c91e8c0b2d24ec74c9010608f55100c5625c9c0be56
languageName: node
linkType: hard
"@react-email/components@npm:0.0.12":
version: 0.0.12
resolution: "@react-email/components@npm:0.0.12"
"@react-email/code-block@npm:0.0.11":
version: 0.0.11
resolution: "@react-email/code-block@npm:0.0.11"
dependencies:
"@react-email/body": "npm:0.0.4"
"@react-email/button": "npm:0.0.11"
"@react-email/column": "npm:0.0.8"
"@react-email/container": "npm:0.0.10"
"@react-email/font": "npm:0.0.4"
"@react-email/head": "npm:0.0.6"
"@react-email/heading": "npm:0.0.9"
"@react-email/hr": "npm:0.0.6"
"@react-email/html": "npm:0.0.6"
"@react-email/img": "npm:0.0.6"
"@react-email/link": "npm:0.0.6"
"@react-email/preview": "npm:0.0.7"
"@react-email/render": "npm:0.0.9"
"@react-email/row": "npm:0.0.6"
"@react-email/section": "npm:0.0.10"
"@react-email/tailwind": "npm:0.0.13"
"@react-email/text": "npm:0.0.6"
prismjs: "npm:1.29.0"
peerDependencies:
react: 18.2.0
checksum: 10c0/1cc01198e5eeb42aac79b11e1a0ceaddd75d3164425899d6fc676ddbcd84cb869cebb0c6feb1f4383ba92d150c32e94d1fe5eec2ee74711b9309569e3d9bc6ac
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/98a45460620c887a8adf5c59a936dd9fa2df76101b00b246df90ffe9108158262715b00401018ba6ba22f10dfad46b7e9b71cefa3c672728deee0a18c1f13293
languageName: node
linkType: hard
"@react-email/container@npm:0.0.10":
version: 0.0.10
resolution: "@react-email/container@npm:0.0.10"
"@react-email/code-inline@npm:0.0.5":
version: 0.0.5
resolution: "@react-email/code-inline@npm:0.0.5"
peerDependencies:
react: 18.2.0
checksum: 10c0/d074fad448f6033d232b890b9d1a9914d0f92908ba494feaa627828718f4fa6e639636f239eb8eeb8b597c220da9019e90cb72ee2b0328c2ec908fd73e48fc13
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/4081233686dd09575c580303f2822c415e1acc3c21847e64536afee60d37108810f5325e50a417ca39ab796fb21aae488108b4dcb55b0bb5e5b750f1019f32d7
languageName: node
linkType: hard
"@react-email/font@npm:0.0.4":
version: 0.0.4
resolution: "@react-email/font@npm:0.0.4"
peerDependencies:
react: 18.2.0
checksum: 10c0/066a0016fa78267c83665d5e3846421f7d787361b11f4e712bd32353d0de947a72a42036fdfd35b75eff479ca77deba0f5c220bee43ace8594f7c6345c30a0bc
languageName: node
linkType: hard
"@react-email/head@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/head@npm:0.0.6"
peerDependencies:
react: 18.2.0
checksum: 10c0/aa2362c965c6f1fa2bcd41be04c1ce8695864153768b4ba4f4b102dd1e1adb28ba067c54f71ded592799aacfa348813cae0f442797b3448bb87feb4588443546
languageName: node
linkType: hard
"@react-email/heading@npm:0.0.9":
version: 0.0.9
resolution: "@react-email/heading@npm:0.0.9"
dependencies:
"@radix-ui/react-slot": "npm:1.0.2"
react: "npm:18.2.0"
checksum: 10c0/d082d2a4d3db312cbaa0d62419cc1b29c6b6c3ee1467a220c97c9cb009be1af5f6409370b9caac054d8aee8d326fb6e894a72073ff429f05ed097ba471e12a43
languageName: node
linkType: hard
"@react-email/hr@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/hr@npm:0.0.6"
peerDependencies:
react: 18.2.0
checksum: 10c0/b965c176192a06b39d2c696a8b747cdf4060ba7229a7d45eaf1d5729c59920fefe90f43fbc5f8d203a8e5d77645ee62745d06ec5ec5c9b030815f0642a8ac4ab
languageName: node
linkType: hard
"@react-email/html@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/html@npm:0.0.6"
peerDependencies:
react: 18.2.0
checksum: 10c0/9046476ccb20e405a64e33ca3a80f1ed7645bacec0601001fd36efd95497a5999daebf0ad141f0c08387190582e23ff2b2f7fc536461ec9b27d0b397a311fe4f
languageName: node
linkType: hard
"@react-email/img@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/img@npm:0.0.6"
peerDependencies:
react: 18.2.0
checksum: 10c0/046f0b60bdf9c7c04a2033b39967de96e31ffedae8922f9f187ce39f6040deee33f02e5695f56c26cf1691cce7de937bcbd303c3804b9a824d0aabc71427a462
languageName: node
linkType: hard
"@react-email/link@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/link@npm:0.0.6"
peerDependencies:
react: 18.2.0
checksum: 10c0/3e5eb2e222abe99bdcec6127a20d4ac8ed584189527a2bced119b09d08625b74f0ffa8a1de009974b4cd47249ade4081e108ca4fd65daa0ca811a7c6058cf838
languageName: node
linkType: hard
"@react-email/preview@npm:0.0.7":
version: 0.0.7
resolution: "@react-email/preview@npm:0.0.7"
peerDependencies:
react: 18.2.0
checksum: 10c0/9125597760e69d36b9caf1a94595913f52364642351728a5ff91b7d97fce26fad74bae5f1c9baade8831f4154d4c88c773adcbc1f9f1d602b4113c50bf21eb30
languageName: node
linkType: hard
"@react-email/render@npm:0.0.10":
version: 0.0.10
resolution: "@react-email/render@npm:0.0.10"
dependencies:
html-to-text: "npm:9.0.5"
pretty: "npm:2.0.0"
react: "npm:18.2.0"
react-dom: "npm:18.2.0"
checksum: 10c0/ea0db578ef58734160ac512d04de5b09f558d192fbb74c0b9bdb3006e91d0d73ee7d77007f4740bef0d587f8b231f8dba5ef01e16e18d2deb37859ddd2e7d09a
languageName: node
linkType: hard
"@react-email/render@npm:0.0.9":
version: 0.0.9
resolution: "@react-email/render@npm:0.0.9"
dependencies:
html-to-text: "npm:9.0.5"
pretty: "npm:2.0.0"
react: "npm:18.2.0"
react-dom: "npm:18.2.0"
checksum: 10c0/128b3a7c65e77a14600e48fb24183e182de82b4ddc8ff11bb239c421fa68bd6eb8b063822b5abe9f8599e34ece315cdb961b4133c59285cebcc517d2ec0ae8da
languageName: node
linkType: hard
"@react-email/row@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/row@npm:0.0.6"
peerDependencies:
react: 18.2.0
checksum: 10c0/ca1d92094a5ccc35c93560538311c38989162e9f0235a71897296bc43f2c0ba31d53df9c7db1688f7be0d77ccc03a0094cc227c4d095787f3b3ea0c3d262e520
languageName: node
linkType: hard
"@react-email/section@npm:0.0.10":
version: 0.0.10
resolution: "@react-email/section@npm:0.0.10"
peerDependencies:
react: 18.2.0
checksum: 10c0/d1af5dc3ff9a5bd2675a82f976df79ab5acded5ca305536df36ad84440b3828b021f8026d721e34fe92853bc3dfe8b9aa4603c25bf2f901b22049748ed6a7fbc
languageName: node
linkType: hard
"@react-email/tailwind@npm:0.0.13":
"@react-email/column@npm:0.0.13":
version: 0.0.13
resolution: "@react-email/tailwind@npm:0.0.13"
dependencies:
react: "npm:18.2.0"
react-dom: "npm:18.2.0"
resolution: "@react-email/column@npm:0.0.13"
peerDependencies:
react: 18.2.0
checksum: 10c0/5980a8593b699e9a0e0a8178120d206e74ccb525ba5fedb02e7048f8efff7ca41f82308584624a9701dc021d2ccfd8fa224f11a191d78e567a77f8d35bd47bb4
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/56ebc6af1c546daca2c32b0700538242ab7d90ffff4be37bf9dcf929311b6996c66b39f506dfd37063bacd4382abdeab93baf8c1e3266aa62fe3b282b16a023f
languageName: node
linkType: hard
"@react-email/text@npm:0.0.6":
version: 0.0.6
resolution: "@react-email/text@npm:0.0.6"
"@react-email/components@npm:0.0.32":
version: 0.0.32
resolution: "@react-email/components@npm:0.0.32"
dependencies:
"@react-email/body": "npm:0.0.11"
"@react-email/button": "npm:0.0.19"
"@react-email/code-block": "npm:0.0.11"
"@react-email/code-inline": "npm:0.0.5"
"@react-email/column": "npm:0.0.13"
"@react-email/container": "npm:0.0.15"
"@react-email/font": "npm:0.0.9"
"@react-email/head": "npm:0.0.12"
"@react-email/heading": "npm:0.0.15"
"@react-email/hr": "npm:0.0.11"
"@react-email/html": "npm:0.0.11"
"@react-email/img": "npm:0.0.11"
"@react-email/link": "npm:0.0.12"
"@react-email/markdown": "npm:0.0.14"
"@react-email/preview": "npm:0.0.12"
"@react-email/render": "npm:1.0.4"
"@react-email/row": "npm:0.0.12"
"@react-email/section": "npm:0.0.16"
"@react-email/tailwind": "npm:1.0.4"
"@react-email/text": "npm:0.0.11"
peerDependencies:
react: 18.2.0
checksum: 10c0/1e960838bfe81bf33b42db1aa1d84446fc36911b4d9e9a79570d9a43fe9cc29d9271f7e1b25448383d8fe950a73130f8bed5c65cd8dbc786a2e6fe02e0c16202
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/8162915c75fbf03eeba9e34cc63cf29e3bbe264c3a3c2ea6cc16a134817a640b60b81c2368cae5947e917dfe2a1fbfb1177d22c5220ea6f16a17a76797eb9003
languageName: node
linkType: hard
"@react-email/container@npm:0.0.15":
version: 0.0.15
resolution: "@react-email/container@npm:0.0.15"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/5098468b5336682f0f833a57cea1182bfe4a46bb03d5aa9fc85f96ab1e79845e30a9487c4c56094a9482465e94aa4395f10978c99b1772ca4bd0823d2d9071f6
languageName: node
linkType: hard
"@react-email/font@npm:0.0.9":
version: 0.0.9
resolution: "@react-email/font@npm:0.0.9"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/b51c9bc22f3ea6e26c34fd5e4186be0b42a0414558f318b5784079145b267f7316729d54c8ba8c955ee5100e4b9ca9f5048c123a66ad2e277d49dd07c718287c
languageName: node
linkType: hard
"@react-email/head@npm:0.0.12":
version: 0.0.12
resolution: "@react-email/head@npm:0.0.12"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/511147ea52330f5752e2d226a3417192adb5c0f301e35077a07fd66b99504eda6c3bfa49713a10400cf8542d75dfb317e5050b5383b285129db9854d5760d97d
languageName: node
linkType: hard
"@react-email/heading@npm:0.0.15":
version: 0.0.15
resolution: "@react-email/heading@npm:0.0.15"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/74e58d2933eb6d37f4f3a6f82c63af6c9ffe2ce8cd14c7f6e27f8b76d39800cbf1a215d86e17a55d69eca4c73d5e9ea747ae1cd0a7df4a08a861a13afb9989dc
languageName: node
linkType: hard
"@react-email/hr@npm:0.0.11":
version: 0.0.11
resolution: "@react-email/hr@npm:0.0.11"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/9d8199bdcfdc7e180636cdc11b7af5c44d185598fedd97dd0734103d662074ed8b7204e362c31f0dfd3925c37181e2fe22dbf1f76908c862d489f34e7efea7a9
languageName: node
linkType: hard
"@react-email/html@npm:0.0.11":
version: 0.0.11
resolution: "@react-email/html@npm:0.0.11"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/04be96e135677cd507636877c2f9bf1a507d40f6d4442ff3fac58bc70d478e7f23dd03d94ecc1605d3e368d50129281e71f4b7afb242f1b32d285bfc37236a09
languageName: node
linkType: hard
"@react-email/img@npm:0.0.11":
version: 0.0.11
resolution: "@react-email/img@npm:0.0.11"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/082e9f7d7290de4d340b06bc0ab0e4ffec08604885fdf06d93594e3684726279a3a65c0be2c83c9397bb832289078d533f0499b423ed3558f7736ad7d333d457
languageName: node
linkType: hard
"@react-email/link@npm:0.0.12":
version: 0.0.12
resolution: "@react-email/link@npm:0.0.12"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/d831666bd52af9ba3a50bd4853e2b70387a041264e3781d3dab4708b755e8b2cb6df339f71eecd889b35221c205bd9997d47e950d1e3b226b4be50a22405ca87
languageName: node
linkType: hard
"@react-email/markdown@npm:0.0.14":
version: 0.0.14
resolution: "@react-email/markdown@npm:0.0.14"
dependencies:
md-to-react-email: "npm:5.0.5"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/e124a1844704e3c48f189d2d2769ca9f1193499f1c7353a804161b1c5df373fa815255116e653f7228192bcd5ff826ff55eb15c972a8e7facb6c82721511c764
languageName: node
linkType: hard
"@react-email/preview@npm:0.0.12":
version: 0.0.12
resolution: "@react-email/preview@npm:0.0.12"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/54c09fb599263b7e01f290cd3ed37db31b7370cb036851496067470f4873dfe82102e0746e390e9b83e27d9a054044259412521ba65eac7366fb5e17580b7787
languageName: node
linkType: hard
"@react-email/render@npm:0.0.17":
version: 0.0.17
resolution: "@react-email/render@npm:0.0.17"
dependencies:
html-to-text: "npm:9.0.5"
js-beautify: "npm:^1.14.11"
react-promise-suspense: "npm:0.3.4"
peerDependencies:
react: ^18.2.0
react-dom: ^18.2.0
checksum: 10c0/34a1c5a55586d7cd723638d8cd5328fddf30015e5065a2e9d5204772e0532e84d63af1b2b1b8ec02cef52a8f57d34871200c0075a9ed7b2861362d8138d3db5e
languageName: node
linkType: hard
"@react-email/render@npm:1.0.4":
version: 1.0.4
resolution: "@react-email/render@npm:1.0.4"
dependencies:
html-to-text: "npm:9.0.5"
prettier: "npm:3.4.2"
react-promise-suspense: "npm:0.3.4"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/88d01143a634294b4092b847bfe0c71fc28063055c979d0dbe29c226c7d84a9dd673a6c2a035d6091decbb7743faf6a5394a9a38c74a51745bf6031b6d01b087
languageName: node
linkType: hard
"@react-email/row@npm:0.0.12":
version: 0.0.12
resolution: "@react-email/row@npm:0.0.12"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/440c54071543700ce7a0db4749c93c56fa0cfae1057464231b25d9d7598f81a2f395816b922376acd5445c29163ae2858e4fc840d8cf30f3d4520104f7f5e3ed
languageName: node
linkType: hard
"@react-email/section@npm:0.0.16":
version: 0.0.16
resolution: "@react-email/section@npm:0.0.16"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/48bfacdd78d403b50c4c1098d100a96f3afe6159d910374a0306d6186daa1bf3803b4a2b3163fb38d9137835041b9f70145c7bb2f652ba347a82a0d396fe2ef2
languageName: node
linkType: hard
"@react-email/tailwind@npm:1.0.4":
version: 1.0.4
resolution: "@react-email/tailwind@npm:1.0.4"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/47472ae00c1731ec9cce20e1083fcb405c049a378d28889fb5334d6d3fbd1526e13f6c775691f3fa5e6796a30b98b2f3e9e242a61454dfc097dc5f6f5dc5fc8d
languageName: node
linkType: hard
"@react-email/text@npm:0.0.11":
version: 0.0.11
resolution: "@react-email/text@npm:0.0.11"
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
checksum: 10c0/b79545cebe067bbfa7d32d02cc5911bc4f85c939f4f64b2bf181fcba59627ea950d14bb3cfc344641ce8f66876847ddeb3796d8da81a6019b6fe341e1b656db1
languageName: node
linkType: hard
@ -23562,17 +23596,6 @@ __metadata:
languageName: node
linkType: hard
"condense-newlines@npm:^0.2.1":
version: 0.2.1
resolution: "condense-newlines@npm:0.2.1"
dependencies:
extend-shallow: "npm:^2.0.1"
is-whitespace: "npm:^0.3.0"
kind-of: "npm:^3.0.2"
checksum: 10c0/19485db92a5d4658b50ab250626ece0cebe57f73af126b348604309894ed9a2b05f88f1802a090fd1897156eda0af69d8f14446bc62f978e0d048b5135e91694
languageName: node
linkType: hard
"confbox@npm:^0.1.7":
version: 0.1.7
resolution: "confbox@npm:0.1.7"
@ -27573,6 +27596,13 @@ __metadata:
languageName: node
linkType: hard
"fast-deep-equal@npm:^2.0.1":
version: 2.0.1
resolution: "fast-deep-equal@npm:2.0.1"
checksum: 10c0/1602e0d6ed63493c865cc6b03f9070d6d3926e8cd086a123060b58f80a295f3f08b1ecfb479ae7c45b7fd45535202aea7cf5b49bc31bffb81c20b1502300be84
languageName: node
linkType: hard
"fast-deep-equal@npm:^3, fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
version: 3.1.3
resolution: "fast-deep-equal@npm:3.1.3"
@ -31207,7 +31237,7 @@ __metadata:
languageName: node
linkType: hard
"is-buffer@npm:^1.1.0, is-buffer@npm:^1.1.5":
"is-buffer@npm:^1.1.0":
version: 1.1.6
resolution: "is-buffer@npm:1.1.6"
checksum: 10c0/ae18aa0b6e113d6c490ad1db5e8df9bdb57758382b313f5a22c9c61084875c6396d50bbf49315f5b1926d142d74dfb8d31b40d993a383e0a158b15fea7a82234
@ -31789,13 +31819,6 @@ __metadata:
languageName: node
linkType: hard
"is-whitespace@npm:^0.3.0":
version: 0.3.0
resolution: "is-whitespace@npm:0.3.0"
checksum: 10c0/2f4ef13e0195170bbb587437133ef81ed9d6aec1c5e88f4c2b9055a18a1e70f75d9a9376f0cdae64f3c519e05e5f734d6b8f9682e5cb50384843480bade785ae
languageName: node
linkType: hard
"is-windows@npm:^0.2.0":
version: 0.2.0
resolution: "is-windows@npm:0.2.0"
@ -32841,7 +32864,7 @@ __metadata:
languageName: node
linkType: hard
"js-beautify@npm:^1.6.12":
"js-beautify@npm:^1.14.11":
version: 1.15.1
resolution: "js-beautify@npm:1.15.1"
dependencies:
@ -33594,15 +33617,6 @@ __metadata:
languageName: node
linkType: hard
"kind-of@npm:^3.0.2":
version: 3.2.2
resolution: "kind-of@npm:3.2.2"
dependencies:
is-buffer: "npm:^1.1.5"
checksum: 10c0/7e34bc29d4b02c997f92f080de34ebb92033a96736bbb0bb2410e033a7e5ae6571f1fa37b2d7710018f95361473b816c604234197f4f203f9cf149d8ef1574d9
languageName: node
linkType: hard
"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2":
version: 6.0.3
resolution: "kind-of@npm:6.0.3"
@ -34968,6 +34982,15 @@ __metadata:
languageName: node
linkType: hard
"marked@npm:7.0.4":
version: 7.0.4
resolution: "marked@npm:7.0.4"
bin:
marked: bin/marked.js
checksum: 10c0/7f5993bfb2d260806ffada81051c45952857117cba0fd82790779dc696c7ebd35a96be47409b4bdabd75e7ede286f5f5142a75a47200e3fa54eaf8b0cd6f74f6
languageName: node
linkType: hard
"match-sorter@npm:^6.0.2":
version: 6.3.4
resolution: "match-sorter@npm:6.3.4"
@ -34987,6 +35010,17 @@ __metadata:
languageName: node
linkType: hard
"md-to-react-email@npm:5.0.5":
version: 5.0.5
resolution: "md-to-react-email@npm:5.0.5"
dependencies:
marked: "npm:7.0.4"
peerDependencies:
react: ^18.0 || ^19.0
checksum: 10c0/0d6eedb905562d88025fbf45c79117d9d668c86427eac9a3ecc2f5082a7fac9cf55c271f8892083e994d794322e8f0ede928ee2380465c9f4f878cbd2a392999
languageName: node
linkType: hard
"md5.js@npm:^1.3.4":
version: 1.3.5
resolution: "md5.js@npm:1.3.5"
@ -39842,6 +39876,15 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:3.4.2":
version: 3.4.2
resolution: "prettier@npm:3.4.2"
bin:
prettier: bin/prettier.cjs
checksum: 10c0/99e076a26ed0aba4ebc043880d0f08bbb8c59a4c6641cdee6cdadf2205bdd87aa1d7823f50c3aea41e015e99878d37c58d7b5f0e663bba0ef047f94e36b96446
languageName: node
linkType: hard
"prettier@npm:^3.1.1, prettier@npm:^3.2.5":
version: 3.3.3
resolution: "prettier@npm:3.3.3"
@ -39906,17 +39949,6 @@ __metadata:
languageName: node
linkType: hard
"pretty@npm:2.0.0":
version: 2.0.0
resolution: "pretty@npm:2.0.0"
dependencies:
condense-newlines: "npm:^0.2.1"
extend-shallow: "npm:^2.0.1"
js-beautify: "npm:^1.6.12"
checksum: 10c0/2fcd72f331d0afae3893ba88a5c05f6fdd62b059cb309028aa3309fc8a90410d81dfe66ae95677bc6d6d4a68f3cc1a247c13e5872bd35686f99acb33acc51164
languageName: node
linkType: hard
"prettyjson@npm:^1.2.1":
version: 1.2.5
resolution: "prettyjson@npm:1.2.5"
@ -39950,7 +39982,7 @@ __metadata:
languageName: node
linkType: hard
"prismjs@npm:^1.23.0":
"prismjs@npm:1.29.0, prismjs@npm:^1.23.0":
version: 1.29.0
resolution: "prismjs@npm:1.29.0"
checksum: 10c0/d906c4c4d01b446db549b4f57f72d5d7e6ccaca04ecc670fb85cea4d4b1acc1283e945a9cbc3d81819084a699b382f970e02f9d1378e14af9808d366d9ed7ec6
@ -40819,18 +40851,6 @@ __metadata:
languageName: node
linkType: hard
"react-dom@npm:18.2.0":
version: 18.2.0
resolution: "react-dom@npm:18.2.0"
dependencies:
loose-envify: "npm:^1.1.0"
scheduler: "npm:^0.23.0"
peerDependencies:
react: ^18.2.0
checksum: 10c0/66dfc5f93e13d0674e78ef41f92ed21dfb80f9c4ac4ac25a4b51046d41d4d2186abc915b897f69d3d0ebbffe6184e7c5876f2af26bfa956f179225d921be713a
languageName: node
linkType: hard
"react-dom@npm:^18, react-dom@npm:^18.2.0":
version: 18.3.1
resolution: "react-dom@npm:18.3.1"
@ -41061,6 +41081,15 @@ __metadata:
languageName: node
linkType: hard
"react-promise-suspense@npm:0.3.4":
version: 0.3.4
resolution: "react-promise-suspense@npm:0.3.4"
dependencies:
fast-deep-equal: "npm:^2.0.1"
checksum: 10c0/ab7a22f5400f9e9933995537bf6430a4c79e33a121aedb51864968e7604e5c40421fd539ead62554f32300b7d49755c79636de06caa36fe52973b626b4ddfebf
languageName: node
linkType: hard
"react-query@npm:^3.34.19":
version: 3.39.3
resolution: "react-query@npm:3.39.3"
@ -41369,15 +41398,6 @@ __metadata:
languageName: node
linkType: hard
"react@npm:18.2.0":
version: 18.2.0
resolution: "react@npm:18.2.0"
dependencies:
loose-envify: "npm:^1.1.0"
checksum: 10c0/b562d9b569b0cb315e44b48099f7712283d93df36b19a39a67c254c6686479d3980b7f013dc931f4a5a3ae7645eae6386b4aa5eea933baa54ecd0f9acb0902b8
languageName: node
linkType: hard
"react@npm:^18, react@npm:^18.2.0":
version: 18.3.1
resolution: "react@npm:18.3.1"
@ -42830,7 +42850,7 @@ __metadata:
languageName: node
linkType: hard
"scheduler@npm:^0.23.0, scheduler@npm:^0.23.2":
"scheduler@npm:^0.23.2":
version: 0.23.2
resolution: "scheduler@npm:0.23.2"
dependencies:
@ -45827,6 +45847,8 @@ __metadata:
"twenty-chrome-extension@workspace:packages/twenty-chrome-extension":
version: 0.0.0-use.local
resolution: "twenty-chrome-extension@workspace:packages/twenty-chrome-extension"
dependencies:
twenty-shared: "workspace:*"
languageName: unknown
linkType: soft
@ -46059,8 +46081,8 @@ __metadata:
"@playwright/test": "npm:^1.46.0"
"@ptc-org/nestjs-query-core": "npm:^4.2.0"
"@ptc-org/nestjs-query-typeorm": "npm:4.2.1-alpha.2"
"@react-email/components": "npm:0.0.12"
"@react-email/render": "npm:0.0.10"
"@react-email/components": "npm:0.0.32"
"@react-email/render": "npm:0.0.17"
"@sentry/node": "npm:^8"
"@sentry/profiling-node": "npm:^8"
"@sentry/react": "npm:^8"