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

@ -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,