diff --git a/apps/web/src/app/(recipient)/d/[token]/direct-template.tsx b/apps/web/src/app/(recipient)/d/[token]/direct-template.tsx index 4f9e99fb1..e1c38f3da 100644 --- a/apps/web/src/app/(recipient)/d/[token]/direct-template.tsx +++ b/apps/web/src/app/(recipient)/d/[token]/direct-template.tsx @@ -7,7 +7,7 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; -import { RECIPIENT_ROLES_DESCRIPTION_ENG } from '@documenso/lib/constants/recipient-roles'; +import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; import type { Field } from '@documenso/prisma/client'; import { type Recipient } from '@documenso/prisma/client'; import type { TemplateWithDetails } from '@documenso/prisma/types/template'; @@ -53,7 +53,9 @@ export const DirectTemplatePageView = ({ const [step, setStep] = useState('configure'); const [isDocumentPdfLoaded, setIsDocumentPdfLoaded] = useState(false); - const recipientRoleDescription = RECIPIENT_ROLES_DESCRIPTION_ENG[directTemplateRecipient.role]; + const recipientActionVerb = _( + RECIPIENT_ROLES_DESCRIPTION[directTemplateRecipient.role].actionVerb, + ); const directTemplateFlow: Record = { configure: { @@ -62,9 +64,8 @@ export const DirectTemplatePageView = ({ stepIndex: 1, }, sign: { - // Todo: Translations - title: msg`${recipientRoleDescription.actionVerb} document`, - description: msg`${recipientRoleDescription.actionVerb} the document to complete the process.`, + title: msg`${recipientActionVerb} document`, + description: msg`${recipientActionVerb} the document to complete the process.`, stepIndex: 2, }, }; diff --git a/packages/email/template-components/template-confirmation-email.tsx b/packages/email/template-components/template-confirmation-email.tsx index 0c3c687ec..14c5b1481 100644 --- a/packages/email/template-components/template-confirmation-email.tsx +++ b/packages/email/template-components/template-confirmation-email.tsx @@ -1,5 +1,4 @@ import { Trans } from '@lingui/macro'; -import { useLingui } from '@lingui/react'; import { Button, Section, Text } from '../components'; import { TemplateDocumentImage } from './template-document-image'; @@ -13,8 +12,6 @@ export const TemplateConfirmationEmail = ({ confirmationLink, assetBaseUrl, }: TemplateConfirmationEmailProps) => { - const { _ } = useLingui(); - return ( <> diff --git a/packages/email/template-components/template-document-completed.tsx b/packages/email/template-components/template-document-completed.tsx index ed1dfc25e..497017fd1 100644 --- a/packages/email/template-components/template-document-completed.tsx +++ b/packages/email/template-components/template-document-completed.tsx @@ -38,7 +38,7 @@ export const TemplateDocumentCompleted = ({ - {customBody ?? `“${documentName}” was signed by all signers`} + {customBody || “{documentName}” was signed by all signers} diff --git a/packages/email/template-components/template-document-invite.tsx b/packages/email/template-components/template-document-invite.tsx index 6f59bab2c..f913c6fe9 100644 --- a/packages/email/template-components/template-document-invite.tsx +++ b/packages/email/template-components/template-document-invite.tsx @@ -1,8 +1,9 @@ import { Trans } from '@lingui/macro'; import { useLingui } from '@lingui/react'; +import { match } from 'ts-pattern'; -import { RECIPIENT_ROLES_DESCRIPTION_ENG } from '@documenso/lib/constants/recipient-roles'; -import type { RecipientRole } from '@documenso/prisma/client'; +import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; +import { RecipientRole } from '@documenso/prisma/client'; import { Button, Section, Text } from '../components'; import { TemplateDocumentImage } from './template-document-image'; @@ -31,7 +32,7 @@ export const TemplateDocumentInvite = ({ }: TemplateDocumentInviteProps) => { const { _ } = useLingui(); - const { actionVerb, progressiveVerb } = RECIPIENT_ROLES_DESCRIPTION_ENG[role]; + const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[role]; return ( <> @@ -41,29 +42,29 @@ export const TemplateDocumentInvite = ({ {selfSigner ? ( - {`Please ${_(actionVerb).toLowerCase()} your document`} -
- {`"${documentName}"`} + Please {_(actionVerb).toLowerCase()} your document +
"{documentName}"
) : isTeamInvite ? ( - {`${inviterName} on behalf of ${teamName} has invited you to ${_( - actionVerb, - ).toLowerCase()}`} -
- {`"${documentName}"`} + {inviterName} on behalf of {teamName} has invited you to {_(actionVerb).toLowerCase()} +
"{documentName}"
) : ( - {`${inviterName} has invited you to ${_(actionVerb).toLowerCase()}`} -
- {`"${documentName}"`} + {inviterName} has invited you to {_(actionVerb).toLowerCase()} +
"{documentName}"
)}
- Continue by {_(progressiveVerb).toLowerCase()} the document. + {match(role) + .with(RecipientRole.SIGNER, () => Continue by signing the document.) + .with(RecipientRole.VIEWER, () => Continue by viewing the document.) + .with(RecipientRole.APPROVER, () => Continue by approving the document.) + .with(RecipientRole.CC, () => '') + .exhaustive()}
@@ -71,7 +72,12 @@ export const TemplateDocumentInvite = ({ className="bg-documenso-500 inline-flex items-center justify-center rounded-lg px-6 py-3 text-center text-sm font-medium text-black no-underline" href={signDocumentLink} > - {_(actionVerb)} Document + {match(role) + .with(RecipientRole.SIGNER, () => Sign Document) + .with(RecipientRole.VIEWER, () => View Document) + .with(RecipientRole.APPROVER, () => Approve Document) + .with(RecipientRole.CC, () => '') + .exhaustive()}
diff --git a/packages/email/templates/document-created-from-direct-template.tsx b/packages/email/templates/document-created-from-direct-template.tsx index 63d46c9b8..74739de75 100644 --- a/packages/email/templates/document-created-from-direct-template.tsx +++ b/packages/email/templates/document-created-from-direct-template.tsx @@ -1,7 +1,7 @@ import { Trans, msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; -import { RECIPIENT_ROLES_DESCRIPTION_ENG } from '@documenso/lib/constants/recipient-roles'; +import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; import { Body, Button, Container, Head, Html, Img, Preview, Section, Text } from '../components'; import TemplateDocumentImage from '../template-components/template-document-image'; @@ -25,7 +25,7 @@ export const DocumentCreatedFromDirectTemplateEmailTemplate = ({ }: DocumentCompletedEmailTemplateProps) => { const { _ } = useLingui(); - const action = _(RECIPIENT_ROLES_DESCRIPTION_ENG[recipientRole].actioned).toLowerCase(); + const action = _(RECIPIENT_ROLES_DESCRIPTION[recipientRole].actioned).toLowerCase(); const previewText = msg`Document created from direct template`; diff --git a/packages/email/templates/document-invite.tsx b/packages/email/templates/document-invite.tsx index edfd525f1..884a12023 100644 --- a/packages/email/templates/document-invite.tsx +++ b/packages/email/templates/document-invite.tsx @@ -1,7 +1,7 @@ import { Trans, msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; -import { RECIPIENT_ROLES_DESCRIPTION_ENG } from '@documenso/lib/constants/recipient-roles'; +import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; import type { RecipientRole } from '@documenso/prisma/client'; import { Body, Container, Head, Hr, Html, Img, Link, Preview, Section, Text } from '../components'; @@ -32,7 +32,7 @@ export const DocumentInviteEmailTemplate = ({ }: DocumentInviteEmailTemplateProps) => { const { _ } = useLingui(); - const action = _(RECIPIENT_ROLES_DESCRIPTION_ENG[role].actionVerb).toLowerCase(); + const action = _(RECIPIENT_ROLES_DESCRIPTION[role].actionVerb).toLowerCase(); const previewText = selfSigner ? msg`Please ${action} your document ${documentName}` @@ -89,7 +89,7 @@ export const DocumentInviteEmailTemplate = ({
{customBody}
) : ( - `${inviterName} has invited you to ${action} the document "${documentName}".` + {inviterName} has invited you to {action} the document {documentName}. )}
diff --git a/packages/email/templates/recipient-removed-from-document.tsx b/packages/email/templates/recipient-removed-from-document.tsx index 2ba19dc03..ad70db070 100644 --- a/packages/email/templates/recipient-removed-from-document.tsx +++ b/packages/email/templates/recipient-removed-from-document.tsx @@ -1,4 +1,4 @@ -import { msg } from '@lingui/macro'; +import { Trans, msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; import { Body, Container, Head, Hr, Html, Img, Preview, Section, Text } from '../components'; @@ -40,8 +40,10 @@ export const RecipientRemovedFromDocumentTemplate = ({
- {inviterName} has removed you from the document -
"{documentName}" + + {inviterName} has removed you from the document +
"{documentName}" +
diff --git a/packages/lib/constants/recipient-roles.ts b/packages/lib/constants/recipient-roles.ts index 51b890268..ad994c98d 100644 --- a/packages/lib/constants/recipient-roles.ts +++ b/packages/lib/constants/recipient-roles.ts @@ -9,59 +9,27 @@ export const RECIPIENT_ROLES_DESCRIPTION = { actioned: msg`Approved`, progressiveVerb: msg`Approving`, roleName: msg`Approver`, + roleNamePlural: msg`Approvers`, }, [RecipientRole.CC]: { actionVerb: msg`CC`, actioned: msg`CC'd`, progressiveVerb: msg`CC`, roleName: msg`Cc`, + roleNamePlural: msg`Ccers`, }, [RecipientRole.SIGNER]: { actionVerb: msg`Sign`, actioned: msg`Signed`, progressiveVerb: msg`Signing`, roleName: msg`Signer`, + roleNamePlural: msg`Signers`, }, [RecipientRole.VIEWER]: { actionVerb: msg`View`, actioned: msg`Viewed`, progressiveVerb: msg`Viewing`, roleName: msg`Viewer`, - }, -} satisfies Record; - -/** - * Raw english descriptions for emails. - * - * Todo: Handle i18n for emails. - */ -export const RECIPIENT_ROLES_DESCRIPTION_ENG = { - [RecipientRole.APPROVER]: { - actionVerb: `Approve`, - actioned: `Approved`, - progressiveVerb: `Approving`, - roleName: `Approver`, - roleNamePlural: msg`Approvers`, - }, - [RecipientRole.CC]: { - actionVerb: `CC`, - actioned: `CC'd`, - progressiveVerb: `CC`, - roleName: `Cc`, - roleNamePlural: msg`Ccers`, - }, - [RecipientRole.SIGNER]: { - actionVerb: `Sign`, - actioned: `Signed`, - progressiveVerb: `Signing`, - roleName: `Signer`, - roleNamePlural: msg`Signers`, - }, - [RecipientRole.VIEWER]: { - actionVerb: `View`, - actioned: `Viewed`, - progressiveVerb: `Viewing`, - roleName: `Viewer`, roleNamePlural: msg`Viewers`, }, } satisfies Record; diff --git a/packages/lib/jobs/definitions/emails/send-signing-email.ts b/packages/lib/jobs/definitions/emails/send-signing-email.ts index 552dbae72..f272eba16 100644 --- a/packages/lib/jobs/definitions/emails/send-signing-email.ts +++ b/packages/lib/jobs/definitions/emails/send-signing-email.ts @@ -17,7 +17,7 @@ import { getI18nInstance } from '../../../client-only/providers/i18n.server'; import { NEXT_PUBLIC_WEBAPP_URL } from '../../../constants/app'; import { FROM_ADDRESS, FROM_NAME } from '../../../constants/email'; import { - RECIPIENT_ROLES_DESCRIPTION_ENG, + RECIPIENT_ROLES_DESCRIPTION, RECIPIENT_ROLE_TO_EMAIL_TYPE, } from '../../../constants/recipient-roles'; import { DOCUMENT_AUDIT_LOG_TYPE } from '../../../types/document-audit-logs'; @@ -89,11 +89,13 @@ export const SEND_SIGNING_EMAIL_JOB_DEFINITION = { const { email, name } = recipient; const selfSigner = email === user.email; - const recipientActionVerb = - RECIPIENT_ROLES_DESCRIPTION_ENG[recipient.role].actionVerb.toLowerCase(); const i18n = await getI18nInstance(documentMeta?.language); + const recipientActionVerb = i18n + ._(RECIPIENT_ROLES_DESCRIPTION[recipient.role].actionVerb) + .toLowerCase(); + let emailMessage = customEmail?.message || ''; let emailSubject = i18n._(msg`Please ${recipientActionVerb} this document`); diff --git a/packages/ui/primitives/document-flow/add-fields.tsx b/packages/ui/primitives/document-flow/add-fields.tsx index 3adb96b5e..ff0e4592e 100644 --- a/packages/ui/primitives/document-flow/add-fields.tsx +++ b/packages/ui/primitives/document-flow/add-fields.tsx @@ -28,7 +28,7 @@ import { prop, sortBy } from 'remeda'; import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect'; import { useDocumentElement } from '@documenso/lib/client-only/hooks/use-document-element'; import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; -import { RECIPIENT_ROLES_DESCRIPTION_ENG } from '@documenso/lib/constants/recipient-roles'; +import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; import { type TFieldMetaSchema as FieldMeta, ZFieldMetaSchema, @@ -690,7 +690,7 @@ export const AddFieldsFormPartial = ({ {recipientsByRoleToDisplay.map(([role, roleRecipients], roleIndex) => (
- {_(RECIPIENT_ROLES_DESCRIPTION_ENG[role].roleNamePlural)} + {_(RECIPIENT_ROLES_DESCRIPTION[role].roleNamePlural)}
{roleRecipients.length === 0 && ( diff --git a/packages/ui/primitives/template-flow/add-template-fields.tsx b/packages/ui/primitives/template-flow/add-template-fields.tsx index ec5bcef07..b515684a1 100644 --- a/packages/ui/primitives/template-flow/add-template-fields.tsx +++ b/packages/ui/primitives/template-flow/add-template-fields.tsx @@ -23,7 +23,7 @@ import { useFieldArray, useForm } from 'react-hook-form'; import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect'; import { useDocumentElement } from '@documenso/lib/client-only/hooks/use-document-element'; import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; -import { RECIPIENT_ROLES_DESCRIPTION_ENG } from '@documenso/lib/constants/recipient-roles'; +import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; import { type TFieldMetaSchema as FieldMeta, ZFieldMetaSchema, @@ -508,7 +508,7 @@ export const AddTemplateFieldsFormPartial = ({ {recipientsByRoleToDisplay.map(([role, roleRecipients], roleIndex) => (
- {_(RECIPIENT_ROLES_DESCRIPTION_ENG[role].roleNamePlural)} + {_(RECIPIENT_ROLES_DESCRIPTION[role].roleNamePlural)}
{roleRecipients.length === 0 && (