feat: add page title translations (#2629)

This commit is contained in:
David Nguyen
2026-03-19 15:44:53 +11:00
committed by GitHub
parent 4f8132be61
commit e87aa29823
53 changed files with 761 additions and 121 deletions
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import {
AlertTriangleIcon,
@@ -19,9 +20,14 @@ import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
import { AdminLicenseStatusBanner } from '~/components/general/admin-license-status-banner';
import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/_layout';
export function meta() {
return appMetaTags(msg`Admin`);
}
export async function loader({ request }: Route.LoaderArgs) {
const { user } = await getSession(request);
@@ -1,5 +1,6 @@
import { useMemo } from 'react';
import { msg } from '@lingui/core/macro';
import { Plural, Trans, useLingui } from '@lingui/react/macro';
import { Building2Icon, InboxIcon, SettingsIcon, UsersIcon } from 'lucide-react';
import { DateTime } from 'luxon';
@@ -25,7 +26,7 @@ export function loader() {
}
export function meta() {
return appMetaTags('Dashboard');
return appMetaTags(msg`Dashboard`);
}
export default function DashboardPage() {
@@ -54,7 +55,7 @@ export default function DashboardPage() {
<h1 className="text-3xl font-bold">
<Trans>Dashboard</Trans>
</h1>
<p className="text-muted-foreground mt-1">
<p className="mt-1 text-muted-foreground">
<Trans>Welcome back! Here's an overview of your account.</Trans>
</p>
@@ -69,7 +70,7 @@ export default function DashboardPage() {
<p className="font-semibold">
<Trans>No organisations found</Trans>
</p>
<p className="text-muted-foreground text-sm">
<p className="text-sm text-muted-foreground">
<Trans>Create an organisation to get started.</Trans>
</p>
</div>
@@ -87,7 +88,7 @@ export default function DashboardPage() {
<div className="mb-8">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<Building2Icon className="text-muted-foreground h-5 w-5" />
<Building2Icon className="h-5 w-5 text-muted-foreground" />
<h2 className="text-xl font-semibold">
<Trans>Organisations</Trans>
</h2>
@@ -104,7 +105,7 @@ export default function DashboardPage() {
{organisations.map((org) => (
<div key={org.id} className="group relative">
<Link to={`/o/${org.url}`}>
<Card className="hover:bg-muted/50 h-full border pr-6 transition-all">
<Card className="h-full border pr-6 transition-all hover:bg-muted/50">
<CardContent className="p-4">
<div className="flex items-center gap-3">
<Avatar className="h-10 w-10 border border-solid">
@@ -118,7 +119,7 @@ export default function DashboardPage() {
<div className="flex-1">
<h3 className="font-medium">{org.name}</h3>
<div className="text-muted-foreground mt-1 flex items-center gap-3 text-xs">
<div className="mt-1 flex items-center gap-3 text-xs text-muted-foreground">
<div className="flex items-center gap-1">
<UsersIcon className="h-3 w-3" />
<span>
@@ -148,7 +149,7 @@ export default function DashboardPage() {
'MANAGE_ORGANISATION',
org.currentOrganisationRole,
) && (
<div className="text-muted-foreground absolute right-4 top-4 opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<div className="absolute right-4 top-4 text-muted-foreground opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<Link to={`/o/${org.url}/settings`}>
<SettingsIcon className="h-4 w-4" />
</Link>
@@ -165,7 +166,7 @@ export default function DashboardPage() {
<div className="mb-8">
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<UsersIcon className="text-muted-foreground h-5 w-5" />
<UsersIcon className="h-5 w-5 text-muted-foreground" />
<h2 className="text-xl font-semibold">
<Trans>Teams</Trans>
</h2>
@@ -183,7 +184,7 @@ export default function DashboardPage() {
{teams.map((team) => (
<div key={team.id} className="group relative">
<Link to={`/t/${team.url}`}>
<Card className="hover:bg-muted/50 w-[350px] shrink-0 border transition-all">
<Card className="w-[350px] shrink-0 border transition-all hover:bg-muted/50">
<CardContent className="p-4">
<div className="flex items-center gap-3">
<Avatar className="h-10 w-10 border border-solid">
@@ -197,7 +198,7 @@ export default function DashboardPage() {
<div className="flex-1">
<h3 className="font-medium">{team.name}</h3>
<div className="text-muted-foreground mt-1 flex items-center gap-3 text-xs">
<div className="mt-1 flex items-center gap-3 text-xs text-muted-foreground">
<div className="flex items-center gap-1">
<UsersIcon className="h-3 w-3" />
{team.organisation.ownerUserId === user.id
@@ -211,7 +212,7 @@ export default function DashboardPage() {
</div>
</div>
</div>
<div className="text-muted-foreground mt-3 text-xs">
<div className="mt-3 text-xs text-muted-foreground">
<Trans>
Joined{' '}
{DateTime.fromJSDate(team.createdAt).toRelative({ style: 'short' })}
@@ -222,7 +223,7 @@ export default function DashboardPage() {
</Link>
{canExecuteTeamAction('MANAGE_TEAM', team.currentTeamRole) && (
<div className="text-muted-foreground absolute right-4 top-4 opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<div className="absolute right-4 top-4 text-muted-foreground opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<Link to={`/t/${team.url}/settings`}>
<SettingsIcon className="h-4 w-4" />
</Link>
@@ -240,7 +241,7 @@ export default function DashboardPage() {
<div>
<div className="mb-4 flex items-center justify-between">
<div className="flex items-center gap-2">
<InboxIcon className="text-muted-foreground h-5 w-5" />
<InboxIcon className="h-5 w-5 text-muted-foreground" />
<h2 className="text-xl font-semibold">
<Trans>Personal Inbox</Trans>
</h2>
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { InboxIcon } from 'lucide-react';
@@ -6,7 +7,7 @@ import { InboxTable } from '~/components/tables/inbox-table';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Personal Inbox');
return appMetaTags(msg`Personal Inbox`);
}
export default function InboxPage() {
@@ -14,11 +15,11 @@ export default function InboxPage() {
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
<div className="mb-8">
<h1 className="flex flex-row items-center gap-2 text-3xl font-bold">
<InboxIcon className="text-muted-foreground h-8 w-8" />
<InboxIcon className="h-8 w-8 text-muted-foreground" />
<Trans>Personal Inbox</Trans>
</h1>
<p className="text-muted-foreground mt-1">
<p className="mt-1 text-muted-foreground">
<Trans>Any documents that you have been invited to will appear here</Trans>
</p>
@@ -22,7 +22,7 @@ import { GenericErrorLayout } from '~/components/general/generic-error-layout';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Organisation Settings');
return appMetaTags(msg`Organisation Settings`);
}
export default function SettingsLayout() {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { SubscriptionStatus } from '@prisma/client';
@@ -15,7 +16,7 @@ import { OrganisationBillingInvoicesTable } from '~/components/tables/organisati
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Billing');
return appMetaTags(msg`Billing`);
}
export default function TeamsSettingBillingPage() {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import { Loader } from 'lucide-react';
import { Link } from 'react-router';
@@ -21,7 +22,7 @@ import { useOptionalCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Branding Preferences');
return appMetaTags(msg`Branding Preferences`);
}
export default function OrganisationSettingsBrandingPage() {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { Loader } from 'lucide-react';
import { useLoaderData } from 'react-router';
@@ -18,7 +19,7 @@ import { SettingsHeader } from '~/components/general/settings-header';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Document Preferences');
return appMetaTags(msg`Document Preferences`);
}
export const loader = () => {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import { Link } from 'react-router';
@@ -14,7 +15,7 @@ import { OrganisationEmailDomainsDataTable } from '~/components/tables/organisat
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Email Domains');
return appMetaTags(msg`Email Domains`);
}
export default function OrganisationSettingsEmailDomains() {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
@@ -13,7 +14,7 @@ import { SettingsHeader } from '~/components/general/settings-header';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Email Preferences');
return appMetaTags(msg`Email Preferences`);
}
export default function OrganisationSettingsGeneral() {
@@ -13,7 +13,7 @@ import { SettingsHeader } from '~/components/general/settings-header';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Settings');
return appMetaTags(msg`Settings`);
}
export default function OrganisationSettingsGeneral() {
@@ -69,7 +69,7 @@ const ZProviderFormSchema = ZUpdateOrganisationAuthenticationPortalRequestSchema
type TProviderFormSchema = z.infer<typeof ZProviderFormSchema>;
export function meta() {
return appMetaTags('Organisation SSO Portal');
return appMetaTags(msg`Organisation SSO Portal`);
}
export default function OrganisationSettingSSOLoginPage() {
@@ -205,7 +205,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
</div>
</div>
<p className="text-muted-foreground text-xs">
<p className="text-xs text-muted-foreground">
<Trans>This is the URL which users will use to sign in to your organisation.</Trans>
</p>
</div>
@@ -229,7 +229,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
</div>
</div>
<p className="text-muted-foreground text-xs">
<p className="text-xs text-muted-foreground">
<Trans>Add this URL to your provider's allowed redirect URIs</Trans>
</p>
</div>
@@ -241,7 +241,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
<Input className="pr-12" disabled value={`openid profile email`} />
<p className="text-muted-foreground text-xs">
<p className="text-xs text-muted-foreground">
<Trans>This is the required scopes you must set in your provider's settings</Trans>
</p>
</div>
@@ -262,7 +262,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
</FormControl>
{!form.formState.errors.wellKnownUrl && (
<p className="text-muted-foreground text-xs">
<p className="text-xs text-muted-foreground">
<Trans>The OpenID discovery endpoint URL for your provider</Trans>
</p>
)}
@@ -356,7 +356,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
</FormControl>
{!form.formState.errors.allowedDomains && (
<p className="text-muted-foreground text-xs">
<p className="text-xs text-muted-foreground">
<Trans>
Space-separated list of domains. Leave empty to allow all domains.
</Trans>
@@ -399,7 +399,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
<FormLabel>
<Trans>Enable SSO portal</Trans>
</FormLabel>
<p className="text-muted-foreground text-sm">
<p className="text-sm text-muted-foreground">
<Trans>Whether to enable the SSO portal for your organisation</Trans>
</p>
</div>
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { BookIcon, HelpCircleIcon, Link2Icon } from 'lucide-react';
import { Link, useSearchParams } from 'react-router';
@@ -13,7 +14,7 @@ import { SupportTicketForm } from '~/components/forms/support-ticket-form';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Support');
return appMetaTags(msg`Support`);
}
export default function SupportPage() {
@@ -39,18 +40,18 @@ export default function SupportPage() {
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
<div className="mb-8">
<h1 className="flex flex-row items-center gap-2 text-3xl font-bold">
<HelpCircleIcon className="text-muted-foreground h-8 w-8" />
<HelpCircleIcon className="h-8 w-8 text-muted-foreground" />
<Trans>Support</Trans>
</h1>
<p className="text-muted-foreground mt-2">
<p className="mt-2 text-muted-foreground">
<Trans>Your current plan includes the following support channels:</Trans>
</p>
<div className="mt-6 flex flex-col gap-4">
<div className="rounded-lg border p-4">
<h2 className="flex items-center gap-2 text-lg font-bold">
<BookIcon className="text-muted-foreground h-5 w-5" />
<BookIcon className="h-5 w-5 text-muted-foreground" />
<Link
to="https://docs.documenso.com"
target="_blank"
@@ -60,13 +61,13 @@ export default function SupportPage() {
<Trans>Documentation</Trans>
</Link>
</h2>
<p className="text-muted-foreground mt-1">
<p className="mt-1 text-muted-foreground">
<Trans>Read our documentation to get started with Documenso.</Trans>
</p>
</div>
<div className="rounded-lg border p-4">
<h2 className="flex items-center gap-2 text-lg font-bold">
<Link2Icon className="text-muted-foreground h-5 w-5" />
<Link2Icon className="h-5 w-5 text-muted-foreground" />
<Link
to="https://documen.so/discord"
target="_blank"
@@ -76,7 +77,7 @@ export default function SupportPage() {
<Trans>Discord</Trans>
</Link>
</h2>
<p className="text-muted-foreground mt-1">
<p className="mt-1 text-muted-foreground">
<Trans>
Join our community on{' '}
<Link
@@ -95,10 +96,10 @@ export default function SupportPage() {
<>
<div className="rounded-lg border p-4">
<h2 className="flex items-center gap-2 text-lg font-bold">
<Link2Icon className="text-muted-foreground h-5 w-5" />
<Link2Icon className="h-5 w-5 text-muted-foreground" />
<Trans>Contact us</Trans>
</h2>
<p className="text-muted-foreground mt-1">
<p className="mt-1 text-muted-foreground">
<Trans>We'll get back to you as soon as possible via email.</Trans>
</p>
<div className="mt-4">
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Outlet } from 'react-router';
@@ -6,7 +7,7 @@ import { SettingsMobileNav } from '~/components/general/settings-nav-mobile';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Settings');
return appMetaTags(msg`Settings`);
}
export default function SettingsLayout() {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { SettingsHeader } from '~/components/general/settings-header';
@@ -5,7 +6,7 @@ import { UserBillingOrganisationsTable } from '~/components/tables/user-billing-
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Billing');
return appMetaTags(msg`Billing`);
}
export default function SettingsBilling() {
@@ -15,7 +15,7 @@ import { TeamEmailUsage } from '~/components/general/teams/team-email-usage';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Profile');
return appMetaTags(msg`Profile`);
}
export default function SettingsProfile() {
@@ -19,7 +19,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/security._index';
export function meta() {
return appMetaTags('Security');
return appMetaTags(msg`Security`);
}
export async function loader({ request }: Route.LoaderArgs) {
@@ -71,7 +71,7 @@ export default function SettingsSecurity({ loaderData }: Route.ComponentProps) {
<>
<PasswordForm user={user} />
<hr className="border-border/50 mt-6" />
<hr className="mt-6 border-border/50" />
</>
)}
@@ -6,7 +6,7 @@ import { SettingsSecurityActivityTable } from '~/components/tables/settings-secu
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Security activity');
return appMetaTags(msg`Security activity`);
}
export default function SettingsSecurityActivity() {
@@ -1,5 +1,6 @@
import { useMemo, useState } from 'react';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { Trans } from '@lingui/react/macro';
import { useQuery } from '@tanstack/react-query';
@@ -26,7 +27,7 @@ import { SettingsHeader } from '~/components/general/settings-header';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Linked Accounts');
return appMetaTags(msg`Linked Accounts`);
}
export default function SettingsSecurityLinkedAccounts() {
@@ -7,7 +7,7 @@ import { SettingsSecurityPasskeyTable } from '~/components/tables/settings-secur
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Manage passkeys');
return appMetaTags(msg`Manage passkeys`);
}
export default function SettingsPasskeys() {
@@ -1,5 +1,6 @@
import { useMemo, useState } from 'react';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { Trans } from '@lingui/react/macro';
import { useQuery } from '@tanstack/react-query';
@@ -21,7 +22,7 @@ import { SettingsHeader } from '~/components/general/settings-header';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Active Sessions');
return appMetaTags(msg`Active Sessions`);
}
const parser = new UAParser();
@@ -1,5 +1,6 @@
import { useEffect, useMemo, useState } from 'react';
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { EnvelopeType } from '@prisma/client';
import { FolderType, OrganisationType } from '@prisma/client';
@@ -38,7 +39,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Documents');
return appMetaTags(msg`Documents`);
}
const ZSearchParamsSchema = ZFindDocumentsInternalRequestSchema.pick({
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
import { Link, useSearchParams } from 'react-router';
@@ -19,7 +20,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Documents');
return appMetaTags(msg`Documents`);
}
export default function DocumentsFoldersPage() {
@@ -24,7 +24,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/settings._layout';
export function meta() {
return appMetaTags('Team Settings');
return appMetaTags(msg`Team Settings`);
}
export async function loader({ request, params }: Route.LoaderArgs) {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { Loader } from 'lucide-react';
@@ -14,7 +15,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Branding Preferences');
return appMetaTags(msg`Branding Preferences`);
}
export default function TeamsSettingsPage() {
@@ -69,7 +70,7 @@ export default function TeamsSettingsPage() {
if (isLoadingTeam || !teamWithSettings) {
return (
<div className="flex items-center justify-center rounded-lg py-32">
<Loader className="text-muted-foreground h-6 w-6 animate-spin" />
<Loader className="h-6 w-6 animate-spin text-muted-foreground" />
</div>
);
}
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { Loader } from 'lucide-react';
import { useLoaderData } from 'react-router';
@@ -16,7 +17,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Document Preferences');
return appMetaTags(msg`Document Preferences`);
}
export const loader = () => {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { trpc } from '@documenso/trpc/react';
@@ -13,7 +14,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Settings');
return appMetaTags(msg`Settings`);
}
export default function TeamEmailSettingsGeneral() {
@@ -1,5 +1,6 @@
import { useEffect, useMemo, useState } from 'react';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react/macro';
import { Trans } from '@lingui/react/macro';
import { type TemplateDirectLink, TemplateType } from '@prisma/client';
@@ -31,7 +32,7 @@ type DirectTemplate = FindTemplateRow & {
};
export function meta() {
return appMetaTags('Public Profile');
return appMetaTags(msg`Public Profile`);
}
// Todo: This can be optimized.
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { TeamMemberRole } from '@prisma/client';
@@ -15,7 +16,7 @@ import { useOptionalCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('API Tokens');
return appMetaTags(msg`API Tokens`);
}
export default function ApiTokensPage() {
@@ -70,7 +71,7 @@ export default function ApiTokensPage() {
{tokens && tokens.length === 0 && (
<div className="mb-4">
<p className="text-muted-foreground mt-2 text-sm italic">
<p className="mt-2 text-sm italic text-muted-foreground">
<Trans>Your tokens will be shown here once you create them.</Trans>
</p>
</div>
@@ -79,24 +80,24 @@ export default function ApiTokensPage() {
{tokens && tokens.length > 0 && (
<div className="mt-4 flex max-w-xl flex-col gap-y-4">
{tokens.map((token) => (
<div key={token.id} className="border-border rounded-lg border p-4">
<div key={token.id} className="rounded-lg border border-border p-4">
<div className="flex items-center justify-between gap-x-4">
<div>
<h5 className="text-base">{token.name}</h5>
<p className="text-muted-foreground mt-2 text-xs">
<p className="mt-2 text-xs text-muted-foreground">
<Trans>
Created on {i18n.date(token.createdAt, DateTime.DATETIME_FULL)}
</Trans>
</p>
{token.expires ? (
<p className="text-muted-foreground mt-1 text-xs">
<p className="mt-1 text-xs text-muted-foreground">
<Trans>
Expires on {i18n.date(token.expires, DateTime.DATETIME_FULL)}
</Trans>
</p>
) : (
<p className="text-muted-foreground mt-1 text-xs">
<p className="mt-1 text-xs text-muted-foreground">
<Trans>Token doesn't have an expiration date</Trans>
</p>
)}
@@ -55,7 +55,7 @@ const WebhookSearchParamsSchema = ZUrlSearchParamsSchema.extend({
});
export function meta() {
return appMetaTags('Webhooks');
return appMetaTags(msg`Webhooks`);
}
export default function WebhookPage({ params }: Route.ComponentProps) {
@@ -151,10 +151,10 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
accessorKey: 'event',
cell: ({ row }) => (
<div>
<p className="text-foreground text-sm font-semibold">
<p className="text-sm font-semibold text-foreground">
{toFriendlyWebhookEventName(row.original.event)}
</p>
<p className="text-muted-foreground text-xs">{row.original.id}</p>
<p className="text-xs text-muted-foreground">{row.original.id}</p>
</div>
),
},
@@ -276,17 +276,17 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
<Tabs value={parsedSearchParams.status || ''} className="flex-shrink-0">
<TabsList>
<TabsTrigger className="hover:text-foreground min-w-[60px]" value="" asChild>
<TabsTrigger className="min-w-[60px] hover:text-foreground" value="" asChild>
<Link to={getTabHref('')}>
<Trans>All</Trans>
</Link>
</TabsTrigger>
<TabsTrigger className="hover:text-foreground min-w-[60px]" value="SUCCESS" asChild>
<TabsTrigger className="min-w-[60px] hover:text-foreground" value="SUCCESS" asChild>
<Link to={getTabHref(WebhookCallStatus.SUCCESS)}>
<Trans>Success</Trans>
</Link>
</TabsTrigger>
<TabsTrigger className="hover:text-foreground min-w-[60px]" value="FAILED" asChild>
<TabsTrigger className="min-w-[60px] hover:text-foreground" value="FAILED" asChild>
<Link to={getTabHref(WebhookCallStatus.FAILED)}>
<Trans>Failed</Trans>
</Link>
@@ -375,7 +375,7 @@ const WebhookEventCombobox = () => {
return (
<MultiSelectCombobox
emptySelectionPlaceholder={
<p className="text-muted-foreground font-normal">
<p className="font-normal text-muted-foreground">
<Trans>
<span className="text-muted-foreground/70">Events:</span> All
</Trans>
@@ -4,25 +4,13 @@ import { msg } from '@lingui/core/macro';
import { Plural, useLingui } from '@lingui/react/macro';
import { Trans } from '@lingui/react/macro';
import type { Webhook } from '@prisma/client';
import {
CheckCircle2Icon,
EditIcon,
Loader,
MoreHorizontalIcon,
ScrollTextIcon,
Trash2Icon,
XCircleIcon,
} from 'lucide-react';
import { DateTime } from 'luxon';
import { EditIcon, Loader, MoreHorizontalIcon, ScrollTextIcon, Trash2Icon } from 'lucide-react';
import { Link } from 'react-router';
import { toFriendlyWebhookEventName } from '@documenso/lib/universal/webhook/to-friendly-webhook-event-name';
import { trpc } from '@documenso/trpc/react';
import { cn } from '@documenso/ui/lib/utils';
import { Badge } from '@documenso/ui/primitives/badge';
import { Button } from '@documenso/ui/primitives/button';
import { DataTable, type DataTableColumnDef } from '@documenso/ui/primitives/data-table';
import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination';
import {
DropdownMenu,
DropdownMenuContent,
@@ -41,7 +29,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Webhooks');
return appMetaTags(msg`Webhooks`);
}
export default function WebhookPage() {
@@ -64,9 +52,9 @@ export default function WebhookPage() {
header: t`Webhook`,
cell: ({ row }) => (
<Link to={`/t/${team.url}/settings/webhooks/${row.original.id}`}>
<p className="text-muted-foreground text-xs">{row.original.id}</p>
<p className="text-xs text-muted-foreground">{row.original.id}</p>
<p
className="text-foreground max-w-sm truncate text-xs font-semibold"
className="max-w-sm truncate text-xs font-semibold text-foreground"
title={row.original.webhookUrl}
>
{row.original.webhookUrl}
@@ -130,7 +118,7 @@ export default function WebhookPage() {
enable: isError,
}}
emptyState={
<div className="text-muted-foreground/60 flex h-60 flex-col items-center justify-center gap-y-4">
<div className="flex h-60 flex-col items-center justify-center gap-y-4 text-muted-foreground/60">
<p>
<Trans>
You have no webhooks yet. Your webhooks will be shown here once you create them.
@@ -172,7 +160,7 @@ const WebhookTableActionDropdown = ({ webhook }: { webhook: Webhook }) => {
return (
<DropdownMenu>
<DropdownMenuTrigger data-testid="webhook-table-action-btn">
<MoreHorizontalIcon className="text-muted-foreground h-5 w-5" />
<MoreHorizontalIcon className="h-5 w-5 text-muted-foreground" />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" forceMount>
@@ -1,5 +1,6 @@
import { useMemo, useState } from 'react';
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { EnvelopeType, OrganisationType } from '@prisma/client';
import { Bird } from 'lucide-react';
@@ -30,7 +31,7 @@ const TEMPLATE_VIEWS = ['team', 'organisation'] as const;
type TemplateView = (typeof TEMPLATE_VIEWS)[number];
export function meta() {
return appMetaTags('Templates');
return appMetaTags(msg`Templates`);
}
export default function TemplatesPage() {
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
import { Link, useSearchParams } from 'react-router';
@@ -19,7 +20,7 @@ import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Templates');
return appMetaTags(msg`Templates`);
}
export default function TemplatesFoldersPage() {
+4 -4
View File
@@ -19,7 +19,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/_layout';
export function meta() {
return appMetaTags('Profile');
return appMetaTags(msg`Profile`);
}
export default function PublicProfileLayout() {
@@ -44,14 +44,14 @@ export default function PublicProfileLayout() {
) : (
<header
className={cn(
'supports-backdrop-blur:bg-background/60 bg-background/95 sticky top-0 z-[60] flex h-16 w-full items-center border-b border-b-transparent backdrop-blur duration-200',
'supports-backdrop-blur:bg-background/60 sticky top-0 z-[60] flex h-16 w-full items-center border-b border-b-transparent bg-background/95 backdrop-blur duration-200',
scrollY > 5 && 'border-b-border',
)}
>
<div className="mx-auto flex w-full max-w-screen-xl items-center justify-between gap-x-4 px-4 md:px-8">
<Link
to="/"
className="focus-visible:ring-ring ring-offset-background rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 md:inline"
className="rounded-md ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 md:inline"
>
<BrandingLogo className="hidden h-6 w-auto sm:block" />
@@ -65,7 +65,7 @@ export default function PublicProfileLayout() {
</Link>
<div className="flex flex-row items-center justify-center">
<p className="text-muted-foreground mr-4">
<p className="mr-4 text-muted-foreground">
<span className="text-sm sm:hidden">
<Trans>Want your own public profile?</Trans>
</span>
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Link } from 'react-router';
@@ -6,7 +7,7 @@ import { Button } from '@documenso/ui/primitives/button';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Forgot password');
return appMetaTags(msg`Forgot password`);
}
export default function ForgotPasswordPage() {
@@ -17,7 +18,7 @@ export default function ForgotPasswordPage() {
<Trans>Email sent!</Trans>
</h1>
<p className="text-muted-foreground mb-4 mt-2 text-sm">
<p className="mb-4 mt-2 text-sm text-muted-foreground">
<Trans>
A password reset email has been sent, if you have an account you should see it in your
inbox shortly.
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Link } from 'react-router';
@@ -5,7 +6,7 @@ import { ForgotPasswordForm } from '~/components/forms/forgot-password';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Forgot Password');
return appMetaTags(msg`Forgot Password`);
}
export default function ForgotPasswordPage() {
@@ -16,7 +17,7 @@ export default function ForgotPasswordPage() {
<Trans>Forgot your password?</Trans>
</h1>
<p className="text-muted-foreground mt-2 text-sm">
<p className="mt-2 text-sm text-muted-foreground">
<Trans>
No worries, it happens! Enter your email and we'll email you a special link to reset
your password.
@@ -25,7 +26,7 @@ export default function ForgotPasswordPage() {
<ForgotPasswordForm className="mt-4" />
<p className="text-muted-foreground mt-6 text-center text-sm">
<p className="mt-6 text-center text-sm text-muted-foreground">
<Trans>
Remembered your password?{' '}
<Link to="/signin" className="text-primary duration-200 hover:opacity-70">
@@ -19,7 +19,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/o.$orgUrl.signin';
export function meta() {
return appMetaTags('Sign In');
return appMetaTags(msg`Sign In`);
}
export function ErrorBoundary() {
@@ -127,14 +127,14 @@ export default function OrganisationSignIn({ loaderData }: Route.ComponentProps)
<div className="w-screen max-w-lg px-4">
<div className="flex items-start">
<div className="mr-4 mt-1 hidden md:block">
<MailsIcon className="text-primary h-10 w-10" strokeWidth={2} />
<MailsIcon className="h-10 w-10 text-primary" strokeWidth={2} />
</div>
<div className="">
<h2 className="text-2xl font-bold md:text-4xl">
<Trans>Confirmation email sent</Trans>
</h2>
<p className="text-muted-foreground mt-4">
<p className="mt-4 text-muted-foreground">
<Trans>
To gain access to your account, please confirm your email address by clicking on the
confirmation link from your inbox.
@@ -156,12 +156,12 @@ export default function OrganisationSignIn({ loaderData }: Route.ComponentProps)
return (
<div className="w-screen max-w-lg px-4">
<div className="border-border dark:bg-background z-10 rounded-xl border bg-neutral-100 p-6">
<div className="z-10 rounded-xl border border-border bg-neutral-100 p-6 dark:bg-background">
<h1 className="text-2xl font-semibold">
<Trans>Welcome to {organisationName}</Trans>
</h1>
<p className="text-muted-foreground mt-2 text-sm">
<p className="mt-2 text-sm text-muted-foreground">
<Trans>Sign in to your account</Trans>
</p>
@@ -177,7 +177,7 @@ export default function OrganisationSignIn({ loaderData }: Route.ComponentProps)
/>
<label
className="text-muted-foreground ml-2 flex flex-row items-center text-sm"
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
htmlFor={`flag-3rd-party-service`}
>
<Trans>
@@ -191,7 +191,7 @@ export default function OrganisationSignIn({ loaderData }: Route.ComponentProps)
type="button"
size="lg"
variant="outline"
className="bg-background w-full"
className="w-full bg-background"
loading={isSubmitting}
disabled={!isConfirmationChecked}
onClick={onSignInWithOIDCClick}
@@ -200,14 +200,14 @@ export default function OrganisationSignIn({ loaderData }: Route.ComponentProps)
</Button>
<div className="relative mt-2 flex items-center justify-center gap-x-4 py-2 text-xs uppercase">
<div className="bg-border h-px flex-1" />
<span className="text-muted-foreground bg-transparent">
<div className="h-px flex-1 bg-border" />
<span className="bg-transparent text-muted-foreground">
<Trans>OR</Trans>
</span>
<div className="bg-border h-px flex-1" />
<div className="h-px flex-1 bg-border" />
</div>
<div className="text-muted-foreground mt-1 flex items-center justify-center text-xs">
<div className="mt-1 flex items-center justify-center text-xs text-muted-foreground">
<Link to="/signin">
<Trans>Return to Documenso sign in page here</Trans>
</Link>
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Link, redirect } from 'react-router';
@@ -9,7 +10,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/reset-password.$token';
export function meta() {
return appMetaTags('Reset Password');
return appMetaTags(msg`Reset Password`);
}
export async function loader({ params }: Route.LoaderArgs) {
@@ -36,13 +37,13 @@ export default function ResetPasswordPage({ loaderData }: Route.ComponentProps)
<Trans>Reset Password</Trans>
</h1>
<p className="text-muted-foreground mt-2 text-sm">
<p className="mt-2 text-sm text-muted-foreground">
<Trans>Please choose your new password</Trans>
</p>
<ResetPasswordForm token={token} className="mt-4" />
<p className="text-muted-foreground mt-6 text-center text-sm">
<p className="mt-6 text-center text-sm text-muted-foreground">
<Trans>
Don't have an account?{' '}
<Link to="/signup" className="text-primary duration-200 hover:opacity-70">
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Link } from 'react-router';
@@ -6,7 +7,7 @@ import { Button } from '@documenso/ui/primitives/button';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Reset Password');
return appMetaTags(msg`Reset Password`);
}
export default function ResetPasswordPage() {
@@ -17,7 +18,7 @@ export default function ResetPasswordPage() {
<Trans>Unable to reset password</Trans>
</h1>
<p className="text-muted-foreground mt-2 text-sm">
<p className="mt-2 text-sm text-muted-foreground">
<Trans>
The token you have used to reset your password is either expired or it never existed. If
you have still forgotten your password, please request a new reset link.
@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { Link, redirect, useSearchParams } from 'react-router';
@@ -22,7 +23,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/signin';
export function meta() {
return appMetaTags('Sign In');
return appMetaTags(msg`Sign In`);
}
export async function loader({ request }: Route.LoaderArgs) {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { redirect } from 'react-router';
import {
@@ -14,7 +15,7 @@ import { appMetaTags } from '~/utils/meta';
import type { Route } from './+types/signup';
export function meta() {
return appMetaTags('Sign Up');
return appMetaTags(msg`Sign Up`);
}
export function loader({ request }: Route.LoaderArgs) {
@@ -1,3 +1,4 @@
import { msg } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { XCircle } from 'lucide-react';
import { Link } from 'react-router';
@@ -7,7 +8,7 @@ import { Button } from '@documenso/ui/primitives/button';
import { appMetaTags } from '~/utils/meta';
export function meta() {
return appMetaTags('Verify Email');
return appMetaTags(msg`Verify Email`);
}
export default function EmailVerificationWithoutTokenPage() {
@@ -15,7 +16,7 @@ export default function EmailVerificationWithoutTokenPage() {
<div className="w-screen max-w-lg px-4">
<div className="flex w-full items-start">
<div className="mr-4 mt-1 hidden md:block">
<XCircle className="text-destructive h-10 w-10" strokeWidth={2} />
<XCircle className="h-10 w-10 text-destructive" strokeWidth={2} />
</div>
<div>
@@ -23,7 +24,7 @@ export default function EmailVerificationWithoutTokenPage() {
<Trans>Uh oh! Looks like you're missing a token</Trans>
</h2>
<p className="text-muted-foreground mt-4">
<p className="mt-4 text-muted-foreground">
<Trans>
It seems that there is no token provided, if you are trying to verify your email
please follow the link in your email.
+4 -2
View File
@@ -1,12 +1,14 @@
import { type MessageDescriptor, i18n } from '@lingui/core';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
export const appMetaTags = (title?: string) => {
export const appMetaTags = (title?: MessageDescriptor) => {
const description =
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.';
return [
{
title: title ? `${title} - Documenso` : 'Documenso',
title: title ? `${i18n._(title)} - Documenso` : 'Documenso',
},
{
name: 'description',