feat: improve translation coverage (#1427)

Improves translation coverage across the app.
This commit is contained in:
David Nguyen
2024-11-01 08:57:32 +09:00
committed by GitHub
parent 0cee07aed3
commit f199183c78
41 changed files with 1746 additions and 439 deletions

View File

@ -87,7 +87,7 @@ export const DeleteDocumentDialog = ({
const onInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
setIsDeleteEnabled(event.target.value === 'delete');
setIsDeleteEnabled(event.target.value === _(msg`delete`));
};
return (

View File

@ -117,10 +117,10 @@ export const MoveDocumentDialog = ({ documentId, open, onOpenChange }: MoveDocum
<DialogFooter>
<Button variant="secondary" onClick={() => onOpenChange(false)}>
Cancel
<Trans>Cancel</Trans>
</Button>
<Button onClick={onMove} loading={isLoading} disabled={!selectedTeamId || isLoading}>
{isLoading ? 'Moving...' : 'Move'}
{isLoading ? <Trans>Moving...</Trans> : <Trans>Move</Trans>}
</Button>
</DialogFooter>
</DialogContent>

View File

@ -1,7 +1,7 @@
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans } from '@lingui/macro';
import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { useSession } from 'next-auth/react';
import { useForm } from 'react-hook-form';
@ -77,7 +77,7 @@ export const ConfigureDirectTemplateFormPartial = ({
if (template.Recipient.map((recipient) => recipient.email).includes(items.email)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Email cannot already exist in the template',
message: _(msg`Email cannot already exist in the template`),
path: ['email'],
});
}

View File

@ -222,7 +222,7 @@ export default async function CompletedSigningPage({
)}
{isLoggedIn && (
<Link href="/documents" className="text-documenso-700 hover:text-documenso-600">
<Link href="/documents" className="text-documenso-700 hover:text-documenso-600 mt-2">
<Trans>Go Back Home</Trans>
</Link>
)}

View File

@ -124,9 +124,9 @@ export const SigningForm = ({
>
<div className={cn('flex flex-1 flex-col')}>
<h3 className="text-foreground text-2xl font-semibold">
{recipient.role === RecipientRole.VIEWER && 'View Document'}
{recipient.role === RecipientRole.SIGNER && 'Sign Document'}
{recipient.role === RecipientRole.APPROVER && 'Approve Document'}
{recipient.role === RecipientRole.VIEWER && <Trans>View Document</Trans>}
{recipient.role === RecipientRole.SIGNER && <Trans>Sign Document</Trans>}
{recipient.role === RecipientRole.APPROVER && <Trans>Approve Document</Trans>}
</h3>
{recipient.role === RecipientRole.VIEWER ? (
@ -166,7 +166,7 @@ export const SigningForm = ({
) : (
<>
<p className="text-muted-foreground mt-2 text-sm">
Please review the document before signing.
<Trans>Please review the document before signing.</Trans>
</p>
<hr className="border-border mb-8 mt-4" />
@ -174,7 +174,9 @@ export const SigningForm = ({
<div className="-mx-2 flex flex-1 flex-col gap-4 overflow-y-auto px-2">
<div className="flex flex-1 flex-col gap-y-4">
<div>
<Label htmlFor="full-name">Full Name</Label>
<Label htmlFor="full-name">
<Trans>Full Name</Trans>
</Label>
<Input
type="text"
@ -186,7 +188,9 @@ export const SigningForm = ({
</div>
<div>
<Label htmlFor="Signature">Signature</Label>
<Label htmlFor="Signature">
<Trans>Signature</Trans>
</Label>
<Card className="mt-2" gradient degrees={-120}>
<CardContent className="p-0">
@ -213,7 +217,7 @@ export const SigningForm = ({
disabled={typeof window !== 'undefined' && window.history.length <= 1}
onClick={() => router.back()}
>
Cancel
<Trans>Cancel</Trans>
</Button>
<SignDialog

View File

@ -4,6 +4,8 @@ import { useTransition } from 'react';
import { useRouter } from 'next/navigation';
import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { Loader } from 'lucide-react';
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
@ -37,6 +39,7 @@ export const InitialsField = ({
}: InitialsFieldProps) => {
const router = useRouter();
const { toast } = useToast();
const { _ } = useLingui();
const { fullName } = useRequiredSigningContext();
const initials = extractInitials(fullName);
@ -83,8 +86,8 @@ export const InitialsField = ({
console.error(err);
toast({
title: 'Error',
description: 'An error occurred while signing the document.',
title: _(msg`Error`),
description: _(msg`An error occurred while signing the document.`),
variant: 'destructive',
});
}
@ -109,8 +112,8 @@ export const InitialsField = ({
console.error(err);
toast({
title: 'Error',
description: 'An error occurred while removing the signature.',
title: _(msg`Error`),
description: _(msg`An error occurred while removing the field.`),
variant: 'destructive',
});
}
@ -126,7 +129,7 @@ export const InitialsField = ({
{!field.inserted && (
<p className="group-hover:text-primary text-muted-foreground duration-200 group-hover:text-yellow-300">
Initials
<Trans>Initials</Trans>
</p>
)}

View File

@ -5,101 +5,156 @@ import { Trans } from '@lingui/macro';
import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server';
import { Button } from '@documenso/ui/primitives/button';
const SUPPORT_EMAIL = 'support@documenso.com';
export default function SignatureDisclosure() {
setupI18nSSR();
return (
<div>
<article className="prose dark:prose-invert">
<h1>Electronic Signature Disclosure</h1>
<h1>
<Trans>Electronic Signature Disclosure</Trans>
</h1>
<h2>Welcome</h2>
<h2>
<Trans>Welcome</Trans>
</h2>
<p>
Thank you for using Documenso to perform your electronic document signing. The purpose of
this disclosure is to inform you about the process, legality, and your rights regarding
the use of electronic signatures on our platform. By opting to use an electronic
signature, you are agreeing to the terms and conditions outlined below.
<Trans>
Thank you for using Documenso to perform your electronic document signing. The purpose
of this disclosure is to inform you about the process, legality, and your rights
regarding the use of electronic signatures on our platform. By opting to use an
electronic signature, you are agreeing to the terms and conditions outlined below.
</Trans>
</p>
<h2>Acceptance and Consent</h2>
<h2>
<Trans>Acceptance and Consent</Trans>
</h2>
<p>
When you use our platform to affix your electronic signature to documents, you are
consenting to do so under the Electronic Signatures in Global and National Commerce Act
(E-Sign Act) and other applicable laws. This action indicates your agreement to use
electronic means to sign documents and receive notifications.
<Trans>
When you use our platform to affix your electronic signature to documents, you are
consenting to do so under the Electronic Signatures in Global and National Commerce Act
(E-Sign Act) and other applicable laws. This action indicates your agreement to use
electronic means to sign documents and receive notifications.
</Trans>
</p>
<h2>Legality of Electronic Signatures</h2>
<h2>
<Trans>Legality of Electronic Signatures</Trans>
</h2>
<p>
An electronic signature provided by you on our platform, achieved through clicking through
to a document and entering your name, or any other electronic signing method we provide,
is legally binding. It carries the same weight and enforceability as a manual signature
written with ink on paper.
<Trans>
An electronic signature provided by you on our platform, achieved through clicking
through to a document and entering your name, or any other electronic signing method we
provide, is legally binding. It carries the same weight and enforceability as a manual
signature written with ink on paper.
</Trans>
</p>
<h2>System Requirements</h2>
<p>To use our electronic signature service, you must have access to:</p>
<h2>
<Trans>System Requirements</Trans>
</h2>
<p>
<Trans>To use our electronic signature service, you must have access to:</Trans>
</p>
<ul>
<li>A stable internet connection</li>
<li>An email account</li>
<li>A device capable of accessing, opening, and reading documents</li>
<li>A means to print or download documents for your records</li>
<li>
<Trans>A stable internet connection</Trans>
</li>
<li>
<Trans>An email account</Trans>
</li>
<li>
<Trans>A device capable of accessing, opening, and reading documents</Trans>
</li>
<li>
<Trans>A means to print or download documents for your records</Trans>
</li>
</ul>
<h2>Electronic Delivery of Documents</h2>
<h2>
<Trans>Electronic Delivery of Documents</Trans>
</h2>
<p>
All documents related to the electronic signing process will be provided to you
electronically through our platform or via email. It is your responsibility to ensure that
your email address is current and that you can receive and open our emails.
<Trans>
All documents related to the electronic signing process will be provided to you
electronically through our platform or via email. It is your responsibility to ensure
that your email address is current and that you can receive and open our emails.
</Trans>
</p>
<h2>Consent to Electronic Transactions</h2>
<h2>
<Trans>Consent to Electronic Transactions</Trans>
</h2>
<p>
By using the electronic signature feature, you are consenting to conduct transactions and
receive disclosures electronically. You acknowledge that your electronic signature on
documents is binding and that you accept the terms outlined in the documents you are
signing.
<Trans>
By using the electronic signature feature, you are consenting to conduct transactions
and receive disclosures electronically. You acknowledge that your electronic signature
on documents is binding and that you accept the terms outlined in the documents you are
signing.
</Trans>
</p>
<h2>Withdrawing Consent</h2>
<h2>
<Trans>Withdrawing Consent</Trans>
</h2>
<p>
You have the right to withdraw your consent to use electronic signatures at any time
before completing the signing process. To withdraw your consent, please contact the sender
of the document. In failing to contact the sender you may reach out to{' '}
<a href="mailto:support@documenso.com">support@documenso.com</a> for assistance. Be aware
that withdrawing consent may delay or halt the completion of the related transaction or
service.
<Trans>
You have the right to withdraw your consent to use electronic signatures at any time
before completing the signing process. To withdraw your consent, please contact the
sender of the document. In failing to contact the sender you may reach out to{' '}
<a href={`mailto:${SUPPORT_EMAIL}`}>{SUPPORT_EMAIL}</a> for assistance. Be aware that
withdrawing consent may delay or halt the completion of the related transaction or
service.
</Trans>
</p>
<h2>Updating Your Information</h2>
<h2>
<Trans>Updating Your Information</Trans>
</h2>
<p>
It is crucial to keep your contact information, especially your email address, up to date
with us. Please notify us immediately of any changes to ensure that you continue to
receive all necessary communications.
<Trans>
It is crucial to keep your contact information, especially your email address, up to
date with us. Please notify us immediately of any changes to ensure that you continue to
receive all necessary communications.
</Trans>
</p>
<h2>Retention of Documents</h2>
<h2>
<Trans>Retention of Documents</Trans>
</h2>
<p>
After signing a document electronically, you will be provided the opportunity to view,
download, and print the document for your records. It is highly recommended that you
retain a copy of all electronically signed documents for your personal records. We will
also retain a copy of the signed document for our records however we may not be able to
provide you with a copy of the signed document after a certain period of time.
<Trans>
After signing a document electronically, you will be provided the opportunity to view,
download, and print the document for your records. It is highly recommended that you
retain a copy of all electronically signed documents for your personal records. We will
also retain a copy of the signed document for our records however we may not be able to
provide you with a copy of the signed document after a certain period of time.
</Trans>
</p>
<h2>Acknowledgment</h2>
<h2>
<Trans>Acknowledgment</Trans>
</h2>
<p>
By proceeding to use the electronic signature service provided by Documenso, you affirm
that you have read and understood this disclosure. You agree to all terms and conditions
related to the use of electronic signatures and electronic transactions as outlined
herein.
<Trans>
By proceeding to use the electronic signature service provided by Documenso, you affirm
that you have read and understood this disclosure. You agree to all terms and conditions
related to the use of electronic signatures and electronic transactions as outlined
herein.
</Trans>
</p>
<h2>Contact Information</h2>
<h2>
<Trans>Contact Information</Trans>
</h2>
<p>
For any questions regarding this disclosure, electronic signatures, or any related
process, please contact us at:{' '}
<a href="mailto:support@documenso.com">support@documenso.com</a>
<Trans>
For any questions regarding this disclosure, electronic signatures, or any related
process, please contact us at: <a href={`mailto:${SUPPORT_EMAIL}`}>{SUPPORT_EMAIL}</a>
</Trans>
</p>
</article>

View File

@ -4,12 +4,18 @@ import { useCallback, useEffect, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value';
import { Input } from '@documenso/ui/primitives/input';
export const DocumentSearch = ({ initialValue = '' }: { initialValue?: string }) => {
const { _ } = useLingui();
const router = useRouter();
const searchParams = useSearchParams();
const [searchTerm, setSearchTerm] = useState(initialValue);
const debouncedSearchTerm = useDebouncedValue(searchTerm, 500);
@ -33,7 +39,7 @@ export const DocumentSearch = ({ initialValue = '' }: { initialValue?: string })
return (
<Input
type="search"
placeholder="Search documents..."
placeholder={_(msg`Search documents...`)}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>

View File

@ -1,7 +1,9 @@
import { msg } from '@lingui/macro';
export const EXPIRATION_DATES = {
ONE_WEEK: '7 days',
ONE_MONTH: '1 month',
THREE_MONTHS: '3 months',
SIX_MONTHS: '6 months',
ONE_YEAR: '12 months',
ONE_WEEK: msg`7 days`,
ONE_MONTH: msg`1 month`,
THREE_MONTHS: msg`3 months`,
SIX_MONTHS: msg`6 months`,
ONE_YEAR: msg`12 months`,
} as const;

View File

@ -53,7 +53,7 @@ export default function DeleteTokenDialog({
const [isOpen, setIsOpen] = useState(false);
const deleteMessage = `delete ${token.name}`;
const deleteMessage = _(msg`delete ${token.name}`);
const ZDeleteTokenDialogSchema = z.object({
tokenName: z.literal(deleteMessage, {

View File

@ -51,7 +51,7 @@ export const DeleteWebhookDialog = ({ webhook, children }: DeleteWebhookDialogPr
const [open, setOpen] = useState(false);
const deleteMessage = `delete ${webhook.webhookUrl}`;
const deleteMessage = _(msg`delete ${webhook.webhookUrl}`);
const ZDeleteWebhookFormSchema = z.object({
webhookUrl: z.literal(deleteMessage, {

View File

@ -47,7 +47,7 @@ export const DeleteTeamDialog = ({ trigger, teamId, teamName }: DeleteTeamDialog
const { _ } = useLingui();
const { toast } = useToast();
const deleteMessage = `delete ${teamName}`;
const deleteMessage = _(msg`delete ${teamName}`);
const ZDeleteTeamFormSchema = z.object({
teamName: z.literal(deleteMessage, {

View File

@ -73,7 +73,7 @@ export const TransferTeamDialog = ({
teamId,
});
const confirmTransferMessage = `transfer ${teamName}`;
const confirmTransferMessage = _(msg`transfer ${teamName}`);
const ZTransferTeamFormSchema = z.object({
teamName: z.literal(confirmTransferMessage, {

View File

@ -83,7 +83,7 @@ export const CurrentUserTeamsDataTable = () => {
accessorKey: 'role',
cell: ({ row }) =>
row.original.ownerUserId === row.original.currentTeamMember.userId
? 'Owner'
? _(msg`Owner`)
: _(TEAM_MEMBER_ROLE_MAP[row.original.currentTeamMember.role]),
},
{

View File

@ -106,7 +106,7 @@ export const TeamMembersDataTable = ({
accessorKey: 'role',
cell: ({ row }) =>
teamOwnerUserId === row.original.userId
? 'Owner'
? _(msg`Owner`)
: _(TEAM_MEMBER_ROLE_MAP[row.original.role]),
},
{

View File

@ -2,6 +2,7 @@
import { useState } from 'react';
import { useLingui } from '@lingui/react';
import { EyeOffIcon } from 'lucide-react';
import { P, match } from 'ts-pattern';
@ -12,6 +13,7 @@ import {
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones';
import type { DocumentField } from '@documenso/lib/server-only/field/get-fields-for-document';
import { parseMessageDescriptor } from '@documenso/lib/utils/i18n';
import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
import type { DocumentMeta } from '@documenso/prisma/client';
import { FieldType, SigningStatus } from '@documenso/prisma/client';
@ -28,6 +30,8 @@ export type DocumentReadOnlyFieldsProps = {
};
export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnlyFieldsProps) => {
const { _ } = useLingui();
const [hiddenFieldIds, setHiddenFieldIds] = useState<Record<string, boolean>>({});
const handleHideField = (fieldId: string) => {
@ -59,7 +63,7 @@ export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnl
>
<p className="font-semibold">
{field.Recipient.signingStatus === SigningStatus.SIGNED ? 'Signed' : 'Pending'}{' '}
{FRIENDLY_FIELD_TYPE[field.type].toLowerCase()} field
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type]).toLowerCase()} field
</p>
<p className="text-muted-foreground text-xs">
@ -127,7 +131,7 @@ export const DocumentReadOnlyFields = ({ documentMeta, fields }: DocumentReadOnl
field.type === FieldType.FREE_SIGNATURE,
})}
>
{FRIENDLY_FIELD_TYPE[field.type]}
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type])}
</p>
)}
</div>

View File

@ -202,7 +202,7 @@ export const ApiTokenForm = ({ className, teamId, tokens }: ApiTokenFormProps) =
<SelectContent>
{Object.entries(EXPIRATION_DATES).map(([key, date]) => (
<SelectItem key={key} value={key}>
{date}
{_(date)}
</SelectItem>
))}
</SelectContent>

View File

@ -2,6 +2,8 @@ import type { HTMLAttributes } from 'react';
import Link from 'next/link';
import { Trans } from '@lingui/macro';
import { cn } from '@documenso/ui/lib/utils';
export type SigningDisclosureProps = HTMLAttributes<HTMLParagraphElement>;
@ -9,20 +11,24 @@ export type SigningDisclosureProps = HTMLAttributes<HTMLParagraphElement>;
export const SigningDisclosure = ({ className, ...props }: SigningDisclosureProps) => {
return (
<p className={cn('text-muted-foreground text-xs', className)} {...props}>
By proceeding with your electronic signature, you acknowledge and consent that it will be used
to sign the given document and holds the same legal validity as a handwritten signature. By
completing the electronic signing process, you affirm your understanding and acceptance of
these conditions.
<Trans>
By proceeding with your electronic signature, you acknowledge and consent that it will be
used to sign the given document and holds the same legal validity as a handwritten
signature. By completing the electronic signing process, you affirm your understanding and
acceptance of these conditions.
</Trans>
<span className="mt-2 block">
Read the full{' '}
<Link
className="text-documenso-700 underline"
href="/articles/signature-disclosure"
target="_blank"
>
signature disclosure
</Link>
.
<Trans>
Read the full{' '}
<Link
className="text-documenso-700 underline"
href="/articles/signature-disclosure"
target="_blank"
>
signature disclosure
</Link>
.
</Trans>
</span>
</p>
);