diff --git a/apps/marketing/package.json b/apps/marketing/package.json index fb6478fca..a1c25d459 100644 --- a/apps/marketing/package.json +++ b/apps/marketing/package.json @@ -20,7 +20,6 @@ "@documenso/trpc": "*", "@documenso/ui": "*", "@hookform/resolvers": "^3.1.0", - "@lingui/macro": "^4.11.1", "@lingui/react": "^4.11.1", "@openstatus/react": "^0.0.3", "cmdk": "^0.2.1", diff --git a/apps/marketing/src/app/(marketing)/singleplayer/client.tsx b/apps/marketing/src/app/(marketing)/singleplayer/client.tsx index 2d8bbe9d9..a3df5af29 100644 --- a/apps/marketing/src/app/(marketing)/singleplayer/client.tsx +++ b/apps/marketing/src/app/(marketing)/singleplayer/client.tsx @@ -5,6 +5,8 @@ import { useEffect, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; +import { msg } from '@lingui/macro'; + import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { base64 } from '@documenso/lib/universal/base64'; @@ -46,8 +48,8 @@ export const SinglePlayerClient = () => { const documentFlow: Record = { fields: { - title: 'Add document', - description: 'Upload a document and add fields.', + title: msg`Add document`, + description: msg`Upload a document and add fields.`, stepIndex: 1, onBackStep: uploadedFile ? () => { @@ -58,8 +60,8 @@ export const SinglePlayerClient = () => { onNextStep: () => setStep('sign'), }, sign: { - title: 'Sign', - description: 'Enter your details.', + title: msg`Sign`, + description: msg`Enter your details.`, stepIndex: 2, onBackStep: () => setStep('fields'), }, diff --git a/apps/web/lingui.config.ts b/apps/web/lingui.config.ts index f129b49ce..a5862eb98 100644 --- a/apps/web/lingui.config.ts +++ b/apps/web/lingui.config.ts @@ -8,7 +8,7 @@ const config: LinguiConfig = { locales: APP_I18N_OPTIONS.supportedLangs as unknown as string[], catalogs: [ { - path: '/../../packages/lib/translations/web/{locale}', + path: '/../../packages/lib/translations/{locale}/web', include: ['/apps/web/src'], }, { diff --git a/apps/web/package.json b/apps/web/package.json index f86e5769a..be73389c8 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -23,7 +23,6 @@ "@documenso/trpc": "*", "@documenso/ui": "*", "@hookform/resolvers": "^3.1.0", - "@lingui/macro": "^4.11.1", "@lingui/react": "^4.11.1", "@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/server": "^9.0.3", @@ -60,9 +59,9 @@ "zod": "^3.22.4" }, "devDependencies": { + "@documenso/tailwind-config": "*", "@lingui/loader": "^4.11.1", "@lingui/swc-plugin": "4.0.6", - "@documenso/tailwind-config": "*", "@simplewebauthn/types": "^9.0.1", "@types/formidable": "^2.0.6", "@types/luxon": "^3.3.1", diff --git a/apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx b/apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx index f084b5db5..330f31eb1 100644 --- a/apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx +++ b/apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx @@ -2,6 +2,9 @@ import Link from 'next/link'; +import { Trans, msg } from '@lingui/macro'; +import { useLingui } from '@lingui/react'; + import type { Recipient } from '@documenso/prisma/client'; import { type Document, SigningStatus } from '@documenso/prisma/client'; import { trpc } from '@documenso/trpc/react'; @@ -22,20 +25,21 @@ export type AdminActionsProps = { }; export const AdminActions = ({ className, document, recipients }: AdminActionsProps) => { + const { _ } = useLingui(); const { toast } = useToast(); const { mutate: resealDocument, isLoading: isResealDocumentLoading } = trpc.admin.resealDocument.useMutation({ onSuccess: () => { toast({ - title: 'Success', - description: 'Document resealed', + title: _(msg`Success`), + description: _(msg`Document resealed`), }); }, onError: () => { toast({ - title: 'Error', - description: 'Failed to reseal document', + title: _(msg`Error`), + description: _(msg`Failed to reseal document`), variant: 'destructive', }); }, @@ -54,19 +58,23 @@ export const AdminActions = ({ className, document, recipients }: AdminActionsPr )} onClick={() => resealDocument({ id: document.id })} > - Reseal document + Reseal document - Attempts sealing the document again, useful for after a code change has occurred to - resolve an erroneous document. + + Attempts sealing the document again, useful for after a code change has occurred to + resolve an erroneous document. + ); diff --git a/apps/web/src/app/(dashboard)/admin/documents/[id]/page.tsx b/apps/web/src/app/(dashboard)/admin/documents/[id]/page.tsx index 563db8d1b..48211fbc0 100644 --- a/apps/web/src/app/(dashboard)/admin/documents/[id]/page.tsx +++ b/apps/web/src/app/(dashboard)/admin/documents/[id]/page.tsx @@ -1,5 +1,7 @@ +import { Trans } from '@lingui/macro'; import { DateTime } from 'luxon'; +import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server'; import { getEntireDocument } from '@documenso/lib/server-only/admin/get-entire-document'; import { Accordion, @@ -23,6 +25,8 @@ type AdminDocumentDetailsPageProps = { }; export default async function AdminDocumentDetailsPage({ params }: AdminDocumentDetailsPageProps) { + setupI18nSSR(); + const document = await getEntireDocument({ id: Number(params.id) }); return ( @@ -35,28 +39,34 @@ export default async function AdminDocumentDetailsPage({ params }: AdminDocument {document.deletedAt && ( - Deleted + Deleted )}
- Created on: + Created on:{' '} +
- Last updated at: + Last updated at:{' '} +

-

Admin Actions

+

+ Admin Actions +


-

Recipients

+

+ Recipients +

diff --git a/apps/web/src/app/(dashboard)/admin/documents/[id]/recipient-item.tsx b/apps/web/src/app/(dashboard)/admin/documents/[id]/recipient-item.tsx index 3bf8c78ab..92304a62e 100644 --- a/apps/web/src/app/(dashboard)/admin/documents/[id]/recipient-item.tsx +++ b/apps/web/src/app/(dashboard)/admin/documents/[id]/recipient-item.tsx @@ -2,6 +2,8 @@ import { useRouter } from 'next/navigation'; +import { Trans, msg } from '@lingui/macro'; +import { useLingui } from '@lingui/react'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; @@ -43,7 +45,9 @@ export type RecipientItemProps = { }; export const RecipientItem = ({ recipient }: RecipientItemProps) => { + const { _ } = useLingui(); const { toast } = useToast(); + const router = useRouter(); const form = useForm({ @@ -64,14 +68,14 @@ export const RecipientItem = ({ recipient }: RecipientItemProps) => { }); toast({ - title: 'Recipient updated', - description: 'The recipient has been updated successfully', + title: _(msg`Recipient updated`), + description: _(msg`The recipient has been updated successfully`), }); router.refresh(); } catch (error) { toast({ - title: 'Failed to update recipient', + title: _(msg`Failed to update recipient`), description: error.message, variant: 'destructive', }); @@ -93,7 +97,9 @@ export const RecipientItem = ({ recipient }: RecipientItemProps) => { name="name" render={({ field }) => ( - Name + + Name + @@ -109,7 +115,9 @@ export const RecipientItem = ({ recipient }: RecipientItemProps) => { name="email" render={({ field }) => ( - Email + + Email + @@ -122,7 +130,7 @@ export const RecipientItem = ({ recipient }: RecipientItemProps) => {
@@ -131,7 +139,9 @@ export const RecipientItem = ({ recipient }: RecipientItemProps) => {
-

Fields

+

+ Fields +

{ cell: ({ row }) =>
{row.original.id}
, }, { - header: 'Type', + header: _(msg`Type`), accessorKey: 'type', cell: ({ row }) =>
{row.original.type}
, }, { - header: 'Inserted', + header: _(msg`Inserted`), accessorKey: 'inserted', cell: ({ row }) =>
{row.original.inserted ? 'True' : 'False'}
, }, { - header: 'Value', + header: _(msg`Value`), accessorKey: 'customText', cell: ({ row }) =>
{row.original.customText}
, }, { - header: 'Signature', + header: _(msg`Signature`), accessorKey: 'signature', cell: ({ row }) => (
diff --git a/apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx b/apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx index 63ad88a3f..337796959 100644 --- a/apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx +++ b/apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx @@ -4,6 +4,9 @@ import { useState } from 'react'; import { useRouter } from 'next/navigation'; +import { Trans, msg } from '@lingui/macro'; +import { useLingui } from '@lingui/react'; + import type { Document } from '@documenso/prisma/client'; import { TRPCClientError } from '@documenso/trpc/client'; import { trpc } from '@documenso/trpc/react'; @@ -26,7 +29,9 @@ export type SuperDeleteDocumentDialogProps = { }; export const SuperDeleteDocumentDialog = ({ document }: SuperDeleteDocumentDialogProps) => { + const { _ } = useLingui(); const { toast } = useToast(); + const router = useRouter(); const [reason, setReason] = useState(''); @@ -43,7 +48,7 @@ export const SuperDeleteDocumentDialog = ({ document }: SuperDeleteDocumentDialo await deleteDocument({ id: document.id, reason }); toast({ - title: 'Document deleted', + title: _(msg`Document deleted`), description: 'The Document has been deleted successfully.', duration: 5000, }); @@ -52,13 +57,13 @@ export const SuperDeleteDocumentDialog = ({ document }: SuperDeleteDocumentDialo } catch (err) { if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') { toast({ - title: 'An error occurred', + title: _(msg`An error occurred`), description: err.message, variant: 'destructive', }); } else { toast({ - title: 'An unknown error occurred', + title: _(msg`An unknown error occurred`), variant: 'destructive', description: err.message ?? @@ -76,31 +81,41 @@ export const SuperDeleteDocumentDialog = ({ document }: SuperDeleteDocumentDialo variant="neutral" >
- Delete Document + + Delete Document + - Delete the document. This action is irreversible so proceed with caution. + + Delete the document. This action is irreversible so proceed with caution. +
- + - Delete Document + + Delete Document + - This action is not reversible. Please be certain. + This action is not reversible. Please be certain.
- To confirm, please enter the reason + + To confirm, please enter the reason + - {isDeletingDocument ? 'Deleting document...' : 'Delete Document'} + Delete document diff --git a/apps/web/src/app/(dashboard)/admin/documents/document-results.tsx b/apps/web/src/app/(dashboard)/admin/documents/document-results.tsx index b7e235981..3226ed2c7 100644 --- a/apps/web/src/app/(dashboard)/admin/documents/document-results.tsx +++ b/apps/web/src/app/(dashboard)/admin/documents/document-results.tsx @@ -5,6 +5,8 @@ import { useState } from 'react'; import Link from 'next/link'; import { useSearchParams } from 'next/navigation'; +import { msg } from '@lingui/macro'; +import { useLingui } from '@lingui/react'; import { Loader } from 'lucide-react'; import { useDebouncedValue } from '@documenso/lib/client-only/hooks/use-debounced-value'; @@ -23,6 +25,8 @@ import { LocaleDate } from '~/components/formatter/locale-date'; // export type AdminDocumentResultsProps = {}; export const AdminDocumentResults = () => { + const { _ } = useLingui(); + const searchParams = useSearchParams(); const updateSearchParams = useUpdateSearchParams(); @@ -56,7 +60,7 @@ export const AdminDocumentResults = () => {
setTerm(e.target.value)} /> @@ -65,12 +69,12 @@ export const AdminDocumentResults = () => { , }, { - header: 'Title', + header: _(msg`Title`), accessorKey: 'title', cell: ({ row }) => { return ( @@ -84,12 +88,12 @@ export const AdminDocumentResults = () => { }, }, { - header: 'Status', + header: _(msg`Status`), accessorKey: 'status', cell: ({ row }) => , }, { - header: 'Owner', + header: _(msg`Owner`), accessorKey: 'owner', cell: ({ row }) => { const avatarFallbackText = row.original.User.name diff --git a/apps/web/src/app/(dashboard)/admin/documents/page.tsx b/apps/web/src/app/(dashboard)/admin/documents/page.tsx index 96e4dcef8..7f21bf5fa 100644 --- a/apps/web/src/app/(dashboard)/admin/documents/page.tsx +++ b/apps/web/src/app/(dashboard)/admin/documents/page.tsx @@ -1,9 +1,17 @@ +import { Trans } from '@lingui/macro'; + +import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server'; + import { AdminDocumentResults } from './document-results'; export default function AdminDocumentsPage() { + setupI18nSSR(); + return (
-

Manage documents

+

+ Manage documents +

diff --git a/apps/web/src/app/(dashboard)/admin/layout.tsx b/apps/web/src/app/(dashboard)/admin/layout.tsx index 12330679d..c489c34a1 100644 --- a/apps/web/src/app/(dashboard)/admin/layout.tsx +++ b/apps/web/src/app/(dashboard)/admin/layout.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { redirect } from 'next/navigation'; +import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server'; import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { isAdmin } from '@documenso/lib/next-auth/guards/is-admin'; @@ -12,6 +13,8 @@ export type AdminSectionLayoutProps = { }; export default async function AdminSectionLayout({ children }: AdminSectionLayoutProps) { + setupI18nSSR(); + const { user } = await getRequiredServerComponentSession(); if (!isAdmin(user)) { diff --git a/apps/web/src/app/(dashboard)/admin/nav.tsx b/apps/web/src/app/(dashboard)/admin/nav.tsx index 080cb9741..cf0bb81f2 100644 --- a/apps/web/src/app/(dashboard)/admin/nav.tsx +++ b/apps/web/src/app/(dashboard)/admin/nav.tsx @@ -5,6 +5,7 @@ import type { HTMLAttributes } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; +import { Trans } from '@lingui/macro'; import { BarChart3, FileStack, Settings, Users, Wallet2 } from 'lucide-react'; import { cn } from '@documenso/ui/lib/utils'; @@ -33,7 +34,7 @@ export const AdminNav = ({ className, ...props }: AdminNavProps) => { > - Stats + Stats @@ -47,7 +48,7 @@ export const AdminNav = ({ className, ...props }: AdminNavProps) => { > - Users + Users @@ -61,7 +62,7 @@ export const AdminNav = ({ className, ...props }: AdminNavProps) => { > - Documents + Documents @@ -75,7 +76,7 @@ export const AdminNav = ({ className, ...props }: AdminNavProps) => { > - Subscriptions + Subscriptions @@ -89,7 +90,7 @@ export const AdminNav = ({ className, ...props }: AdminNavProps) => { > - Site Settings + Site Settings
diff --git a/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx b/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx index 351e146ff..d68eed63b 100644 --- a/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx +++ b/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx @@ -3,6 +3,8 @@ import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, msg } from '@lingui/macro'; +import { useLingui } from '@lingui/react'; import { useForm } from 'react-hook-form'; import type { z } from 'zod'; @@ -37,8 +39,10 @@ export type BannerFormProps = { }; export function BannerForm({ banner }: BannerFormProps) { - const router = useRouter(); const { toast } = useToast(); + const { _ } = useLingui(); + + const router = useRouter(); const form = useForm({ resolver: zodResolver(ZBannerFormSchema), @@ -67,8 +71,8 @@ export function BannerForm({ banner }: BannerFormProps) { }); toast({ - title: 'Banner Updated', - description: 'Your banner has been updated successfully.', + title: _(msg`Banner Updated`), + description: _(msg`Your banner has been updated successfully.`), duration: 5000, }); @@ -76,16 +80,17 @@ export function BannerForm({ banner }: BannerFormProps) { } catch (err) { if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') { toast({ - title: 'An error occurred', + title: _(msg`An error occurred`), description: err.message, variant: 'destructive', }); } else { toast({ - title: 'An unknown error occurred', + title: _(msg`An unknown error occurred`), variant: 'destructive', - description: - 'We encountered an unknown error while attempting to update the banner. Please try again later.', + description: _( + msg`We encountered an unknown error while attempting to update the banner. Please try again later.`, + ), }); } } @@ -93,10 +98,14 @@ export function BannerForm({ banner }: BannerFormProps) { return (
-

Site Banner

+

+ Site Banner +

- The site banner is a message that is shown at the top of the site. It can be used to display - important information to your users. + + The site banner is a message that is shown at the top of the site. It can be used to + display important information to your users. +

@@ -110,7 +119,9 @@ export function BannerForm({ banner }: BannerFormProps) { name="enabled" render={({ field }) => ( - Enabled + + Enabled +
@@ -131,7 +142,9 @@ export function BannerForm({ banner }: BannerFormProps) { name="data.bgColor" render={({ field }) => ( - Background Color + + Background Color +
@@ -149,7 +162,9 @@ export function BannerForm({ banner }: BannerFormProps) { name="data.textColor" render={({ field }) => ( - Text Color + + Text Color +
@@ -170,14 +185,16 @@ export function BannerForm({ banner }: BannerFormProps) { name="data.content" render={({ field }) => ( - Content + + Content +