Compare commits

...

17 Commits

Author SHA1 Message Date
github-actions
d1528fd63b chore: extract translations 2024-09-11 07:27:20 +00:00
Catalin Pit
85012ae991 Merge branch 'main' into feat/save-data-on-blur 2024-09-11 10:26:39 +03:00
David Nguyen
357bdd374f feat: add language switcher (#1337)
## Description

Web changes:

- Enabled i18n for web
- Add option to change language in command menu
- Add option to change language in menu-switcher

Web and marketing changes:

- Stop setting 'en' preference into cookie if the user's language is not
supported
- Dropped middleware changes
- Rotated cookie from 'i18n' to 'language'

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Introduced a language switcher in the footer for improved language
selection.
	- Added dynamic language change functionality in the command menu.
- Implemented a dropdown menu item for quick access to the language
switcher.

- **Bug Fixes**
- Resolved issues related to language change notifications and state
management.

- **Translations**
- Added new translation entries for improved language support, including
"Search languages..." in English and German.
	- Updated existing translations to enhance clarity and accuracy.

- **Chores**
	- Simplified internationalization handling in middleware.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: github-actions <github-actions@documenso.com>
2024-09-11 13:22:43 +10:00
Catalin Pit
ff4c9616fc Merge branch 'main' into feat/save-data-on-blur 2024-09-05 10:26:22 +03:00
Catalin Pit
fd004f5f24 chore: merge main 2024-08-29 12:37:19 +03:00
github-actions
bb222cc0fc chore: extract translations 2024-08-22 05:16:14 +00:00
Catalin Pit
f627cbc7db Delete packages/lib/translations/de/common.po 2024-08-22 08:15:24 +03:00
Catalin Pit
67be4fdb45 Delete packages/lib/translations/de/web.po 2024-08-22 08:15:15 +03:00
Catalin Pit
c8b7d13b4f Delete packages/lib/translations/de/marketing.po 2024-08-22 08:15:05 +03:00
Catalin Pit
2b4699bb61 Delete packages/lib/translations/de/marketing.js 2024-08-22 08:14:52 +03:00
github-actions
39603fc150 chore: extract translations 2024-08-21 10:59:09 +00:00
Catalin Pit
7f2a8deda3 Merge branch 'main' into feat/save-data-on-blur 2024-08-21 13:58:17 +03:00
Catalin Pit
f24a33c182 fix: fix err msg 2024-08-21 13:57:43 +03:00
Catalin Pit
4a8f32a44f fix: remove unnecessary code 2024-08-21 12:56:28 +03:00
Catalin Pit
bbf2ed7154 feat: fix code 2024-08-21 12:15:22 +03:00
Catalin Pit
5ce7f4adcc feat: ux improvements 2024-08-21 08:50:24 +03:00
Catalin Pit
d74aca2aa6 feat: save subject and message on blur 2024-08-20 14:19:16 +03:00
23 changed files with 582 additions and 358 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import type { HTMLAttributes } from 'react';
import { type HTMLAttributes, useState } from 'react';
import Image from 'next/image';
import Link from 'next/link';
@@ -9,15 +9,15 @@ import { msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { FaXTwitter } from 'react-icons/fa6';
import { LiaDiscord } from 'react-icons/lia';
import { LuGithub } from 'react-icons/lu';
import { LuGithub, LuLanguages } from 'react-icons/lu';
import LogoImage from '@documenso/assets/logo.png';
import { cn } from '@documenso/ui/lib/utils';
import { ThemeSwitcher } from '@documenso/ui/primitives/theme-switcher';
import { I18nSwitcher } from '~/components/(marketing)/i18n-switcher';
import { SUPPORTED_LANGUAGES } from '@documenso/lib/constants/i18n';
// import { StatusWidgetContainer } from './status-widget-container';
import { LanguageSwitcherDialog } from '@documenso/ui/components/common/language-switcher-dialog';
import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
import { ThemeSwitcher } from '@documenso/ui/primitives/theme-switcher';
export type FooterProps = HTMLAttributes<HTMLDivElement>;
@@ -44,7 +44,9 @@ const FOOTER_LINKS = [
];
export const Footer = ({ className, ...props }: FooterProps) => {
const { _ } = useLingui();
const { _, i18n } = useLingui();
const [languageSwitcherOpen, setLanguageSwitcherOpen] = useState(false);
return (
<div className={cn('border-t py-12', className)} {...props}>
@@ -97,13 +99,22 @@ export const Footer = ({ className, ...props }: FooterProps) => {
</p>
<div className="flex flex-row-reverse items-center sm:flex-row">
<I18nSwitcher className="text-muted-foreground ml-2 rounded-full font-normal sm:mr-2" />
<Button
className="text-muted-foreground ml-2 rounded-full font-normal sm:mr-2"
variant="ghost"
onClick={() => setLanguageSwitcherOpen(true)}
>
<LuLanguages className="mr-1.5 h-4 w-4" />
{SUPPORTED_LANGUAGES[i18n.locale]?.full || i18n.locale}
</Button>
<div className="flex flex-wrap">
<ThemeSwitcher />
</div>
</div>
</div>
<LanguageSwitcherDialog open={languageSwitcherOpen} setOpen={setLanguageSwitcherOpen} />
</div>
);
};

View File

@@ -1,71 +0,0 @@
import { useState } from 'react';
import { msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { CheckIcon } from 'lucide-react';
import { LuLanguages } from 'react-icons/lu';
import { SUPPORTED_LANGUAGES } from '@documenso/lib/constants/i18n';
import { switchI18NLanguage } from '@documenso/lib/server-only/i18n/switch-i18n-language';
import { dynamicActivate } from '@documenso/lib/utils/i18n';
import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
import {
CommandDialog,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@documenso/ui/primitives/command';
type I18nSwitcherProps = {
className?: string;
};
export const I18nSwitcher = ({ className }: I18nSwitcherProps) => {
const { i18n, _ } = useLingui();
const [open, setOpen] = useState(false);
const [value, setValue] = useState(i18n.locale);
const setLanguage = async (lang: string) => {
setValue(lang);
setOpen(false);
await dynamicActivate(i18n, lang);
await switchI18NLanguage(lang);
};
return (
<>
<Button className={className} variant="ghost" onClick={() => setOpen(true)}>
<LuLanguages className="mr-1.5 h-4 w-4" />
{SUPPORTED_LANGUAGES[value]?.full || i18n.locale}
</Button>
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder={_(msg`Search languages...`)} />
<CommandList>
<CommandGroup>
{Object.values(SUPPORTED_LANGUAGES).map((language) => (
<CommandItem
key={language.short}
value={language.full}
onSelect={async () => setLanguage(language.short)}
>
<CheckIcon
className={cn(
'mr-2 h-4 w-4',
value === language.short ? 'opacity-100' : 'opacity-0',
)}
/>
{SUPPORTED_LANGUAGES[language.short].full}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</CommandDialog>
</>
);
};

View File

@@ -1,39 +0,0 @@
import { cookies } from 'next/headers';
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { extractLocaleData } from '@documenso/lib/utils/i18n';
export default function middleware(req: NextRequest) {
const { lang } = extractLocaleData({
headers: req.headers,
cookies: cookies(),
});
const response = NextResponse.next();
response.cookies.set('i18n', lang);
return response;
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - ingest (analytics)
* - site.webmanifest
*/
{
source: '/((?!api|_next/static|_next/image|ingest|favicon|site.webmanifest).*)',
missing: [
{ type: 'header', key: 'next-router-prefetch' },
{ type: 'header', key: 'purpose', value: 'prefetch' },
],
},
],
};

View File

@@ -7,10 +7,11 @@ import { useRouter } from 'next/navigation';
import type { MessageDescriptor } from '@lingui/core';
import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { Loader, Monitor, Moon, Sun } from 'lucide-react';
import { CheckIcon, Loader, Monitor, Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';
import { useHotkeys } from 'react-hotkeys-hook';
import { SUPPORTED_LANGUAGES } from '@documenso/lib/constants/i18n';
import {
DOCUMENTS_PAGE_SHORTCUT,
SETTINGS_PAGE_SHORTCUT,
@@ -20,7 +21,10 @@ import {
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
SKIP_QUERY_BATCH_META,
} from '@documenso/lib/constants/trpc';
import { switchI18NLanguage } from '@documenso/lib/server-only/i18n/switch-i18n-language';
import { dynamicActivate } from '@documenso/lib/utils/i18n';
import { trpc as trpcReact } from '@documenso/trpc/react';
import { cn } from '@documenso/ui/lib/utils';
import {
CommandDialog,
CommandEmpty,
@@ -31,6 +35,7 @@ import {
CommandShortcut,
} from '@documenso/ui/primitives/command';
import { THEMES_TYPE } from '@documenso/ui/primitives/constants';
import { useToast } from '@documenso/ui/primitives/use-toast';
const DOCUMENTS_PAGES = [
{
@@ -207,6 +212,9 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
<Commands push={push} pages={SETTINGS_PAGES} />
</CommandGroup>
<CommandGroup className="mx-2 p-0 pb-2" heading={_(msg`Preferences`)}>
<CommandItem className="-mx-2 -my-1 rounded-lg" onSelect={() => addPage('language')}>
Change language
</CommandItem>
<CommandItem className="-mx-2 -my-1 rounded-lg" onSelect={() => addPage('theme')}>
Change theme
</CommandItem>
@@ -218,7 +226,9 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
)}
</>
)}
{currentPage === 'theme' && <ThemeCommands setTheme={setTheme} />}
{currentPage === 'language' && <LanguageCommands />}
</CommandList>
</CommandDialog>
);
@@ -269,3 +279,46 @@ const ThemeCommands = ({ setTheme }: { setTheme: (_theme: string) => void }) =>
</CommandItem>
));
};
const LanguageCommands = () => {
const { i18n, _ } = useLingui();
const { toast } = useToast();
const [isLoading, setIsLoading] = useState(false);
const setLanguage = async (lang: string) => {
if (isLoading || lang === i18n.locale) {
return;
}
setIsLoading(true);
try {
await dynamicActivate(i18n, lang);
await switchI18NLanguage(lang);
} catch (err) {
toast({
title: _(msg`An unknown error occurred`),
variant: 'destructive',
description: _(msg`Unable to change the language at this time. Please try again later.`),
});
}
setIsLoading(false);
};
return Object.values(SUPPORTED_LANGUAGES).map((language) => (
<CommandItem
disabled={isLoading}
key={language.full}
onSelect={async () => setLanguage(language.short)}
className="-my-1 mx-2 rounded-lg first:mt-2 last:mb-2"
>
<CheckIcon
className={cn('mr-2 h-4 w-4', i18n.locale === language.short ? 'opacity-100' : 'opacity-0')}
/>
{language.full}
</CommandItem>
));
};

View File

@@ -1,5 +1,7 @@
'use client';
import { useState } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
@@ -17,6 +19,7 @@ import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
import { canExecuteTeamAction } from '@documenso/lib/utils/teams';
import type { User } from '@documenso/prisma/client';
import { trpc } from '@documenso/trpc/react';
import { LanguageSwitcherDialog } from '@documenso/ui/components/common/language-switcher-dialog';
import { cn } from '@documenso/ui/lib/utils';
import { AvatarWithText } from '@documenso/ui/primitives/avatar';
import { Button } from '@documenso/ui/primitives/button';
@@ -41,6 +44,8 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
const pathname = usePathname();
const [languageSwitcherOpen, setLanguageSwitcherOpen] = useState(false);
const isUserAdmin = isAdmin(user);
const { data: teamsQueryResult } = trpc.team.getTeams.useQuery(undefined, {
@@ -274,6 +279,13 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
</DropdownMenuItem>
)}
<DropdownMenuItem
className="text-muted-foreground px-4 py-2"
onClick={() => setLanguageSwitcherOpen(true)}
>
<Trans>Language</Trans>
</DropdownMenuItem>
<DropdownMenuItem
className="text-destructive/90 hover:!text-destructive px-4 py-2"
onSelect={async () =>
@@ -285,6 +297,8 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
<Trans>Sign Out</Trans>
</DropdownMenuItem>
</DropdownMenuContent>
<LanguageSwitcherDialog open={languageSwitcherOpen} setOpen={setLanguageSwitcherOpen} />
</DropdownMenu>
);
};

View File

@@ -5,7 +5,6 @@ import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
import { TEAM_URL_ROOT_REGEX } from '@documenso/lib/constants/teams';
import { extractLocaleData } from '@documenso/lib/utils/i18n';
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
async function middleware(req: NextRequest): Promise<NextResponse> {
@@ -96,12 +95,7 @@ async function middleware(req: NextRequest): Promise<NextResponse> {
export default async function middlewareWrapper(req: NextRequest) {
const response = await middleware(req);
const { lang } = extractLocaleData({
headers: req.headers,
cookies: cookies(),
});
response.cookies.set('i18n', lang);
// Can place anything that needs to be set on the response here.
return response;
}

View File

@@ -10,7 +10,7 @@ export const NEXT_PRIVATE_INTERNAL_WEBAPP_URL = process.env.NEXT_PRIVATE_INTERNA
export const IS_APP_MARKETING = process.env.NEXT_PUBLIC_PROJECT === 'marketing';
export const IS_APP_WEB = process.env.NEXT_PUBLIC_PROJECT === 'web';
export const IS_BILLING_ENABLED = () => env('NEXT_PUBLIC_FEATURE_BILLING_ENABLED') === 'true';
export const IS_APP_WEB_I18N_ENABLED = false;
export const IS_APP_WEB_I18N_ENABLED = true;
export const APP_FOLDER = () => (IS_APP_MARKETING ? 'marketing' : 'web');

View File

@@ -4,5 +4,5 @@ import { cookies } from 'next/headers';
// eslint-disable-next-line @typescript-eslint/require-await
export const switchI18NLanguage = async (lang: string) => {
cookies().set('i18n', lang);
cookies().set('language', lang);
};

View File

@@ -1,8 +1,8 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2024-07-24 13:01+1000\n"
"POT-Creation-Date: 2024-08-22 05:16+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: de\n"
@@ -367,7 +367,7 @@ msgstr "Max"
msgid "Member"
msgstr "Mitglied"
#: packages/ui/primitives/document-flow/add-subject.tsx:95
#: packages/ui/primitives/document-flow/add-subject.tsx:229
#: packages/ui/primitives/template-flow/add-template-settings.tsx:215
msgid "Message <0>(Optional)</0>"
msgstr "Nachricht <0>(Optional)</0>"
@@ -522,6 +522,10 @@ msgstr "Speichern"
msgid "Save Template"
msgstr "Vorlage speichern"
#: packages/ui/components/common/language-switcher-dialog.tsx:34
msgid "Search languages..."
msgstr "Sprachen suchen..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:105
msgid "Select"
msgstr "Auswählen"
@@ -538,7 +542,7 @@ msgstr "Wählen Sie mindestens"
msgid "Select default option"
msgstr "Standardoption auswählen"
#: packages/ui/primitives/document-flow/add-subject.tsx:124
#: packages/ui/primitives/document-flow/add-subject.tsx:275
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:34
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:64
msgid "Send"
@@ -600,7 +604,7 @@ msgstr "Etwas ist schief gelaufen."
msgid "Step <0>{step} of {maxStep}</0>"
msgstr "Schritt <0>{step} von {maxStep}</0>"
#: packages/ui/primitives/document-flow/add-subject.tsx:78
#: packages/ui/primitives/document-flow/add-subject.tsx:194
#: packages/ui/primitives/template-flow/add-template-settings.tsx:195
msgid "Subject <0>(Optional)</0>"
msgstr "Betreff <0>(Optional)</0>"
@@ -708,7 +712,7 @@ msgstr "Titel"
msgid "To proceed further, please set at least one value for the {0} field."
msgstr "Um fortzufahren, legen Sie bitte mindestens einen Wert für das Feld {0} fest."
#: packages/ui/primitives/document-flow/add-subject.tsx:124
#: packages/ui/primitives/document-flow/add-subject.tsx:275
msgid "Update"
msgstr "Aktualisieren"

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2024-07-24 13:01+1000\n"
"POT-Creation-Date: 2024-08-22 05:16+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: de\n"
@@ -20,19 +20,19 @@ msgstr ""
#: apps/marketing/src/app/(marketing)/blog/page.tsx:45
msgid "{0}"
msgstr "{0}"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:100
msgid "5 standard documents per month"
msgstr "5 Standarddokumente pro Monat"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:198
msgid "5 Users Included"
msgstr "5 Benutzer inbegriffen"
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:34
msgid "A 10x better signing experience."
msgstr "Eine 10x bessere Signaturerfahrung."
msgstr ""
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:51
msgid "Add document"
@@ -40,142 +40,138 @@ msgstr "Dokument hinzufügen"
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:201
msgid "Add More Users for {0}"
msgstr "Mehr Benutzer hinzufügen für {0}"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:165
msgid "All our metrics, finances, and learnings are public. We believe in transparency and want to share our journey with you. You can read more about why here: <0>Announcing Open Metrics</0>"
msgstr "Alle unsere Kennzahlen, Finanzen und Erkenntnisse sind öffentlich. Wir glauben an Transparenz und möchten unsere Reise mit Ihnen teilen. Mehr erfahren Sie hier: <0>Ankündigung Offene Kennzahlen</0>"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/funding-raised.tsx:58
#: apps/marketing/src/app/(marketing)/open/funding-raised.tsx:65
msgid "Amount Raised"
msgstr "Erhobener Betrag"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:145
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:189
msgid "API Access"
msgstr "API-Zugriff"
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:67
msgid "Beautiful."
msgstr "Schön."
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:69
msgid "Because signing should be celebrated. Thats why we care about the smallest detail in our product."
msgstr "Weil Unterschriften gefeiert werden sollten. Deshalb kümmern wir uns um jedes kleinste Detail in unserem Produkt."
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:35
#: apps/marketing/src/components/(marketing)/header.tsx:57
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:36
msgid "Blog"
msgstr "Blog"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:64
msgid "Build on top."
msgstr "Aufbauen oben drauf."
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:163
msgid "Can I use Documenso commercially?"
msgstr "Kann ich Documenso kommerziell nutzen?"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:42
msgid "Careers"
msgstr "Karrieren"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:36
msgid "Changelog"
msgstr "Änderungsprotokoll"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:85
msgid "Choose a template from the community app store. Or submit your own template for others to use."
msgstr "Wählen Sie eine Vorlage aus dem Community-App-Store. Oder reichen Sie Ihre eigene Vorlage ein, damit andere sie benutzen können."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:219
msgid "Community"
msgstr "Gemeinschaft"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx:55
msgid "Completed Documents"
msgstr "Fertige Dokumente"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx:33
msgid "Completed Documents per Month"
msgstr "Fertige Dokumente pro Monat"
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:65
msgid "Connections"
msgstr "Verbindungen"
msgstr ""
#: apps/marketing/src/components/(marketing)/enterprise.tsx:35
msgid "Contact Us"
msgstr "Kontaktiere uns"
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:67
msgid "Create connections and automations with Zapier and more to integrate with your favorite tools."
msgstr "Erstellen Sie Verbindungen und Automatisierungen mit Zapier und mehr, um sich mit Ihren Lieblingstools zu integrieren."
msgstr ""
#: apps/marketing/src/components/(marketing)/call-to-action.tsx:23
msgid "Create your account and start using state-of-the-art document signing. Open and beautiful signing is within your grasp."
msgstr "Erstellen Sie Ihr Konto und beginnen Sie mit der Nutzung modernster Dokumentensignaturen. Offene und schöne Signaturen sind zum Greifen nah."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/tooltip.tsx:35
msgid "Customers with an Active Subscriptions."
msgstr "Kunden mit einer aktiven Abonnements."
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:33
msgid "Customise and expand."
msgstr "Anpassen und erweitern."
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:38
msgid "Design"
msgstr "Design"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:44
msgid "Designed for every stage of your journey."
msgstr "Entwickelt für jede Phase Ihrer Reise."
msgstr ""
#: apps/marketing/src/components/(marketing)/carousel.tsx:40
msgid "Direct Link"
msgstr "Direktlink"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:181
msgid "Documenso is a community effort to create an open and vibrant ecosystem around a tool, everybody is free to use and adapt. By being truly open we want to create trusted infrastructure for the future of the internet."
msgstr "Documenso ist eine Gemeinschaftsanstrengung, um ein offenes und lebendiges Ökosystem um ein Werkzeug zu schaffen, das jeder frei nutzen und anpassen kann. Indem wir wirklich offen sind, wollen wir vertrauenswürdige Infrastruktur für die Zukunft des Internets schaffen."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:28
msgid "Documenso on X"
msgstr "Documenso auf X"
msgstr ""
#: apps/marketing/src/components/(marketing)/hero.tsx:104
msgid "Document signing,<0/>finally open source."
msgstr "Unterschriften,<0/>endlich Open Source."
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:33
#: apps/marketing/src/components/(marketing)/header.tsx:50
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:28
msgid "Documentation"
msgstr "Dokumentation"
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:110
msgid "Easily embed Documenso into your product. Simply copy and paste our react widget into your application."
msgstr "Betten Sie Documenso ganz einfach in Ihr Produkt ein. Kopieren und fügen Sie einfach unser React-Widget in Ihre Anwendung ein."
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:42
#~ msgid "Easy Sharing (Soon)."
#~ msgstr "Easy Sharing (Soon)."
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:46
msgid "Easy Sharing."
msgstr "Einfaches Teilen."
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:148
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:192
msgid "Email and Discord Support"
msgstr "E-Mail- und Discord-Support"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:43
msgid "Engagement"
msgstr "Beteiligung"
msgstr ""
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:64
msgid "Enter your details."
@@ -183,43 +179,43 @@ msgstr "Geben Sie Ihre Details ein."
#: apps/marketing/src/components/(marketing)/enterprise.tsx:16
msgid "Enterprise Compliance, License or Technical Needs?"
msgstr "Enterprise-Konformität, Lizenz- oder technische Bedürfnisse?"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:128
msgid "Everything you need for a great signing experience."
msgstr "Alles, was Sie für ein großartiges Signaturerlebnis benötigen."
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:45
msgid "Fast."
msgstr "Schnell."
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:36
msgid "Faster, smarter and more beautiful."
msgstr "Schneller, intelligenter und schöner."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:210
msgid "Finances"
msgstr "Finanzen"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:38
msgid "Follow us on X"
msgstr "Folgen Sie uns auf X"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:172
msgid "For companies looking to scale across multiple teams."
msgstr "Für Unternehmen, die über mehrere Teams skalieren möchten."
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:85
msgid "For small teams and individuals with basic needs."
msgstr "Für kleine Teams und Einzelpersonen mit grundlegenden Bedürfnissen."
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:80
msgid "Free"
msgstr "Kostenlos"
msgstr ""
#: apps/marketing/src/app/(marketing)/blog/page.tsx:26
msgid "From the blog"
msgstr "Aus dem Blog"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/data.ts:9
#: apps/marketing/src/app/(marketing)/open/data.ts:17
@@ -227,227 +223,222 @@ msgstr "Aus dem Blog"
#: apps/marketing/src/app/(marketing)/open/data.ts:41
#: apps/marketing/src/app/(marketing)/open/data.ts:49
msgid "Full-Time"
msgstr "Vollzeit"
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:87
msgid "Get paid (Soon)."
msgstr "Lassen Sie sich bezahlen (Bald)."
msgstr ""
#: apps/marketing/src/components/(marketing)/call-to-action.tsx:31
msgid "Get started"
msgstr "Loslegen"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:75
msgid "Get Started"
msgstr "Loslegen"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:47
msgid "Get started today."
msgstr "Fangen Sie heute an."
msgstr ""
#: apps/marketing/src/app/(marketing)/blog/page.tsx:30
msgid "Get the latest news from Documenso, including product updates, team announcements and more!"
msgstr "Erhalten Sie die neuesten Nachrichten von Documenso, einschließlich Produkt-Updates, Team-Ankündigungen und mehr!"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:233
msgid "GitHub: Total Merged PRs"
msgstr "GitHub: Gesamte PRs zusammengeführt"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:251
msgid "GitHub: Total Open Issues"
msgstr "GitHub: Gesamte offene Issues"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:225
msgid "GitHub: Total Stars"
msgstr "GitHub: Gesamtanzahl Sterne"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:23
msgid "Global Salary Bands"
msgstr "Globale Gehaltsbänder"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:261
msgid "Growth"
msgstr "Wachstum"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:134
msgid "How can I contribute?"
msgstr "Wie kann ich beitragen?"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:105
msgid "How do you handle my data?"
msgstr "Wie gehen Sie mit meinen Daten um?"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:118
msgid "Individual"
msgstr "Einzelperson"
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:89
msgid "Integrated payments with Stripe so you dont have to worry about getting paid."
msgstr "Integrierte Zahlungen mit Stripe, sodass Sie sich keine Sorgen ums Bezahlen machen müssen."
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:35
msgid "Integrates with all your favourite tools."
msgstr "Integriert sich mit all Ihren Lieblingstools."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:289
msgid "Is there more?"
msgstr "Gibt es mehr?"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:44
msgid "Its up to you. Either clone our repository or rely on our easy to use hosting solution."
msgstr "Es liegt an Ihnen. Entweder klonen Sie unser Repository oder nutzen unsere einfach zu bedienende Hosting-Lösung."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:49
msgid "Join Date"
msgstr "Eintrittsdatum"
msgstr ""
#: apps/marketing/src/components/(marketing)/call-to-action.tsx:19
msgid "Join the Open Signing Movement"
msgstr "Treten Sie der Open Signing-Bewegung bei"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:46
msgid "Location"
msgstr "Standort"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:66
msgid "Make it your own through advanced customization and adjustability."
msgstr "Machen Sie es zu Ihrem eigenen durch erweiterte Anpassung und Einstellbarkeit."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:199
msgid "Merged PR's"
msgstr "Zusammengeführte PRs"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:234
msgid "Merged PRs"
msgstr "Zusammengeführte PRs"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:40
msgid "Monthly"
msgstr "Monatlich"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:34
msgid "Name"
msgstr "Name"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx:30
#: apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx:43
#: apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx:52
msgid "New Users"
msgstr "Neue Benutzer"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:106
msgid "No credit card required"
msgstr "Keine Kreditkarte erforderlich"
msgstr ""
#: apps/marketing/src/components/(marketing)/callout.tsx:29
#: apps/marketing/src/components/(marketing)/hero.tsx:125
msgid "No Credit Card required"
msgstr "Keine Kreditkarte erforderlich"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:61
msgid "None of these work for you? Try self-hosting!"
msgstr "Keines dieser Angebote passt zu Ihnen? Versuchen Sie das Selbst-Hosting!"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:194
#: apps/marketing/src/app/(marketing)/open/page.tsx:252
msgid "Open Issues"
msgstr "Offene Issues"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:42
msgid "Open Source or Hosted."
msgstr "Open Source oder Hosted."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:161
#: apps/marketing/src/components/(marketing)/footer.tsx:37
#: apps/marketing/src/components/(marketing)/header.tsx:64
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:40
msgid "Open Startup"
msgstr "Offenes Startup"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:41
msgid "OSS Friends"
msgstr "OSS-Freunde"
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:91
msgid "Our custom templates come with smart rules that can help you save time and energy."
msgstr "Unsere benutzerdefinierten Vorlagen verfügen über intelligente Regeln, die Ihnen Zeit und Energie sparen können."
msgstr ""
#: apps/marketing/src/components/(marketing)/enterprise.tsx:20
msgid "Our Enterprise License is great for large organizations looking to switch to Documenso for all their signing needs. It's available for our cloud offering as well as self-hosted setups and offers a wide range of compliance and Adminstration Features."
msgstr "Unsere Enterprise-Lizenz ist ideal für große Organisationen, die auf Documenso für all ihre Signaturanforderungen umsteigen möchten. Sie ist sowohl für unser Cloud-Angebot als auch für selbstgehostete Setups verfügbar und bietet eine breite Palette an Compliance- und Verwaltungsfunktionen."
#: apps/marketing/src/components/(marketing)/enterprise.tsx:20
#~ msgid "Our Enterprise License is great large organizations looking to switch to Documenso for all their signing needs. It's availible for our cloud offering as well as self-hosted setups and offer a wide range of compliance and Adminstration Features."
#~ msgstr "Our Enterprise License is great large organizations looking to switch to Documenso for all their signing needs. It's availible for our cloud offering as well as self-hosted setups and offer a wide range of compliance and Adminstration Features."
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:65
msgid "Our self-hosted option is great for small teams and individuals who need a simple solution. You can use our docker based setup to get started in minutes. Take control with full customizability and data ownership."
msgstr "Unsere selbstgehostete Option ist ideal für kleine Teams und Einzelpersonen, die eine einfache Lösung benötigen. Sie können unser docker-basiertes Setup verwenden, um in wenigen Minuten loszulegen. Übernehmen Sie die Kontrolle mit vollständiger Anpassbarkeit und Datenhoheit."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/data.ts:25
msgid "Part-Time"
msgstr "Teilzeit"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:151
msgid "Premium Profile Name"
msgstr "Premium Profilname"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:40
#: apps/marketing/src/components/(marketing)/footer.tsx:31
#: apps/marketing/src/components/(marketing)/header.tsx:42
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:24
msgid "Pricing"
msgstr "Preise"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:43
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:53
msgid "Privacy"
msgstr "Datenschutz"
msgstr ""
#: apps/marketing/src/components/(marketing)/carousel.tsx:58
msgid "Profile"
msgstr "Profil"
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:108
msgid "React Widget (Soon)."
msgstr "React Widget (Demnächst)."
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:48
msgid "Receive your personal link to share with everyone you care about."
msgstr "Erhalten Sie Ihren persönlichen Link zum Teilen mit allen, die Ihnen wichtig sind."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:37
msgid "Role"
msgstr "Rolle"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:37
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:40
msgid "Salary"
msgstr "Gehalt"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:62
msgid "Save $60 or $120"
msgstr "Sparen Sie $60 oder $120"
msgstr ""
#: apps/marketing/src/components/(marketing)/i18n-switcher.tsx:47
msgid "Search languages..."
msgstr "Sprachen suchen..."
#~ msgid "Search languages..."
#~ msgstr "Sprachen suchen..."
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:109
msgid "Securely. Our data centers are located in Frankfurt (Germany), giving us the best local privacy laws. We are very aware of the sensitive nature of our data and follow best practices to ensure the security and integrity of the data entrusted to us."
msgstr "Sicher. Unsere Rechenzentren befinden sich in Frankfurt (Deutschland) und bieten uns die besten lokalen Datenschutzgesetze. Uns ist die sensible Natur unserer Daten sehr bewusst und wir folgen bewährten Praktiken, um die Sicherheit und Integrität der uns anvertrauten Daten zu gewährleisten."
msgstr ""
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:37
msgid "Send, connect, receive and embed everywhere."
msgstr "Überall senden, verbinden, empfangen und einbetten."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:34
msgid "Seniority"
msgstr "Dienstalter"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:39
msgid "Shop"
msgstr "Shop"
msgstr ""
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:63
msgid "Sign"
@@ -456,115 +447,115 @@ msgstr "Signieren"
#: apps/marketing/src/components/(marketing)/header.tsx:72
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:61
msgid "Sign in"
msgstr "Anmelden"
msgstr ""
#: apps/marketing/src/components/(marketing)/header.tsx:77
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:57
msgid "Sign up"
msgstr "Registrieren"
msgstr ""
#: apps/marketing/src/components/(marketing)/carousel.tsx:22
msgid "Signing Process"
msgstr "Signaturprozess"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:94
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:136
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:180
msgid "Signup Now"
msgstr "Jetzt registrieren"
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:89
msgid "Smart."
msgstr "Intelligent."
msgstr ""
#: apps/marketing/src/components/(marketing)/hero.tsx:132
msgid "Star on GitHub"
msgstr "Auf GitHub favorisieren"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:226
msgid "Stars"
msgstr "Favoriten"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:40
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:44
msgid "Status"
msgstr "Status"
msgstr ""
#: apps/marketing/src/components/(marketing)/footer.tsx:34
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:48
msgid "Support"
msgstr "Support"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:26
msgid "Team"
msgstr "Team"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:195
msgid "Team Inbox"
msgstr "Team-Posteingang"
msgstr ""
#: apps/marketing/src/components/(marketing)/carousel.tsx:28
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:162
msgid "Teams"
msgstr "Teams"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:83
msgid "Template Store (Soon)."
msgstr "Vorlagen-Shop (Demnächst)."
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:138
msgid "That's awesome. You can take a look at the current <0>Issues</0> and join our <1>Discord Community</1> to keep up to date, on what the current priorities are. In any case, we are an open community and welcome all input, technical and non-technical ❤️"
msgstr "Das ist großartig. Sie können sich die aktuellen <0>Issues</0> ansehen und unserer <1>Discord-Community</1> beitreten, um auf dem neuesten Stand zu bleiben, was die aktuellen Prioritäten sind. In jedem Fall sind wir eine offene Gemeinschaft und begrüßen jegliche Beiträge, technische und nicht-technische ❤️"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:293
msgid "This page is evolving as we learn what makes a great signing company. We'll update it when we have more to share."
msgstr "Diese Seite entwickelt sich weiter, während wir lernen, was ein großartiges Signing-Unternehmen ausmacht. Wir werden sie aktualisieren, wenn wir mehr zu teilen haben."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:31
msgid "Title"
msgstr "Titel"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx:30
#: apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx:55
msgid "Total Completed Documents"
msgstr "Insgesamt Abgeschlossene Dokumente"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/page.tsx:267
#: apps/marketing/src/app/(marketing)/open/page.tsx:268
msgid "Total Customers"
msgstr "Insgesamt Kunden"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/funding-raised.tsx:29
msgid "Total Funding Raised"
msgstr "Insgesamt Finanzierungsvolumen"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx:30
#: apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx:43
#: apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx:52
msgid "Total Users"
msgstr "Gesamtanzahl der Benutzer"
msgstr ""
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:31
msgid "Truly your own."
msgstr "Wirklich Ihr Eigenes."
msgstr ""
#: apps/marketing/src/components/(marketing)/callout.tsx:27
#: apps/marketing/src/components/(marketing)/hero.tsx:123
msgid "Try our Free Plan"
msgstr "Probieren Sie unseren Gratisplan aus"
msgstr ""
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:20
msgid "Twitter Stats"
msgstr "Twitter-Statistiken"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:142
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:186
msgid "Unlimited Documents per Month"
msgstr "Unbegrenzte Dokumente pro Monat"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:103
msgid "Up to 10 recipients per document"
msgstr "Bis zu 10 Empfänger pro Dokument"
msgstr ""
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:52
msgid "Upload a document and add fields."
@@ -572,48 +563,52 @@ msgstr "Laden Sie ein Dokument hoch und fügen Sie Felder hinzu."
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:123
msgid "Using our hosted version is the easiest way to get started, you can simply subscribe and start signing your documents. We take care of the infrastructure, so you can focus on your business. Additionally, when using our hosted version you benefit from our trusted signing certificates which helps you to build trust with your customers."
msgstr "Die Nutzung unserer gehosteten Version ist der einfachste Weg, um zu starten. Sie können einfach abonnieren und mit der Unterzeichnung Ihrer Dokumente beginnen. Wir kümmern uns um die Infrastruktur, damit Sie sich auf Ihr Geschäft konzentrieren können. Zudem profitieren Sie bei der Nutzung unserer gehosteten Version von unseren vertrauenswürdigen Signaturzertifikaten, die Ihnen helfen, Vertrauen bei Ihren Kunden aufzubauen."
msgstr ""
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:33
msgid "View all stats"
msgstr "Alle Statistiken anzeigen"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:195
msgid "We are happy to assist you at <0>support@documenso.com</0> or <1>in our Discord-Support-Channel</1> please message either Lucas or Timur to get added to the channel if you are not already a member."
msgstr "Wir helfen Ihnen gerne unter <0>support@documenso.com</0> oder <1>in unserem Discord-Support-Kanal</1>. Bitte senden Sie Lucas oder Timur eine Nachricht, um dem Kanal beizutreten, falls Sie noch kein Mitglied sind."
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:89
msgid "What is the difference between the plans?"
msgstr "Was ist der Unterschied zwischen den Plänen?"
msgstr ""
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:47
msgid "When it comes to sending or receiving a contract, you can count on lightning-fast speeds."
msgstr "Wenn es um das Senden oder Empfangen eines Vertrags geht, können Sie auf blitzschnelle Geschwindigkeiten zählen."
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:191
msgid "Where can I get support?"
msgstr "Wo kann ich Unterstützung bekommen?"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:177
msgid "Why should I prefer Documenso over DocuSign or some other signing tool?"
msgstr "Warum sollte ich Documenso gegenüber DocuSign oder einem anderen Signatur-Tool bevorzugen?"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:119
msgid "Why should I use your hosting service?"
msgstr "Warum sollte ich Ihren Hosting-Service nutzen?"
msgstr ""
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:60
msgid "Yearly"
msgstr "Jährlich"
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:167
msgid "Yes! Documenso is offered under the GNU AGPL V3 open source license. This means you can use it for free and even modify it to fit your needs, as long as you publish your changes under the same license."
msgstr "Ja! Documenso wird unter der GNU AGPL V3 Open-Source-Lizenz angeboten. Das bedeutet, dass Sie es kostenlos nutzen und sogar an Ihre Bedürfnisse anpassen können, solange Sie Ihre Änderungen unter derselben Lizenz veröffentlichen."
msgstr ""
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:93
msgid "You can self-host Documenso for free or use our ready-to-use hosted version. The hosted version comes with additional support, painless scalability and more. Early adopters will get access to all features we build this year, for no additional cost! Forever! Yes, that includes multiple users per account later. If you want Documenso for your enterprise, we are happy to talk about your needs."
msgstr "Sie können Documenso kostenlos selbst hosten oder unsere sofort einsatzbereite gehostete Version nutzen. Die gehostete Version bietet zusätzlichen Support, schmerzfreie Skalierbarkeit und mehr. Frühzeitige Anwender erhalten in diesem Jahr Zugriff auf alle Funktionen, die wir entwickeln, ohne zusätzliche Kosten! Für immer! Ja, das beinhaltet später mehrere Benutzer pro Konto. Wenn Sie Documenso für Ihr Unternehmen möchten, sprechen wir gerne über Ihre Bedürfnisse."
msgstr ""
#: apps/marketing/src/components/(marketing)/carousel.tsx:265
msgid "Your browser does not support the video tag."
msgstr "Ihr Browser unterstützt das Video-Tag nicht."
msgstr ""
#: apps/marketing/src/components/(marketing)/carousel.tsx:265
#~ msgid "Your browser does not support the video tag.<<<<<<< HEAD"
#~ msgstr "Ihr Browser unterstützt das Video-Tag nicht.>>>>>>> main"

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2024-07-24 13:01+1000\n"
"POT-Creation-Date: 2024-08-22 05:16+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: de\n"
@@ -303,7 +303,7 @@ msgstr "Das Hinzufügen und Entfernen von Sitzplätzen wird Ihre Rechnung entspr
msgid "Admin Actions"
msgstr "Admin-Aktionen"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:257
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:262
msgid "Admin panel"
msgstr "Admin-Panel"
@@ -311,7 +311,7 @@ msgstr "Admin-Panel"
msgid "All"
msgstr "Alle"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:37
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:42
msgid "All documents"
msgstr "Alle Dokumente"
@@ -327,7 +327,7 @@ msgstr "Alle eingefügten Unterschriften werden annulliert"
msgid "All recipients will be notified"
msgstr "Alle Empfänger werden benachrichtigt"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:52
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:57
msgid "All templates"
msgstr "Alle Vorlagen"
@@ -481,6 +481,7 @@ msgstr "Ein Fehler ist aufgetreten, während dein Dokument hochgeladen wurde."
#: apps/web/src/app/(dashboard)/settings/profile/delete-account-dialog.tsx:63
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:98
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/team-transfer-status.tsx:54
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:301
#: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:97
#: apps/web/src/components/(dashboard)/settings/webhooks/delete-webhook-dialog.tsx:88
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:100
@@ -793,7 +794,7 @@ msgstr "Betrachten abschließen"
msgid "Completed"
msgstr "Abgeschlossen"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:43
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:48
msgid "Completed documents"
msgstr "Abgeschlossene Dokumente"
@@ -927,8 +928,8 @@ msgstr "Jetzt erstellen"
msgid "Create one automatically"
msgstr "Einen automatisch erstellen"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:176
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:246
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:181
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:251
#: apps/web/src/components/(teams)/dialogs/create-team-dialog.tsx:138
#: apps/web/src/components/(teams)/dialogs/create-team-dialog.tsx:146
msgid "Create team"
@@ -1006,7 +1007,7 @@ msgstr "Aktueller Plan: {0}"
msgid "Daily"
msgstr "Täglich"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:255
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:265
msgid "Dark Mode"
msgstr "Dunkelmodus"
@@ -1316,7 +1317,7 @@ msgstr "Dokument wird dauerhaft gelöscht"
#: apps/web/src/app/(dashboard)/documents/documents-page-view.tsx:110
#: apps/web/src/app/(profile)/p/[url]/page.tsx:166
#: apps/web/src/app/not-found.tsx:21
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:200
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:205
#: apps/web/src/components/(dashboard)/layout/desktop-nav.tsx:18
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:35
#: apps/web/src/components/ui/user-profile-timur.tsx:60
@@ -1358,7 +1359,7 @@ msgstr "Zertifikat herunterladen"
msgid "Draft"
msgstr "Entwurf"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:41
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:46
msgid "Draft documents"
msgstr "Entwurfdokumente"
@@ -1683,7 +1684,7 @@ msgstr "Wenn Ihre Authenticator-App keine QR-Codes unterstützt, können Sie sta
msgid "Inbox"
msgstr "Posteingang"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:47
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:52
msgid "Inbox documents"
msgstr "Posteingang Dokumente"
@@ -1773,6 +1774,10 @@ msgstr "Es scheint, dass kein Token bereitgestellt wurde. Wenn Sie versuchen, Ih
msgid "It seems that there is no token provided. Please check your email and try again."
msgstr "Es scheint, dass kein Token bereitgestellt wurde. Bitte überprüfen Sie Ihre E-Mail und versuchen Sie es erneut."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:286
msgid "Language"
msgstr ""
#: apps/web/src/components/(dashboard)/period-selector/period-selector.tsx:61
msgid "Last 14 days"
msgstr "Die letzten 14 Tage"
@@ -1810,7 +1815,7 @@ msgstr "Verlassen"
msgid "Leave team"
msgstr "Team verlassen"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:254
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:264
msgid "Light Mode"
msgstr "Lichtmodus"
@@ -1900,7 +1905,7 @@ msgstr "Abonnements verwalten"
msgid "Manage team subscription."
msgstr "Teamabonnement verwalten."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:163
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:168
msgid "Manage teams"
msgstr "Teams verwalten"
@@ -2054,7 +2059,7 @@ msgstr "Keine aktuellen Aktivitäten"
msgid "No recipients"
msgstr "Keine Empfänger"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:195
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:200
msgid "No results found."
msgstr "Keine Ergebnisse gefunden."
@@ -2146,7 +2151,7 @@ msgid "Otherwise, the document will be created as a draft."
msgstr "Andernfalls wird das Dokument als Entwurf erstellt."
#: apps/web/src/app/(dashboard)/admin/documents/document-results.tsx:86
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:76
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:81
msgid "Owner"
msgstr "Besitzer"
@@ -2191,7 +2196,7 @@ msgstr "Passkeys ermöglichen das Anmelden und die Authentifizierung mit biometr
msgid "Passkeys are not supported on this browser"
msgstr "Passkeys werden von diesem Browser nicht unterstützt"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:65
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:70
#: apps/web/src/components/forms/password.tsx:123
#: apps/web/src/components/forms/reset-password.tsx:110
#: apps/web/src/components/forms/signin.tsx:344
@@ -2225,7 +2230,7 @@ msgstr "Zahlung überfällig"
msgid "Pending"
msgstr "Ausstehend"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:46
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:51
msgid "Pending documents"
msgstr "Ausstehende Dokumente"
@@ -2241,11 +2246,11 @@ msgstr "Ausstehende Einladungen"
msgid "Pending team deleted."
msgstr "Ausstehendes Team gelöscht."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:129
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:134
msgid "Personal"
msgstr "Persönlich"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:72
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:77
msgid "Personal Account"
msgstr "Persönliches Konto"
@@ -2329,7 +2334,7 @@ msgstr "Bitte versuchen Sie es später noch einmal."
msgid "Please type <0>{0}</0> to confirm."
msgstr "Bitte geben Sie <0>{0}</0> ein, um zu bestätigen."
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:209
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:214
msgid "Preferences"
msgstr "Einstellungen"
@@ -2347,7 +2352,7 @@ msgid "Private templates can only be modified and viewed by you."
msgstr "Private Vorlagen können nur von Ihnen bearbeitet und angezeigt werden."
#: apps/web/src/app/(dashboard)/settings/profile/page.tsx:28
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:64
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:69
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:36
#: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:39
msgid "Profile"
@@ -2666,8 +2671,8 @@ msgid "Set a password"
msgstr "Ein Passwort festlegen"
#: apps/web/src/app/(dashboard)/settings/layout.tsx:20
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:60
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:206
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:65
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:211
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:47
msgid "Settings"
msgstr "Einstellungen"
@@ -2751,7 +2756,7 @@ msgstr "Einloggen"
msgid "Sign in to your account"
msgstr "Melden Sie sich bei Ihrem Konto an"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:285
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:297
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:84
msgid "Sign Out"
msgstr "Ausloggen"
@@ -2957,7 +2962,7 @@ msgstr "Erfolg"
msgid "Successfully created passkey"
msgstr "Passkey erfolgreich erstellt"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:256
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:266
msgid "System Theme"
msgstr "Systemthema"
@@ -3042,7 +3047,7 @@ msgstr "Team-Eigentum übertragen!"
msgid "Team Public Profile"
msgstr "Öffentliches Profil des Teams"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:272
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:277
msgid "Team settings"
msgstr "Teameinstellungen"
@@ -3068,7 +3073,7 @@ msgid "Team URL"
msgstr "Team-URL"
#: apps/web/src/app/(dashboard)/settings/teams/page.tsx:25
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:157
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:162
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:43
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:64
#: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:67
@@ -3114,7 +3119,7 @@ msgstr "Template saved"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:60
#: apps/web/src/app/(dashboard)/templates/templates-page-view.tsx:55
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:203
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:208
#: apps/web/src/components/(dashboard)/layout/desktop-nav.tsx:22
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:39
msgid "Templates"
@@ -3522,7 +3527,7 @@ msgstr "Type"
msgid "Type 'delete' to confirm"
msgstr "Type 'delete' to confirm"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:181
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:186
msgid "Type a command or search..."
msgstr "Type a command or search..."
@@ -3530,6 +3535,10 @@ msgstr "Type a command or search..."
msgid "Uh oh! Looks like you're missing a token"
msgstr "Uh oh! Looks like you're missing a token"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:303
msgid "Unable to change the language at this time. Please try again later."
msgstr ""
#: apps/web/src/components/forms/2fa/recovery-code-list.tsx:31
msgid "Unable to copy recovery code"
msgstr "Unable to copy recovery code"
@@ -3728,7 +3737,7 @@ msgstr "Benutzer-ID"
msgid "User profiles are here!"
msgstr "Benutzerprofile sind hier!"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:264
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:269
msgid "User settings"
msgstr "Benutzereinstellungen"
@@ -4360,7 +4369,7 @@ msgstr "Ihr Dokument wurde erfolgreich hochgeladen."
msgid "Your document has been uploaded successfully. You will be redirected to the template page."
msgstr "Ihr Dokument wurde erfolgreich hochgeladen. Sie werden zur Vorlagenseite weitergeleitet."
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:215
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:223
msgid "Your documents"
msgstr "Ihre Dokumente"

View File

@@ -362,7 +362,7 @@ msgstr "Max"
msgid "Member"
msgstr "Member"
#: packages/ui/primitives/document-flow/add-subject.tsx:95
#: packages/ui/primitives/document-flow/add-subject.tsx:229
#: packages/ui/primitives/template-flow/add-template-settings.tsx:215
msgid "Message <0>(Optional)</0>"
msgstr "Message <0>(Optional)</0>"
@@ -517,6 +517,10 @@ msgstr "Save"
msgid "Save Template"
msgstr "Save Template"
#: packages/ui/components/common/language-switcher-dialog.tsx:34
msgid "Search languages..."
msgstr "Search languages..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:105
msgid "Select"
msgstr "Select"
@@ -533,7 +537,7 @@ msgstr "Select at least"
msgid "Select default option"
msgstr "Select default option"
#: packages/ui/primitives/document-flow/add-subject.tsx:124
#: packages/ui/primitives/document-flow/add-subject.tsx:275
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:34
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:64
msgid "Send"
@@ -595,7 +599,7 @@ msgstr "Something went wrong."
msgid "Step <0>{step} of {maxStep}</0>"
msgstr "Step <0>{step} of {maxStep}</0>"
#: packages/ui/primitives/document-flow/add-subject.tsx:78
#: packages/ui/primitives/document-flow/add-subject.tsx:194
#: packages/ui/primitives/template-flow/add-template-settings.tsx:195
msgid "Subject <0>(Optional)</0>"
msgstr "Subject <0>(Optional)</0>"
@@ -703,7 +707,7 @@ msgstr "Title"
msgid "To proceed further, please set at least one value for the {0} field."
msgstr "To proceed further, please set at least one value for the {0} field."
#: packages/ui/primitives/document-flow/add-subject.tsx:124
#: packages/ui/primitives/document-flow/add-subject.tsx:275
msgid "Update"
msgstr "Update"

File diff suppressed because one or more lines are too long

View File

@@ -425,8 +425,8 @@ msgid "Save $60 or $120"
msgstr "Save $60 or $120"
#: apps/marketing/src/components/(marketing)/i18n-switcher.tsx:47
msgid "Search languages..."
msgstr "Search languages..."
#~ msgid "Search languages..."
#~ msgstr "Search languages..."
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:109
msgid "Securely. Our data centers are located in Frankfurt (Germany), giving us the best local privacy laws. We are very aware of the sensitive nature of our data and follow best practices to ensure the security and integrity of the data entrusted to us."

File diff suppressed because one or more lines are too long

View File

@@ -298,7 +298,7 @@ msgstr "Adding and removing seats will adjust your invoice accordingly."
msgid "Admin Actions"
msgstr "Admin Actions"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:257
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:262
msgid "Admin panel"
msgstr "Admin panel"
@@ -306,7 +306,7 @@ msgstr "Admin panel"
msgid "All"
msgstr "All"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:37
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:42
msgid "All documents"
msgstr "All documents"
@@ -322,7 +322,7 @@ msgstr "All inserted signatures will be voided"
msgid "All recipients will be notified"
msgstr "All recipients will be notified"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:52
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:57
msgid "All templates"
msgstr "All templates"
@@ -476,6 +476,7 @@ msgstr "An error occurred while uploading your document."
#: apps/web/src/app/(dashboard)/settings/profile/delete-account-dialog.tsx:63
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:98
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/team-transfer-status.tsx:54
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:301
#: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:97
#: apps/web/src/components/(dashboard)/settings/webhooks/delete-webhook-dialog.tsx:88
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:100
@@ -788,7 +789,7 @@ msgstr "Complete Viewing"
msgid "Completed"
msgstr "Completed"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:43
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:48
msgid "Completed documents"
msgstr "Completed documents"
@@ -922,8 +923,8 @@ msgstr "Create now"
msgid "Create one automatically"
msgstr "Create one automatically"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:176
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:246
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:181
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:251
#: apps/web/src/components/(teams)/dialogs/create-team-dialog.tsx:138
#: apps/web/src/components/(teams)/dialogs/create-team-dialog.tsx:146
msgid "Create team"
@@ -1003,7 +1004,7 @@ msgstr "Current plan: {0}"
msgid "Daily"
msgstr "Daily"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:255
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:265
msgid "Dark Mode"
msgstr "Dark Mode"
@@ -1313,7 +1314,7 @@ msgstr "Document will be permanently deleted"
#: apps/web/src/app/(dashboard)/documents/documents-page-view.tsx:110
#: apps/web/src/app/(profile)/p/[url]/page.tsx:166
#: apps/web/src/app/not-found.tsx:21
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:200
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:205
#: apps/web/src/components/(dashboard)/layout/desktop-nav.tsx:18
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:35
#: apps/web/src/components/ui/user-profile-timur.tsx:60
@@ -1355,7 +1356,7 @@ msgstr "Download Certificate"
msgid "Draft"
msgstr "Draft"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:41
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:46
msgid "Draft documents"
msgstr "Draft documents"
@@ -1682,7 +1683,7 @@ msgstr "If your authenticator app does not support QR codes, you can use the fol
msgid "Inbox"
msgstr "Inbox"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:47
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:52
msgid "Inbox documents"
msgstr "Inbox documents"
@@ -1772,6 +1773,10 @@ msgstr "It seems that there is no token provided, if you are trying to verify yo
msgid "It seems that there is no token provided. Please check your email and try again."
msgstr "It seems that there is no token provided. Please check your email and try again."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:286
msgid "Language"
msgstr "Language"
#: apps/web/src/components/(dashboard)/period-selector/period-selector.tsx:61
msgid "Last 14 days"
msgstr "Last 14 days"
@@ -1809,7 +1814,7 @@ msgstr "Leave"
msgid "Leave team"
msgstr "Leave team"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:254
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:264
msgid "Light Mode"
msgstr "Light Mode"
@@ -1899,7 +1904,7 @@ msgstr "Manage subscriptions"
msgid "Manage team subscription."
msgstr "Manage team subscription."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:163
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:168
msgid "Manage teams"
msgstr "Manage teams"
@@ -2053,7 +2058,7 @@ msgstr "No recent activity"
msgid "No recipients"
msgstr "No recipients"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:195
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:200
msgid "No results found."
msgstr "No results found."
@@ -2145,7 +2150,7 @@ msgid "Otherwise, the document will be created as a draft."
msgstr "Otherwise, the document will be created as a draft."
#: apps/web/src/app/(dashboard)/admin/documents/document-results.tsx:86
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:76
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:81
msgid "Owner"
msgstr "Owner"
@@ -2190,7 +2195,7 @@ msgstr "Passkeys allow you to sign in and authenticate using biometrics, passwor
msgid "Passkeys are not supported on this browser"
msgstr "Passkeys are not supported on this browser"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:65
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:70
#: apps/web/src/components/forms/password.tsx:123
#: apps/web/src/components/forms/reset-password.tsx:110
#: apps/web/src/components/forms/signin.tsx:344
@@ -2224,7 +2229,7 @@ msgstr "Payment overdue"
msgid "Pending"
msgstr "Pending"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:46
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:51
msgid "Pending documents"
msgstr "Pending documents"
@@ -2240,11 +2245,11 @@ msgstr "Pending invitations"
msgid "Pending team deleted."
msgstr "Pending team deleted."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:129
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:134
msgid "Personal"
msgstr "Personal"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:72
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:77
msgid "Personal Account"
msgstr "Personal Account"
@@ -2328,7 +2333,7 @@ msgstr "Please try again later."
msgid "Please type <0>{0}</0> to confirm."
msgstr "Please type <0>{0}</0> to confirm."
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:209
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:214
msgid "Preferences"
msgstr "Preferences"
@@ -2346,7 +2351,7 @@ msgid "Private templates can only be modified and viewed by you."
msgstr "Private templates can only be modified and viewed by you."
#: apps/web/src/app/(dashboard)/settings/profile/page.tsx:28
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:64
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:69
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:36
#: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:39
msgid "Profile"
@@ -2665,8 +2670,8 @@ msgid "Set a password"
msgstr "Set a password"
#: apps/web/src/app/(dashboard)/settings/layout.tsx:20
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:60
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:206
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:65
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:211
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:47
msgid "Settings"
msgstr "Settings"
@@ -2750,7 +2755,7 @@ msgstr "Sign In"
msgid "Sign in to your account"
msgstr "Sign in to your account"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:285
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:297
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:84
msgid "Sign Out"
msgstr "Sign Out"
@@ -2956,7 +2961,7 @@ msgstr "Success"
msgid "Successfully created passkey"
msgstr "Successfully created passkey"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:256
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:266
msgid "System Theme"
msgstr "System Theme"
@@ -3041,7 +3046,7 @@ msgstr "Team ownership transferred!"
msgid "Team Public Profile"
msgstr "Team Public Profile"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:272
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:277
msgid "Team settings"
msgstr "Team settings"
@@ -3067,7 +3072,7 @@ msgid "Team URL"
msgstr "Team URL"
#: apps/web/src/app/(dashboard)/settings/teams/page.tsx:25
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:157
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:162
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:43
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:64
#: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:67
@@ -3113,7 +3118,7 @@ msgstr "Template saved"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:60
#: apps/web/src/app/(dashboard)/templates/templates-page-view.tsx:55
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:203
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:208
#: apps/web/src/components/(dashboard)/layout/desktop-nav.tsx:22
#: apps/web/src/components/(dashboard)/layout/mobile-navigation.tsx:39
msgid "Templates"
@@ -3521,7 +3526,7 @@ msgstr "Type"
msgid "Type 'delete' to confirm"
msgstr "Type 'delete' to confirm"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:181
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:186
msgid "Type a command or search..."
msgstr "Type a command or search..."
@@ -3529,6 +3534,10 @@ msgstr "Type a command or search..."
msgid "Uh oh! Looks like you're missing a token"
msgstr "Uh oh! Looks like you're missing a token"
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:303
msgid "Unable to change the language at this time. Please try again later."
msgstr "Unable to change the language at this time. Please try again later."
#: apps/web/src/components/forms/2fa/recovery-code-list.tsx:31
msgid "Unable to copy recovery code"
msgstr "Unable to copy recovery code"
@@ -3727,7 +3736,7 @@ msgstr "User ID"
msgid "User profiles are here!"
msgstr "User profiles are here!"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:264
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:269
msgid "User settings"
msgstr "User settings"
@@ -4359,7 +4368,7 @@ msgstr "Your document has been uploaded successfully."
msgid "Your document has been uploaded successfully. You will be redirected to the template page."
msgstr "Your document has been uploaded successfully. You will be redirected to the template page."
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:215
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:223
msgid "Your documents"
msgstr "Your documents"

View File

@@ -36,7 +36,7 @@ const parseLanguageFromLocale = (locale: string): SupportedLanguageCodes | null
export const extractLocaleDataFromCookies = (
cookies: ReadonlyRequestCookies,
): SupportedLanguageCodes | null => {
const preferredLocale = cookies.get('i18n')?.value || '';
const preferredLocale = cookies.get('language')?.value || '';
const language = parseLanguageFromLocale(preferredLocale || '');

View File

@@ -38,6 +38,7 @@ import {
ZResendDocumentMutationSchema,
ZSearchDocumentsMutationSchema,
ZSendDocumentMutationSchema,
ZSetDocumentEmailSettingsMutationSchema,
ZSetPasswordForDocumentMutationSchema,
ZSetSettingsForDocumentMutationSchema,
ZSetTitleForDocumentMutationSchema,
@@ -275,6 +276,32 @@ export const documentRouter = router({
}
}),
setDocumentEmailSettings: authenticatedProcedure
.input(ZSetDocumentEmailSettingsMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
const { documentId, subject, message } = input;
const userId = ctx.user.id;
return await upsertDocumentMeta({
documentId,
userId,
subject,
message,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update the email settings for this document. Please try again later.',
});
}
}),
setPasswordForDocument: authenticatedProcedure
.input(ZSetPasswordForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {

View File

@@ -139,6 +139,12 @@ export const ZSendDocumentMutationSchema = z.object({
}),
});
export const ZSetDocumentEmailSettingsMutationSchema = z.object({
documentId: z.number(),
subject: z.string().optional(),
message: z.string().optional(),
});
export const ZSetPasswordForDocumentMutationSchema = z.object({
documentId: z.number(),
password: z.string(),

View File

@@ -0,0 +1,57 @@
import { msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { CheckIcon } from 'lucide-react';
import { SUPPORTED_LANGUAGES } from '@documenso/lib/constants/i18n';
import { switchI18NLanguage } from '@documenso/lib/server-only/i18n/switch-i18n-language';
import { dynamicActivate } from '@documenso/lib/utils/i18n';
import { cn } from '@documenso/ui/lib/utils';
import {
CommandDialog,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@documenso/ui/primitives/command';
type LanguageSwitcherDialogProps = {
open: boolean;
setOpen: (_open: boolean) => void;
};
export const LanguageSwitcherDialog = ({ open, setOpen }: LanguageSwitcherDialogProps) => {
const { i18n, _ } = useLingui();
const setLanguage = async (lang: string) => {
setOpen(false);
await dynamicActivate(i18n, lang);
await switchI18NLanguage(lang);
};
return (
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder={_(msg`Search languages...`)} />
<CommandList>
<CommandGroup>
{Object.values(SUPPORTED_LANGUAGES).map((language) => (
<CommandItem
key={language.short}
value={language.full}
onSelect={async () => setLanguage(language.short)}
>
<CheckIcon
className={cn(
'mr-2 h-4 w-4',
i18n.locale === language.short ? 'opacity-100' : 'opacity-0',
)}
/>
{SUPPORTED_LANGUAGES[language.short].full}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</CommandDialog>
);
};

View File

@@ -1,14 +1,23 @@
'use client';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans, msg } from '@lingui/macro';
import { Loader } from 'lucide-react';
import { useForm } from 'react-hook-form';
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
import type { Field, Recipient } from '@documenso/prisma/client';
import { DocumentStatus } from '@documenso/prisma/client';
import type { DocumentWithData } from '@documenso/prisma/types/document-with-data';
import { trpc } from '@documenso/trpc/react';
import { DocumentSendEmailMessageHelper } from '@documenso/ui/components/document/document-send-email-message-helper';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { Button } from '../button';
import { FormErrorMessage } from '../form/form-error-message';
import { Input } from '../input';
import { Label } from '../label';
@@ -45,6 +54,7 @@ export const AddSubjectFormPartial = ({
const {
register,
handleSubmit,
setValue,
formState: { errors, isSubmitting },
} = useForm<TAddSubjectFormSchema>({
defaultValues: {
@@ -56,6 +66,111 @@ export const AddSubjectFormPartial = ({
resolver: zodResolver(ZAddSubjectFormSchema),
});
const [oldEmailData, setOldEmailData] = useState<{ subject: string; message: string } | null>(
document.documentMeta
? {
subject: document.documentMeta.subject ?? '',
message: document.documentMeta.message ?? '',
}
: null,
);
const [changedFields, setChangedFields] = useState<{ subject: boolean; message: boolean }>({
subject: false,
message: false,
});
const { toast } = useToast();
const router = useRouter();
const utils = trpc.useUtils();
const { mutateAsync: setEmailSettingsForDocument } =
trpc.document.setDocumentEmailSettings.useMutation({
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
onSuccess: () => {
const data = utils.document.getDocumentWithDetailsById.getData({
id: document.id,
});
setOldEmailData({
subject: data?.documentMeta?.subject ?? '',
message: data?.documentMeta?.message ?? '',
});
},
});
const handleOnBlur = async (field: 'subject' | 'message', value: string) => {
if (value == oldEmailData?.[field]) return;
try {
await setEmailSettingsForDocument({
documentId: document.id,
[field]: value,
});
setChangedFields((prev) => ({ ...prev, [field]: true }));
router.refresh();
toast({
title: 'Email settings updated',
description: 'The email settings for the document have been updated.',
duration: 5000,
});
} catch (e) {
console.error(e);
toast({
title: 'Error',
description: 'An error occurred while updating the email settings.',
duration: 5000,
});
}
};
const handleUndoButton = async (field: 'subject' | 'message') => {
if (!oldEmailData) return;
try {
await setEmailSettingsForDocument({
documentId: document.id,
[field]: oldEmailData[field],
});
setValue(`meta.${field}`, oldEmailData[field]);
setOldEmailData((prev) => (prev ? { ...prev, [field]: undefined } : null));
setChangedFields((prev) => ({ ...prev, [field]: false }));
router.refresh();
toast({
title: 'Change reverted',
description: `The latest change to the ${field} has been reverted.`,
duration: 5000,
});
if (oldEmailData.subject === undefined && oldEmailData.message === undefined) {
setOldEmailData(null);
}
} catch (e) {
console.error(e);
toast({
title: 'Error',
description: 'An error occurred while undoing the latest change',
duration: 5000,
});
}
};
useEffect(() => {
const timeout = setTimeout(() => {
setChangedFields({ subject: false, message: false });
}, 5000);
return () => {
clearTimeout(timeout);
};
}, [oldEmailData]);
const onFormSubmit = handleSubmit(onSubmit);
const { currentStep, totalSteps, previousStep } = useStep();
@@ -65,6 +180,7 @@ export const AddSubjectFormPartial = ({
title={documentFlow.title}
description={documentFlow.description}
/>
<DocumentFlowFormContainerContent>
<div className="flex flex-col">
{isDocumentPdfLoaded &&
@@ -84,9 +200,27 @@ export const AddSubjectFormPartial = ({
id="subject"
className="bg-background mt-2"
disabled={isSubmitting}
{...register('meta.subject')}
{...register('meta.subject', {
onBlur: (event) => {
void handleOnBlur('subject', event.target.value);
},
})}
/>
{changedFields.subject && oldEmailData && (
<div className="mt-2 flex items-center">
<Button
className="-ml-2"
size="sm"
variant="link"
onClick={() => void handleUndoButton('subject')}
>
<span className="text-xs">Undo change</span>
<Loader className="ml-1 h-4 w-4 animate-spin text-gray-500" />
</Button>
</div>
)}
<FormErrorMessage className="mt-2" error={errors.meta?.subject} />
</div>
@@ -101,15 +235,32 @@ export const AddSubjectFormPartial = ({
id="message"
className="bg-background mt-2 h-32 resize-none"
disabled={isSubmitting}
{...register('meta.message')}
{...register('meta.message', {
onBlur: (event) => {
void handleOnBlur('message', event.target.value);
},
})}
/>
{changedFields.message && oldEmailData && (
<div className="mt-2 flex items-center">
<Button
className="-ml-2"
size="sm"
variant="link"
onClick={() => void handleUndoButton('message')}
>
<span className="text-xs">Undo change</span>
<Loader className="ml-1 h-4 w-4 animate-spin text-gray-500" />
</Button>
</div>
)}
<FormErrorMessage
className="mt-2"
error={typeof errors.meta?.message !== 'string' ? errors.meta?.message : undefined}
/>
</div>
<DocumentSendEmailMessageHelper />
</div>
</div>