🧑💻 Migrate to Tolgee (#976)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ### Summary by CodeRabbit - Refactor: Transitioned to a new translation library (`@tolgee/react`) across the application, enhancing the localization capabilities and consistency. - New Feature: Introduced a JSON configuration file for application settings, improving customization and flexibility. - Refactor: Updated SVG attribute naming convention in the `WhatsAppLogo` component to align with React standards. - Chore: Adjusted the `.gitignore` file and added a new line at the end. - Documentation: Added instructions for setting up environment variables for the Tolgee i18n contribution dev tool, improving the self-hosting configuration guide. - Style: Updated the `CollaborationMenuButton` to hide the `PopoverContent` component by scaling it down to zero. - Refactor: Simplified error handling logic for fetching and updating typebots in `TypebotProvider.tsx`, improving code readability and maintenance. - Refactor: Removed the dependency on the `parseGroupTitle` function, simplifying the code in several components. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@ -29,6 +29,8 @@
|
||||
"@sentry/nextjs": "7.73.0",
|
||||
"@tanstack/react-query": "^4.29.19",
|
||||
"@tanstack/react-table": "8.9.3",
|
||||
"@tolgee/format-icu": "^5.13.3",
|
||||
"@tolgee/react": "^5.13.3",
|
||||
"@trpc/client": "10.40.0",
|
||||
"@trpc/next": "10.40.0",
|
||||
"@trpc/react-query": "10.40.0",
|
||||
@ -68,7 +70,6 @@
|
||||
"micro-cors": "0.1.1",
|
||||
"next": "13.5.4",
|
||||
"next-auth": "4.22.1",
|
||||
"next-international": "0.9.5",
|
||||
"nextjs-cors": "^2.1.2",
|
||||
"nodemailer": "6.9.3",
|
||||
"nprogress": "0.2.0",
|
||||
|
251
apps/builder/public/locales/de.json
Normal file
251
apps/builder/public/locales/de.json
Normal file
@ -0,0 +1,251 @@
|
||||
{
|
||||
"account.apiTokens.createButton.label": "Erstellen",
|
||||
"account.apiTokens.createModal.copyInstruction": "Bitte kopiere deinen Token und bewahre ihn an einem sicheren Ort auf.",
|
||||
"account.apiTokens.createModal.createButton.label": "Token erstellen",
|
||||
"account.apiTokens.createModal.createHeading": "Token erstellen",
|
||||
"account.apiTokens.createModal.createdHeading": "Token erstellt",
|
||||
"account.apiTokens.createModal.doneButton.label": "Fertig",
|
||||
"account.apiTokens.createModal.nameInput.label": "Gib einen eindeutigen Namen für deinen Token ein, um ihn von anderen Token zu unterscheiden.",
|
||||
"account.apiTokens.createModal.nameInput.placeholder": "Z.B. Zapier, Github, Make.com",
|
||||
"account.apiTokens.createModal.securityWarning": "Aus Sicherheitsgründen können wir ihn nicht erneut anzeigen.",
|
||||
"account.apiTokens.deleteButton.label": "Löschen",
|
||||
"account.apiTokens.deleteConfirmationMessage": "Der Token <strong>tokenName</strong> wird dauerhaft widerrufen, bist du sicher, dass du fortfahren möchtest?",
|
||||
"account.apiTokens.description": "Diese Token ermöglichen es anderen Apps, dein gesamtes Konto und Typebots zu steuern. Sei vorsichtig!",
|
||||
"account.apiTokens.heading": "API-Token",
|
||||
"account.apiTokens.table.createdHeader": "Erstellt",
|
||||
"account.apiTokens.table.nameHeader": "Name",
|
||||
"account.myAccount.changePhotoButton.label": "Foto ändern",
|
||||
"account.myAccount.changePhotoButton.specification": ".jpg oder .png, max 1MB",
|
||||
"account.myAccount.emailInput.disabledTooltip": "Das Aktualisieren der E-Mail-Adresse ist nicht verfügbar. Kontaktiere den Support, wenn du sie ändern möchtest.",
|
||||
"account.myAccount.emailInput.label": "E-Mail-Adresse:",
|
||||
"account.myAccount.nameInput.label": "Name:",
|
||||
"account.preferences.appearance.darkLabel": "Dunkel",
|
||||
"account.preferences.appearance.heading": "Erscheinungsbild",
|
||||
"account.preferences.appearance.lightLabel": "Hell",
|
||||
"account.preferences.appearance.systemLabel": "System",
|
||||
"account.preferences.graphNavigation.heading": "Editor-Navigation",
|
||||
"account.preferences.graphNavigation.mouse.description": "Bewege dich, indem du das Board ziehst und zoome rein/raus mit dem Mausrad",
|
||||
"account.preferences.graphNavigation.mouse.label": "Maus",
|
||||
"account.preferences.graphNavigation.trackpad.description": "Bewege das Board mit 2 Fingern und zoome rein/raus, indem du kneifst",
|
||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||
"account.preferences.language.heading": "Sprache",
|
||||
"account.preferences.language.tooltip": "Die Übersetzungen sind noch nicht vollständig. Es ist eine laufende Arbeit. \uD83E\uDD13",
|
||||
"analytics.completionRateLabel": "Abschlussrate",
|
||||
"analytics.notAvailableLabel": "Nicht verfügbar",
|
||||
"analytics.startsLabel": "Starts",
|
||||
"analytics.viewsLabel": "Ansichten",
|
||||
"auth.emailSubmitButton.label": "Absenden",
|
||||
"auth.error.default": "Versuche, dich mit einem anderen Konto anzumelden.",
|
||||
"auth.error.email": "E-Mail nicht gefunden. Versuche, dich mit einem anderen Anbieter anzumelden.",
|
||||
"auth.error.oauthNotLinked": "Um deine Identität zu bestätigen, melde dich mit demselben Konto an, das du ursprünglich verwendet hast.",
|
||||
"auth.error.unknown": "Ein Fehler ist aufgetreten. Bitte versuche es erneut.",
|
||||
"auth.magicLink.description": "Vergiss nicht, deinen Spam-Ordner zu überprüfen.",
|
||||
"auth.magicLink.title": "Eine E-Mail mit magischem Link wurde gesendet. \uD83E\uDE84",
|
||||
"auth.noProvider.link": "mindestens einen Authentifizierungsanbieter konfigurieren (E-Mail, Google, GitHub, Facebook oder Azure AD).",
|
||||
"auth.noProvider.preLink": "Du musst",
|
||||
"auth.orEmailLabel": "Oder mit deiner E-Mail",
|
||||
"auth.register.aggreeToTerms": "Durch die Registrierung stimmst du unseren <terms>termsOfService</terms> und <privacy>privacyPolicy</privacy> zu.",
|
||||
"auth.register.alreadyHaveAccountLabel.link": "Anmelden",
|
||||
"auth.register.alreadyHaveAccountLabel.preLink": "Bereits ein Konto vorhanden?",
|
||||
"auth.register.heading": "Konto erstellen",
|
||||
"auth.signin.heading": "Anmelden",
|
||||
"auth.signin.noAccountLabel.link": "Kostenlos anmelden",
|
||||
"auth.signin.noAccountLabel.preLink": "Noch kein Konto?",
|
||||
"auth.signinErrorToast.description": "Anmeldungen sind deaktiviert.",
|
||||
"auth.signinErrorToast.title": "Nicht autorisiert",
|
||||
"auth.signinErrorToast.tooManyRequests": "Zu viele Anfragen. Versuche es später erneut.",
|
||||
"auth.socialLogin.azureButton.label": "Mit {azureProviderName} fortfahren",
|
||||
"auth.socialLogin.customButton.label": "Mit {customProviderName} fortfahren",
|
||||
"auth.socialLogin.facebookButton.label": "Mit Facebook fortfahren",
|
||||
"auth.socialLogin.githubButton.label": "Mit GitHub fortfahren",
|
||||
"auth.socialLogin.gitlabButton.label": "Mit {gitlabProviderName} fortfahren",
|
||||
"auth.socialLogin.googleButton.label": "Mit Google fortfahren",
|
||||
"back": "Zurück",
|
||||
"billing.billingPortalButton.label": "Abrechnungsportal",
|
||||
"billing.contribution.link": "Erfahre mehr.",
|
||||
"billing.contribution.preLink": "Typebot trägt 1% deines Abonnements dazu bei, CO₂ aus der Atmosphäre zu entfernen.",
|
||||
"billing.currentSubscription.cancelDate": "Wird storniert am",
|
||||
"billing.currentSubscription.heading": "Abonnement",
|
||||
"billing.currentSubscription.pastDueAlert": "Die letzte Zahlung ist fehlgeschlagen. Gehen Sie zum Abrechnungsportal, um fortzufahren und eine Kündigung Ihres Abonnements zu vermeiden.",
|
||||
"billing.currentSubscription.subheading": "Aktuelles Workspace-Abonnement:",
|
||||
"billing.customLimit.link": "Lass uns darüber sprechen!",
|
||||
"billing.customLimit.preLink": "Brauchst du individuelle Limits? Spezielle Funktionen?",
|
||||
"billing.invoices.empty": "Keine Rechnungen für diesen Workspace gefunden.",
|
||||
"billing.invoices.heading": "Rechnungen",
|
||||
"billing.invoices.paidAt": "Bezahlt am",
|
||||
"billing.invoices.subtotal": "Zwischensumme",
|
||||
"billing.limitMessage.analytics": "Detaillierte Analysen freischalten",
|
||||
"billing.limitMessage.brand": "Branding entfernen",
|
||||
"billing.limitMessage.customDomain": "Eigene Domains hinzufügen",
|
||||
"billing.limitMessage.fileInput": "Datei-Eingabefelder verwenden",
|
||||
"billing.limitMessage.folder": "Ordner erstellen",
|
||||
"billing.preCheckoutModal.companyInput.label": "Firmenname:",
|
||||
"billing.preCheckoutModal.emailInput.label": "E-Mail:",
|
||||
"billing.preCheckoutModal.submitButton.label": "Zur Kasse gehen",
|
||||
"billing.preCheckoutModal.taxId.label": "Steuernummer:",
|
||||
"billing.preCheckoutModal.taxId.placeholder": "ID-Typ",
|
||||
"billing.pricingCard.chatsPerMonth": "Chats/Monat",
|
||||
"billing.pricingCard.chatsTooltip": "Ein Chat wird gezählt, wenn ein Benutzer eine Diskussion startet. Es ist unabhängig von der Anzahl der gesendeten und empfangenen Nachrichten.",
|
||||
"billing.pricingCard.heading": "Upgrade auf <strong>plan</strong>",
|
||||
"billing.pricingCard.perMonth": "/ Monat",
|
||||
"billing.pricingCard.plus": ", plus:",
|
||||
"billing.pricingCard.pro.analytics": "Detaillierte Analysen",
|
||||
"billing.pricingCard.pro.customDomains": "Eigene Domains",
|
||||
"billing.pricingCard.pro.description": "Für Agenturen & wachsende Start-ups.",
|
||||
"billing.pricingCard.pro.everythingFromStarter": "Alles in Starter",
|
||||
"billing.pricingCard.pro.includedSeats": "5 Plätze inklusive",
|
||||
"billing.pricingCard.pro.mostPopularLabel": "Am beliebtesten",
|
||||
"billing.pricingCard.pro.whatsAppIntegration": "WhatsApp-Integration",
|
||||
"billing.pricingCard.starter.brandingRemoved": "Branding entfernt",
|
||||
"billing.pricingCard.starter.createFolders": "Ordner erstellen",
|
||||
"billing.pricingCard.starter.description": "Für Einzelpersonen & kleine Unternehmen.",
|
||||
"billing.pricingCard.starter.fileUploadBlock": "Datei-Upload Eingabefeld",
|
||||
"billing.pricingCard.starter.includedSeats": "2 Plätze inklusive",
|
||||
"billing.pricingCard.upgradeButton.current": "Dein aktueller Tarif",
|
||||
"billing.updateSuccessToast.description": "Workspace {plan} Plan erfolgreich aktualisiert \uD83C\uDF89",
|
||||
"billing.upgradeAlert.buttonDefaultLabel": "Mehr Informationen",
|
||||
"billing.upgradeLimitLabel": "Um {type} hinzuzufügen, musst du deinen Tarif aktualisieren",
|
||||
"billing.usage.chats.alert.soonReach": "Deine Typebots sind beliebt! Du wirst bald das Chat-Limit deines Tarifs erreichen. \uD83D\uDE80",
|
||||
"billing.usage.chats.alert.updatePlan": "Vergewissere dich, dass du deinen Tarif aktualisierst, um dieses Limit zu erhöhen und weiterhin mit deinen Benutzern zu chatten.",
|
||||
"billing.usage.chats.heading": "Chats",
|
||||
"billing.usage.heading": "Nutzung",
|
||||
"billing.usage.unlimited": "Unbegrenzt",
|
||||
"cancel": "Abbrechen",
|
||||
"confirmModal.defaultTitle": "Bist du sicher?",
|
||||
"dashboard.header.settingsButton.label": "Einstellungen & Mitglieder",
|
||||
"dashboard.redirectionMessage": "Du wirst weitergeleitet...",
|
||||
"dashboard.title": "Meine Typebots",
|
||||
"delete": "Löschen",
|
||||
"downgrade": "Downgrade",
|
||||
"blocks.bubbles.embed.blockCard.tooltip": "Ein PDF, ein iframe, eine Website einbetten...",
|
||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Dateien hochladen",
|
||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Tabellen",
|
||||
"editor.blockCard.logicBlock.tooltip.code.label": "JavaScript-Code ausführen",
|
||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Ablauf zu einer anderen Gruppe beschleunigen",
|
||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Verlinkung zu einem anderen Typebot",
|
||||
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Zum Bearbeiten klicken...",
|
||||
"editor.blocks.bubbles.audio.settings.autoplay.label": "Autoplay aktivieren",
|
||||
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Datei auswählen",
|
||||
"editor.blocks.bubbles.audio.settings.embedLink.label": "Link einbetten",
|
||||
"editor.blocks.bubbles.audio.settings.upload.label": "Hochladen",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Füge den Audio-Dateilink ein...",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.text": "Funktioniert mit .MP3- und .WAV-Dateien",
|
||||
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Zum Bearbeiten klicken...",
|
||||
"editor.blocks.bubbles.embed.node.show.text": "Einbetten anzeigen",
|
||||
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Füge den Link oder Code ein...",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.text": "Funktioniert mit PDFs, iframes, Websites...",
|
||||
"editor.blocks.bubbles.image.node.clickToEdit.text": "Zum Bearbeiten klicken...",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Beim Klicken Link",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link Alternativtext (Beschreibung)",
|
||||
"editor.blocks.bubbles.textEditor.plate.label": "Texteditor",
|
||||
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Nach einer Variable suchen",
|
||||
"editor.blocks.bubbles.video.node.clickToEdit.text": "Zum Bearbeiten klicken...",
|
||||
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Füge den Videolink ein...",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.text": "Funktioniert mit YouTube, Vimeo und anderen",
|
||||
"editor.blocks.start.text": "Start",
|
||||
"editor.editableTypebotName.tooltip.rename.label": "Umbenennen",
|
||||
"editor.gettingStartedModal.editorBasics.heading": "Grundlagen des Editors",
|
||||
"editor.gettingStartedModal.editorBasics.list.four.label": "Klicke auf die Vorschau-Schaltfläche oben rechts, um deinen Bot anzusehen.",
|
||||
"editor.gettingStartedModal.editorBasics.list.label": "Wenn du Fragen hast, verwende gerne die Sprechblase unten rechts, um sie mir zu stellen. Ich beantworte normalerweise innerhalb der nächsten 24 Stunden. \uD83D\uDE03",
|
||||
"editor.gettingStartedModal.editorBasics.list.one.label": "Die Seitenleiste enthält Blöcke, die du auf das Board ziehen und ablegen kannst.",
|
||||
"editor.gettingStartedModal.editorBasics.list.three.label": "Verbinde die Gruppen miteinander.",
|
||||
"editor.gettingStartedModal.editorBasics.list.two.label": "Du kannst Blöcke gruppieren, indem du sie unter oder über einander ablegst.",
|
||||
"editor.gettingStartedModal.seeAction.item.label": "Weitere Videos",
|
||||
"editor.gettingStartedModal.seeAction.label": "In Aktion sehen",
|
||||
"editor.gettingStartedModal.seeAction.time": "5 Minuten",
|
||||
"editor.headers.flowButton.label": "Ablauf",
|
||||
"editor.headers.helpButton.label": "Hilfe",
|
||||
"editor.headers.previewButton.label": "Vorschau",
|
||||
"editor.headers.resultsButton.label": "Ergebnisse",
|
||||
"editor.headers.savingSpinner.label": "Speichern...",
|
||||
"editor.headers.settingsButton.label": "Einstellungen",
|
||||
"editor.headers.shareButton.label": "Teilen",
|
||||
"editor.headers.themeButton.label": "Design",
|
||||
"editor.sidebarBlock.abTest.label": "AB-Test",
|
||||
"editor.sidebarBlock.analytics.label": "Analytics",
|
||||
"editor.sidebarBlock.audio.label": "Audio",
|
||||
"editor.sidebarBlock.button.label": "Buttons",
|
||||
"editor.sidebarBlock.chatwoot.label": "Chatwoot",
|
||||
"editor.sidebarBlock.condition.label": "Bedingung",
|
||||
"editor.sidebarBlock.date.label": "Datum",
|
||||
"editor.sidebarBlock.email.label": "E-Mail",
|
||||
"editor.sidebarBlock.embed.label": "Einbetten",
|
||||
"editor.sidebarBlock.file.label": "Datei",
|
||||
"editor.sidebarBlock.image.label": "Bild",
|
||||
"editor.sidebarBlock.jump.label": "Springen",
|
||||
"editor.sidebarBlock.makecom.label": "Make.com",
|
||||
"editor.sidebarBlock.number.label": "Nummer",
|
||||
"editor.sidebarBlock.openai.label": "OpenAI",
|
||||
"editor.sidebarBlock.pabbly.label": "Pabbly",
|
||||
"editor.sidebarBlock.payment.label": "Zahlung",
|
||||
"editor.sidebarBlock.phone.label": "Telefon",
|
||||
"editor.sidebarBlock.picChoice.label": "Bildauswahl",
|
||||
"editor.sidebarBlock.pixel.label": "Pixel",
|
||||
"editor.sidebarBlock.rating.label": "Bewertung",
|
||||
"editor.sidebarBlock.redirect.label": "Weiterleitung",
|
||||
"editor.sidebarBlock.script.label": "Skript",
|
||||
"editor.sidebarBlock.setVariable.label": "Variable setzen",
|
||||
"editor.sidebarBlock.sheets.label": "Tabellen",
|
||||
"editor.sidebarBlock.start.label": "Start",
|
||||
"editor.sidebarBlock.text.label": "Text",
|
||||
"editor.sidebarBlock.typebot.label": "Typebot",
|
||||
"editor.sidebarBlock.video.label": "Video",
|
||||
"editor.sidebarBlock.wait.label": "Warten",
|
||||
"editor.sidebarBlock.webhook.label": "Webhook",
|
||||
"editor.sidebarBlock.website.label": "Website",
|
||||
"editor.sidebarBlock.zapier.label": "Zapier",
|
||||
"editor.sidebarBlock.zemanticAi.label": "Zemantic AI",
|
||||
"editor.sidebarBlocks.blockType.bubbles.heading": "Blasen",
|
||||
"editor.sidebarBlocks.blockType.inputs.heading": "Eingaben",
|
||||
"editor.sidebarBlocks.blockType.integrations.heading": "Integrationen",
|
||||
"editor.sidebarBlocks.blockType.logic.heading": "Logik",
|
||||
"editor.sidebarBlocks.sidebar.icon.lock.label": "Sperren",
|
||||
"editor.sidebarBlocks.sidebar.icon.unlock.label": "Entsperren",
|
||||
"editor.sidebarBlocks.sidebar.lock.label": "Seitenleiste sperren",
|
||||
"editor.sidebarBlocks.sidebar.unlock.label": "Seitenleiste entsperren",
|
||||
"errorMessage": "Ein Fehler ist aufgetreten",
|
||||
"folders.createFolderButton.label": "Ordner erstellen",
|
||||
"folders.createTypebotButton.label": "Typebot erstellen",
|
||||
"folders.folderButton.deleteConfirmationMessage": "Möchtest du den Ordner <strong>folderName</strong> wirklich löschen? (Alles im Inneren wird in dein Dashboard verschoben)",
|
||||
"folders.typebotButton.delete": "Löschen",
|
||||
"folders.typebotButton.deleteConfirmationMessage": "Möchtest du deinen Typebot <strong>typebotName</strong> wirklich löschen?",
|
||||
"folders.typebotButton.deleteConfirmationMessageWarning": "Alle zugehörigen Daten werden gelöscht und können nicht wiederhergestellt werden.",
|
||||
"folders.typebotButton.duplicate": "Duplizieren",
|
||||
"folders.typebotButton.live": "Live",
|
||||
"folders.typebotButton.showMoreOptions": "Mehr Optionen anzeigen",
|
||||
"folders.typebotButton.unpublish": "Veröffentlichung aufheben",
|
||||
"pending": "Ausstehend",
|
||||
"remove": "Entfernen",
|
||||
"skip": "Überspringen",
|
||||
"templates.buttons.fromScratchButton.label": "Von Grund auf starten",
|
||||
"templates.buttons.fromTemplateButton.label": "Von einer Vorlage starten",
|
||||
"templates.buttons.heading": "Erstelle einen neuen Typebot",
|
||||
"templates.buttons.importFileButton.label": "Datei importieren",
|
||||
"templates.importFromFileButon.toastError.description": "Konnte die Datei nicht verarbeiten. Bist du sicher, dass es sich um einen Typebot handelt?",
|
||||
"templates.modal.menuHeading.marketing": "Marketing",
|
||||
"templates.modal.menuHeading.new.tag": "Neu",
|
||||
"templates.modal.menuHeading.other": "Andere",
|
||||
"templates.modal.menuHeading.product": "Produkt",
|
||||
"templates.modal.useTemplateButton.label": "Diese Vorlage verwenden",
|
||||
"upgrade": "Upgrade",
|
||||
"workspace.dropdown.logoutButton.label": "Abmelden",
|
||||
"workspace.dropdown.newButton.label": "Neuer Workspace",
|
||||
"workspace.membersList.inviteButton.label": "Einladen",
|
||||
"workspace.membersList.inviteInput.placeholder": "name@unternehmen.de",
|
||||
"workspace.membersList.title": "Mitglieder",
|
||||
"workspace.membersList.unlockBanner.label": "Aktualisiere deinen Plan, um mit mehr Teammitgliedern zu arbeiten und neue Limits freizuschalten \uD83D\uDE80",
|
||||
"workspace.settings.deleteButton.confirmMessage": "Sind Sie sicher, dass Sie den Workspace {workspaceName} löschen möchten? Alle seine Ordner, Typebots und Ergebnisse werden dauerhaft gelöscht.",
|
||||
"workspace.settings.deleteButton.label": "Workspace löschen",
|
||||
"workspace.settings.icon.title": "Symbol",
|
||||
"workspace.settings.modal.menu.billingAndUsage.label": "Abrechnung & Nutzung",
|
||||
"workspace.settings.modal.menu.members.label": "Mitglieder",
|
||||
"workspace.settings.modal.menu.myAccount.label": "Mein Konto",
|
||||
"workspace.settings.modal.menu.preferences.label": "Einstellungen",
|
||||
"workspace.settings.modal.menu.settings.label": "Einstellungen",
|
||||
"workspace.settings.modal.menu.version.label": "Version: {version}",
|
||||
"workspace.settings.modal.menu.workspace.label": "Workspace",
|
||||
"workspace.settings.name.label": "Name:"
|
||||
}
|
252
apps/builder/public/locales/en.json
Normal file
252
apps/builder/public/locales/en.json
Normal file
@ -0,0 +1,252 @@
|
||||
{
|
||||
"account.apiTokens.createButton.label": "Create",
|
||||
"account.apiTokens.createModal.copyInstruction": "Please copy your token and store it in a safe place.",
|
||||
"account.apiTokens.createModal.createButton.label": "Create token",
|
||||
"account.apiTokens.createModal.createHeading": "Create Token",
|
||||
"account.apiTokens.createModal.createdHeading": "Token Created",
|
||||
"account.apiTokens.createModal.doneButton.label": "Done",
|
||||
"account.apiTokens.createModal.nameInput.label": "Enter a unique name for your token to differentiate it from other tokens.",
|
||||
"account.apiTokens.createModal.nameInput.placeholder": "I.e. Zapier, Github, Make.com",
|
||||
"account.apiTokens.createModal.securityWarning": "For security reasons we cannot show it again.",
|
||||
"account.apiTokens.deleteButton.label": "Delete",
|
||||
"account.apiTokens.deleteConfirmationMessage": "The token <strong>tokenName</strong> will be permanently revoked, are you sure you want to continue?",
|
||||
"account.apiTokens.description": "These tokens allow other apps to control your whole account and typebots. Be careful!",
|
||||
"account.apiTokens.heading": "API tokens",
|
||||
"account.apiTokens.table.createdHeader": "Created",
|
||||
"account.apiTokens.table.nameHeader": "Name",
|
||||
"account.myAccount.changePhotoButton.label": "Change photo",
|
||||
"account.myAccount.changePhotoButton.specification": ".jpg or.png, max 1MB",
|
||||
"account.myAccount.emailInput.disabledTooltip": "Updating email is not available. Contact the support if you want to change it.",
|
||||
"account.myAccount.emailInput.label": "Email address:",
|
||||
"account.myAccount.nameInput.label": "Name:",
|
||||
"account.preferences.appearance.darkLabel": "Dark",
|
||||
"account.preferences.appearance.heading": "Appearance",
|
||||
"account.preferences.appearance.lightLabel": "Light",
|
||||
"account.preferences.appearance.systemLabel": "System",
|
||||
"account.preferences.graphNavigation.heading": "Editor Navigation",
|
||||
"account.preferences.graphNavigation.mouse.description": "Move by dragging the board and zoom in/out using the scroll wheel",
|
||||
"account.preferences.graphNavigation.mouse.label": "Mouse",
|
||||
"account.preferences.graphNavigation.trackpad.description": "Move the board using 2 fingers and zoom in/out by pinching",
|
||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||
"account.preferences.language.heading": "Language",
|
||||
"account.preferences.language.tooltip": "The translations are not complete yet. It is a work in progress. 🤓",
|
||||
"analytics.completionRateLabel": "Completion rate",
|
||||
"analytics.notAvailableLabel": "Not available",
|
||||
"analytics.startsLabel": "Starts",
|
||||
"analytics.viewsLabel": "Views",
|
||||
"auth.emailSubmitButton.label": "Submit",
|
||||
"auth.error.default": "Try signing with a different account.",
|
||||
"auth.error.email": "Email not found. Try signing with a different provider.",
|
||||
"auth.error.oauthNotLinked": "To confirm your identity, sign in with the same account you used originally.",
|
||||
"auth.error.unknown": "An error occurred. Please try again.",
|
||||
"auth.magicLink.description": "Make sure to check your spam folder.",
|
||||
"auth.magicLink.title": "A magic link email was sent. 🪄",
|
||||
"auth.noProvider.link": "configure at least one auth provider (Email, Google, GitHub, Facebook or Azure AD).",
|
||||
"auth.noProvider.preLink": "You need to",
|
||||
"auth.orEmailLabel": "Or with your email",
|
||||
"auth.register.aggreeToTerms": "By signing up, you agree to our <terms>termsOfService</terms> and <privacy>privacyPolicy</privacy>.",
|
||||
"auth.register.alreadyHaveAccountLabel.link": "Sign in",
|
||||
"auth.register.alreadyHaveAccountLabel.preLink": "Already have an account?",
|
||||
"auth.register.heading": "Create an account",
|
||||
"auth.signin.heading": "Sign In",
|
||||
"auth.signin.noAccountLabel.link": "Sign up for free",
|
||||
"auth.signin.noAccountLabel.preLink": "Don't have an account?",
|
||||
"auth.signinErrorToast.description": "Sign ups are disabled.",
|
||||
"auth.signinErrorToast.title": "Unauthorized",
|
||||
"auth.signinErrorToast.tooManyRequests": "Too many requests. Try again later.",
|
||||
"auth.socialLogin.azureButton.label": "Continue with {azureProviderName}",
|
||||
"auth.socialLogin.customButton.label": "Continue with {customProviderName}",
|
||||
"auth.socialLogin.facebookButton.label": "Continue with Facebook",
|
||||
"auth.socialLogin.githubButton.label": "Continue with GitHub",
|
||||
"auth.socialLogin.gitlabButton.label": "Continue with {gitlabProviderName}",
|
||||
"auth.socialLogin.googleButton.label": "Continue with Google",
|
||||
"back": "Back",
|
||||
"billing.billingPortalButton.label": "Billing portal",
|
||||
"billing.contribution.link": "Learn more.",
|
||||
"billing.contribution.preLink": "Typebot is contributing 1% of your subscription to remove CO₂ from the atmosphere.",
|
||||
"billing.currentSubscription.cancelDate": "Will be cancelled on",
|
||||
"billing.currentSubscription.heading": "Subscription",
|
||||
"billing.currentSubscription.pastDueAlert": "The latest payment failed. Head over to the billing portal to proceed and avoid having your subscription canceled.",
|
||||
"billing.currentSubscription.subheading": "Current workspace subscription:",
|
||||
"billing.customLimit.link": "Let's chat!",
|
||||
"billing.customLimit.preLink": "Need custom limits? Specific features?",
|
||||
"billing.invoices.empty": "No invoices found for this workspace.",
|
||||
"billing.invoices.heading": "Invoices",
|
||||
"billing.invoices.paidAt": "Paid at",
|
||||
"billing.invoices.subtotal": "Subtotal",
|
||||
"billing.limitMessage.analytics": "unlock in-depth analytics",
|
||||
"billing.limitMessage.brand": "remove branding",
|
||||
"billing.limitMessage.customDomain": "add custom domains",
|
||||
"billing.limitMessage.fileInput": "use file input blocks",
|
||||
"billing.limitMessage.folder": "create folders",
|
||||
"billing.preCheckoutModal.companyInput.label": "Company name:",
|
||||
"billing.preCheckoutModal.emailInput.label": "Email:",
|
||||
"billing.preCheckoutModal.submitButton.label": "Go to checkout",
|
||||
"billing.preCheckoutModal.taxId.label": "Tax ID:",
|
||||
"billing.preCheckoutModal.taxId.placeholder": "ID type",
|
||||
"billing.pricingCard.chatsPerMonth": "chats/mo",
|
||||
"billing.pricingCard.chatsTooltip": "A chat is counted whenever a user starts a discussion. It is independant of the number of messages he sends and receives.",
|
||||
"billing.pricingCard.heading": "Upgrade to <strong>plan</strong>",
|
||||
"billing.pricingCard.perMonth": "/ month",
|
||||
"billing.pricingCard.plus": ", plus:",
|
||||
"billing.pricingCard.pro.analytics": "In-depth analytics",
|
||||
"billing.pricingCard.pro.customDomains": "Custom domains",
|
||||
"billing.pricingCard.pro.description": "For agencies & growing startups.",
|
||||
"billing.pricingCard.pro.everythingFromStarter": "Everything in Starter",
|
||||
"billing.pricingCard.pro.includedSeats": "5 seats included",
|
||||
"billing.pricingCard.pro.mostPopularLabel": "Most popular",
|
||||
"billing.pricingCard.pro.whatsAppIntegration": "WhatsApp integration",
|
||||
"billing.pricingCard.starter.brandingRemoved": "Branding removed",
|
||||
"billing.pricingCard.starter.createFolders": "Create folders",
|
||||
"billing.pricingCard.starter.description": "For individuals & small businesses.",
|
||||
"billing.pricingCard.starter.fileUploadBlock": "File upload input block",
|
||||
"billing.pricingCard.starter.includedSeats": "2 seats included",
|
||||
"billing.pricingCard.upgradeButton.current": "Your current plan",
|
||||
"billing.updateSuccessToast.description": "Workspace {plan} plan successfully updated 🎉",
|
||||
"billing.upgradeAlert.buttonDefaultLabel": "More info",
|
||||
"billing.upgradeLimitLabel": "You need to upgrade your plan in order to {type}",
|
||||
"billing.usage.chats.alert.soonReach": "Your typebots are popular! You will soon reach your plan's chats limit. 🚀",
|
||||
"billing.usage.chats.alert.updatePlan": "Make sure to update your plan to increase this limit and continue chatting with your users.",
|
||||
"billing.usage.chats.heading": "Chats",
|
||||
"billing.usage.heading": "Usage",
|
||||
"billing.usage.unlimited": "Unlimited",
|
||||
"cancel": "Cancel",
|
||||
"confirmModal.defaultTitle": "Are you sure?",
|
||||
"dashboard.header.settingsButton.label": "Settings & Members",
|
||||
"dashboard.redirectionMessage": "You are being redirected...",
|
||||
"dashboard.title": "My typebots",
|
||||
"delete": "Delete",
|
||||
"downgrade": "Downgrade",
|
||||
"blocks.bubbles.embed.blockCard.tooltip": "Embed a pdf, an iframe, a website...",
|
||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Upload Files",
|
||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
||||
"editor.blockCard.logicBlock.tooltip.code.label": "Execute Javascript code",
|
||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Fast forward the flow to another group",
|
||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link and jump to another typebot",
|
||||
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Click to edit...",
|
||||
"editor.blocks.bubbles.audio.settings.autoplay.label": "Enable autoplay",
|
||||
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Choose a file",
|
||||
"editor.blocks.bubbles.audio.settings.embedLink.label": "Embed link",
|
||||
"editor.blocks.bubbles.audio.settings.upload.label": "Upload",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Paste the audio file link...",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.text": "Works with .MP3s and .WAVs",
|
||||
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Click to edit...",
|
||||
"editor.blocks.bubbles.embed.node.show.text": "Show embed",
|
||||
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Paste the link or code...",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.text": "Works with PDFs, iframes, websites...",
|
||||
"editor.blocks.bubbles.image.node.clickToEdit.text": "Click to edit...",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "On click link",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Link alt text (description)",
|
||||
"editor.blocks.bubbles.textEditor.plate.label": "Text editor",
|
||||
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Search for a variable",
|
||||
"editor.blocks.bubbles.video.node.clickToEdit.text": "Click to edit...",
|
||||
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Paste the video link...",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.text": "Works with Youtube, Vimeo and others",
|
||||
"editor.blocks.start.text": "Start",
|
||||
"editor.editableTypebotName.tooltip.rename.label": "Rename",
|
||||
"editor.gettingStartedModal.editorBasics.heading": "Editor Basics",
|
||||
"editor.gettingStartedModal.editorBasics.list.four.label": "Preview your bot by clicking the preview button on the top right",
|
||||
"editor.gettingStartedModal.editorBasics.list.label": "Feel free to use the bottom-right bubble to reach out if you have any question. I usually answer within the next 24 hours. 😃",
|
||||
"editor.gettingStartedModal.editorBasics.list.one.label": "The left side bar contains blocks that you can drag and drop to the board.",
|
||||
"editor.gettingStartedModal.editorBasics.list.three.label": "Connect the groups together",
|
||||
"editor.gettingStartedModal.editorBasics.list.two.label": "You can group blocks together by dropping them below or above each other",
|
||||
"editor.gettingStartedModal.seeAction.item.label": "Other videos",
|
||||
"editor.gettingStartedModal.seeAction.label": "See it in action",
|
||||
"editor.gettingStartedModal.seeAction.time": "5 minutes",
|
||||
"editor.headers.flowButton.label": "Flow",
|
||||
"editor.headers.helpButton.label": "Help",
|
||||
"editor.headers.previewButton.label": "Preview",
|
||||
"editor.headers.resultsButton.label": "Results",
|
||||
"editor.headers.savingSpinner.label": "Saving...",
|
||||
"editor.headers.settingsButton.label": "Settings",
|
||||
"editor.headers.shareButton.label": "Share",
|
||||
"editor.headers.themeButton.label": "Theme",
|
||||
"editor.sidebarBlock.abTest.label": "AB Test",
|
||||
"editor.sidebarBlock.analytics.label": "Analytics",
|
||||
"editor.sidebarBlock.audio.label": "Audio",
|
||||
"editor.sidebarBlock.button.label": "Buttons",
|
||||
"editor.sidebarBlock.chatwoot.label": "Chatwoot",
|
||||
"editor.sidebarBlock.condition.label": "Condition",
|
||||
"editor.sidebarBlock.date.label": "Date",
|
||||
"editor.sidebarBlock.email.label": "Email",
|
||||
"editor.sidebarBlock.embed.label": "Embed",
|
||||
"editor.sidebarBlock.file.label": "File",
|
||||
"editor.sidebarBlock.image.label": "Image",
|
||||
"editor.sidebarBlock.jump.label": "Jump",
|
||||
"editor.sidebarBlock.makecom.label": "Make.com",
|
||||
"editor.sidebarBlock.number.label": "Number",
|
||||
"editor.sidebarBlock.openai.label": "OpenAI",
|
||||
"editor.sidebarBlock.pabbly.label": "Pabbly",
|
||||
"editor.sidebarBlock.payment.label": "Payment",
|
||||
"editor.sidebarBlock.phone.label": "Phone",
|
||||
"editor.sidebarBlock.picChoice.label": "Pic choice",
|
||||
"editor.sidebarBlock.pixel.label": "Pixel",
|
||||
"editor.sidebarBlock.rating.label": "Rating",
|
||||
"editor.sidebarBlock.redirect.label": "Redirect",
|
||||
"editor.sidebarBlock.script.label": "Script",
|
||||
"editor.sidebarBlock.setVariable.label": "Set variable",
|
||||
"editor.sidebarBlock.sheets.label": "Sheets",
|
||||
"editor.sidebarBlock.start.label": "Start",
|
||||
"editor.sidebarBlock.text.label": "Text",
|
||||
"editor.sidebarBlock.typebot.label": "Typebot",
|
||||
"editor.sidebarBlock.video.label": "Video",
|
||||
"editor.sidebarBlock.wait.label": "Wait",
|
||||
"editor.sidebarBlock.webhook.label": "Webhook",
|
||||
"editor.sidebarBlock.website.label": "Website",
|
||||
"editor.sidebarBlock.zapier.label": "Zapier",
|
||||
"editor.sidebarBlock.zemanticAi.label": "Zemantic AI",
|
||||
"editor.sidebarBlocks.blockType.bubbles.heading": "Bubbles",
|
||||
"editor.sidebarBlocks.blockType.inputs.heading": "Inputs",
|
||||
"editor.sidebarBlocks.blockType.integrations.heading": "Integrations",
|
||||
"editor.sidebarBlocks.blockType.logic.heading": "Logic",
|
||||
"editor.sidebarBlocks.sidebar.icon.lock.label": "Lock",
|
||||
"editor.sidebarBlocks.sidebar.icon.unlock.label": "Unlock",
|
||||
"editor.sidebarBlocks.sidebar.lock.label": "Lock sidebar",
|
||||
"editor.sidebarBlocks.sidebar.unlock.label": "Unlock sidebar",
|
||||
"errorMessage": "An error occured",
|
||||
"folders.createFolderButton.label": "Create a folder",
|
||||
"folders.createTypebotButton.label": "Create a typebot",
|
||||
"folders.folderButton.deleteConfirmationMessage": "Are you sure you want to delete <strong>folderName</strong> folder? (Everything inside will be move to your dashboard)",
|
||||
"folders.typebotButton.delete": "Delete",
|
||||
"folders.typebotButton.deleteConfirmationMessage": "Are you sure you want to delete your typebot <strong>typebotName</strong>?",
|
||||
"folders.typebotButton.deleteConfirmationMessageWarning": "All its associated data will be deleted and won't be recoverable.",
|
||||
"folders.typebotButton.duplicate": "Duplicate",
|
||||
"folders.typebotButton.live": "Live",
|
||||
"folders.typebotButton.showMoreOptions": "Show more options",
|
||||
"folders.typebotButton.unpublish": "Unpublish",
|
||||
"pending": "Pending",
|
||||
"remove": "Remove",
|
||||
"skip": "Skip",
|
||||
"templates.buttons.fromScratchButton.label": "Start from scratch",
|
||||
"templates.buttons.fromTemplateButton.label": "Start from a template",
|
||||
"templates.buttons.heading": "Create a new typebot",
|
||||
"templates.buttons.importFileButton.label": "Import a file",
|
||||
"templates.importFromFileButon.toastError.description": "Failed to parse the file. Are you sure it's a typebot?",
|
||||
"templates.modal.menuHeading.marketing": "Marketing",
|
||||
"templates.modal.menuHeading.new.tag": "New",
|
||||
"templates.modal.menuHeading.other": "Other",
|
||||
"templates.modal.menuHeading.product": "Product",
|
||||
"templates.modal.useTemplateButton.label": "Use this template",
|
||||
"upgrade": "Upgrade",
|
||||
"workspace.dropdown.logoutButton.label": "Log out",
|
||||
"workspace.dropdown.newButton.label": "New workspace",
|
||||
"workspace.membersList.inviteButton.label": "Invite",
|
||||
"workspace.membersList.inviteInput.placeholder": "colleague@company.com",
|
||||
"workspace.membersList.title": "Members",
|
||||
"workspace.membersList.unlockBanner.label": "Upgrade your plan to work with more team members, and unlock awesome power features 🚀",
|
||||
"workspace.settings.deleteButton.confirmMessage": "Are you sure you want to delete {workspaceName} workspace? All its folders, typebots and results will be deleted forever.",
|
||||
"workspace.settings.deleteButton.label": "Delete workspace",
|
||||
"workspace.settings.icon.title": "Icon",
|
||||
"workspace.settings.modal.menu.billingAndUsage.label": "Billing & Usage",
|
||||
"workspace.settings.modal.menu.members.label": "Members",
|
||||
"workspace.settings.modal.menu.myAccount.label": "My account",
|
||||
"workspace.settings.modal.menu.preferences.label": "Preferences",
|
||||
"workspace.settings.modal.menu.settings.label": "Settings",
|
||||
"workspace.settings.modal.menu.version.label": "Version: {version}",
|
||||
"workspace.settings.modal.menu.workspace.label": "Workspace",
|
||||
"workspace.settings.name.label": "Name:",
|
||||
"billing.tiersModal.heading": "Chats pricing table"
|
||||
}
|
251
apps/builder/public/locales/fr.json
Normal file
251
apps/builder/public/locales/fr.json
Normal file
@ -0,0 +1,251 @@
|
||||
{
|
||||
"account.apiTokens.createButton.label": "Créer",
|
||||
"account.apiTokens.createModal.copyInstruction": "Copie ton token et enregistre le dans un endroit sûr.",
|
||||
"account.apiTokens.createModal.createButton.label": "Créer un token",
|
||||
"account.apiTokens.createModal.createHeading": "Créer un token",
|
||||
"account.apiTokens.createModal.createdHeading": "Token créé",
|
||||
"account.apiTokens.createModal.doneButton.label": "Terminé",
|
||||
"account.apiTokens.createModal.nameInput.label": "Tape un nom unique pour votre token afin de le différencier des autres tokens.",
|
||||
"account.apiTokens.createModal.nameInput.placeholder": "Ex. Zapier, Github, Make.com",
|
||||
"account.apiTokens.createModal.securityWarning": "Pour des raisons de sécurité, nous ne pourrons pas le montrer à nouveau.",
|
||||
"account.apiTokens.deleteButton.label": "Supprimer",
|
||||
"account.apiTokens.deleteConfirmationMessage": "Le token <strong>tokenName</strong> sera définitivement révoqué, es-tu sûr de vouloir continuer ?",
|
||||
"account.apiTokens.description": "Ces tokens permettent à d'autres applications de contrôler ton compte et tes typebots. Prudence !",
|
||||
"account.apiTokens.heading": "Tokens API",
|
||||
"account.apiTokens.table.createdHeader": "Créé",
|
||||
"account.apiTokens.table.nameHeader": "Nom",
|
||||
"account.myAccount.changePhotoButton.label": "Changer de photo",
|
||||
"account.myAccount.changePhotoButton.specification": ".jpg ou.png, max 1MB",
|
||||
"account.myAccount.emailInput.disabledTooltip": "La mise à jour de l'adresse e-mail n'est pas disponible. Contacte le service d'assistance si tu souhaites la modifier.",
|
||||
"account.myAccount.emailInput.label": "Adresse e-mail:",
|
||||
"account.myAccount.nameInput.label": "Nom:",
|
||||
"account.preferences.appearance.darkLabel": "Sombre",
|
||||
"account.preferences.appearance.heading": "Apparence",
|
||||
"account.preferences.appearance.lightLabel": "Clair",
|
||||
"account.preferences.appearance.systemLabel": "Système",
|
||||
"account.preferences.graphNavigation.heading": "Navigation de l'éditeur",
|
||||
"account.preferences.graphNavigation.mouse.description": "Déplace le board en cliquant avec la souris et zoom utilisant la molette",
|
||||
"account.preferences.graphNavigation.mouse.label": "Souris",
|
||||
"account.preferences.graphNavigation.trackpad.description": "Déplace le board en déplaçant les 2 doigts et zoom pincant",
|
||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||
"account.preferences.language.heading": "Langue",
|
||||
"account.preferences.language.tooltip": "Les traductions ne sont pas encore complètes. C'est un travail en cours. \uD83E\uDD13",
|
||||
"analytics.completionRateLabel": "Taux de complétion",
|
||||
"analytics.notAvailableLabel": "Non disponible",
|
||||
"analytics.startsLabel": "Démarrés",
|
||||
"analytics.viewsLabel": "Vues",
|
||||
"auth.emailSubmitButton.label": "Se connecter",
|
||||
"auth.error.default": "Essaye de te connecter avec un compte différent.",
|
||||
"auth.error.email": "Email non trouvé. Essaye de te connecter avec un fournisseur différent.",
|
||||
"auth.error.oauthNotLinked": "Pour confirmer ton identité, connecte-toi avec le même compte que tu as utilisé à lorigine.",
|
||||
"auth.error.unknown": "Une erreur est survenue. Essaye à nouveau.",
|
||||
"auth.magicLink.description": "N'oublie pas de vérifier ton dossier spam.",
|
||||
"auth.magicLink.title": "Un email avec un lien d'authentification a été envoyé. \uD83E\uDE84",
|
||||
"auth.noProvider.link": "configurer au moins un fournisseur d'authentification (E-mail, Google, GitHub, Facebook ou Azure AD).",
|
||||
"auth.noProvider.preLink": "Tu as besoin de",
|
||||
"auth.orEmailLabel": "Ou avec votre email",
|
||||
"auth.register.aggreeToTerms": "En vous inscrivant, vous acceptez nos <terms>termsOfService</terms> et <privacy>privacyPolicy</privacy>.",
|
||||
"auth.register.alreadyHaveAccountLabel.link": "Se connecter",
|
||||
"auth.register.alreadyHaveAccountLabel.preLink": "Tu as déjà un compte?",
|
||||
"auth.register.heading": "Créer un compte",
|
||||
"auth.signin.heading": "Se connecter",
|
||||
"auth.signin.noAccountLabel.link": "Inscris-toi gratuitement",
|
||||
"auth.signin.noAccountLabel.preLink": "Tu n'as pas de compte?",
|
||||
"auth.signinErrorToast.description": "Les inscriptions sont désactivées.",
|
||||
"auth.signinErrorToast.title": "Non autorisé",
|
||||
"auth.signinErrorToast.tooManyRequests": "Trop de tentatives de connexion.",
|
||||
"auth.socialLogin.azureButton.label": "Continuer avec {azureProviderName}",
|
||||
"auth.socialLogin.customButton.label": "Continuer avec {customProviderName}",
|
||||
"auth.socialLogin.facebookButton.label": "Continuer avec Facebook",
|
||||
"auth.socialLogin.githubButton.label": "Continuer avec GitHub",
|
||||
"auth.socialLogin.gitlabButton.label": "Continuer avec {gitlabProviderName}",
|
||||
"auth.socialLogin.googleButton.label": "Continuer avec Google",
|
||||
"back": "Retour",
|
||||
"billing.billingPortalButton.label": "Portail de facturation",
|
||||
"billing.contribution.link": "En savoir plus.",
|
||||
"billing.contribution.preLink": "Typebot contribue à hauteur de 1% de votre abonnement pour éliminer le CO₂ de l'atmosphère.",
|
||||
"billing.currentSubscription.cancelDate": "Sera annulé le",
|
||||
"billing.currentSubscription.heading": "Abonnement",
|
||||
"billing.currentSubscription.pastDueAlert": "Le dernier paiement a échoué. Rendez-vous sur le portail de facturation pour effectuer la procédure et éviter l'annulation de votre abonnement.",
|
||||
"billing.currentSubscription.subheading": "Abonnement actuel du workspace :",
|
||||
"billing.customLimit.link": "Discutons-en!",
|
||||
"billing.customLimit.preLink": "Tu as besoin de limites personnalisées ? De fonctionnalités spécifiques ?",
|
||||
"billing.invoices.empty": "Aucune facture trouvée pour ce workspace.",
|
||||
"billing.invoices.heading": "Factures",
|
||||
"billing.invoices.paidAt": "Payé le",
|
||||
"billing.invoices.subtotal": "Sous-total",
|
||||
"billing.limitMessage.analytics": "débloquer des analyses approfondies",
|
||||
"billing.limitMessage.brand": "supprimer la marque",
|
||||
"billing.limitMessage.customDomain": "ajouter des domaines personnalisés",
|
||||
"billing.limitMessage.fileInput": "utiliser des blocs de saisie de fichiers",
|
||||
"billing.limitMessage.folder": "créer des dossiers",
|
||||
"billing.preCheckoutModal.companyInput.label": "Nom de l'entreprise :",
|
||||
"billing.preCheckoutModal.emailInput.label": "E-mail :",
|
||||
"billing.preCheckoutModal.submitButton.label": "Continuer",
|
||||
"billing.preCheckoutModal.taxId.label": "Numéro de TVA :",
|
||||
"billing.preCheckoutModal.taxId.placeholder": "Type",
|
||||
"billing.pricingCard.chatsPerMonth": "chats/mois",
|
||||
"billing.pricingCard.chatsTooltip": "Un chat est comptabilisé chaque fois qu'un utilisateur démarre une discussion. Il est indépendant du nombre de messages qu'il envoie et reçoit.",
|
||||
"billing.pricingCard.heading": "Passer à <strong>plan</strong>",
|
||||
"billing.pricingCard.perMonth": "/ mois",
|
||||
"billing.pricingCard.plus": ", plus :",
|
||||
"billing.pricingCard.pro.analytics": "Analyses approfondies",
|
||||
"billing.pricingCard.pro.customDomains": "Domaines personnalisés",
|
||||
"billing.pricingCard.pro.description": "Pour les agences et les startups en croissance.",
|
||||
"billing.pricingCard.pro.everythingFromStarter": "Tout ce qu'il y a dans Starter",
|
||||
"billing.pricingCard.pro.includedSeats": "5 collègues inclus",
|
||||
"billing.pricingCard.pro.mostPopularLabel": "Le plus populaire",
|
||||
"billing.pricingCard.pro.whatsAppIntegration": "Intégration WhatsApp",
|
||||
"billing.pricingCard.starter.brandingRemoved": "Marque enlevée",
|
||||
"billing.pricingCard.starter.createFolders": "Créer des dossiers",
|
||||
"billing.pricingCard.starter.description": "Pour les particuliers et les petites entreprises.",
|
||||
"billing.pricingCard.starter.fileUploadBlock": "Bloc d'upload de fichier",
|
||||
"billing.pricingCard.starter.includedSeats": "2 collègues inclus",
|
||||
"billing.pricingCard.upgradeButton.current": "Abonnement actuel",
|
||||
"billing.updateSuccessToast.description": "Ton abonnement {plan} a été mis à jour avec succès \uD83C\uDF89",
|
||||
"billing.upgradeAlert.buttonDefaultLabel": "Plus d'informations",
|
||||
"billing.upgradeLimitLabel": "Tu dois mettre à niveau ton abonnement pour {type}",
|
||||
"billing.usage.chats.alert.soonReach": "Tes typebots sont populaires ! Tu atteindras bientôt la limite de chats de votre abonnement. \uD83D\uDE80",
|
||||
"billing.usage.chats.alert.updatePlan": "Assure-toi de mettre à jour votre abonnement pour augmenter cette limite et continuer à discuter avec vos utilisateurs.",
|
||||
"billing.usage.chats.heading": "Chats",
|
||||
"billing.usage.heading": "Utilisation",
|
||||
"billing.usage.unlimited": "Illimité",
|
||||
"cancel": "Annuler",
|
||||
"confirmModal.defaultTitle": "Es-tu sûr ?",
|
||||
"dashboard.header.settingsButton.label": "Paramètres & Membres",
|
||||
"dashboard.redirectionMessage": "Redirection en cours...",
|
||||
"dashboard.title": "Mes typebots",
|
||||
"delete": "Supprimer",
|
||||
"downgrade": "Downgrade",
|
||||
"blocks.bubbles.embed.blockCard.tooltip": "Intégrer un pdf, un iframe, un site web...",
|
||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Télécharger des fichiers",
|
||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
||||
"editor.blockCard.logicBlock.tooltip.code.label": "Exécuter du code Javascript",
|
||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Passer rapidement au groupe suivant",
|
||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Lier et exécuter un autre typebot",
|
||||
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Cliquez pour modifier...",
|
||||
"editor.blocks.bubbles.audio.settings.autoplay.label": "Activer la lecture automatique",
|
||||
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Choisir un fichier",
|
||||
"editor.blocks.bubbles.audio.settings.embedLink.label": "Lien intégré",
|
||||
"editor.blocks.bubbles.audio.settings.upload.label": "Uploader",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Collez le lien du fichier audio...",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.text": "Fonctionne avec les fichiers .MP3 et .WAV",
|
||||
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Cliquez pour modifier...",
|
||||
"editor.blocks.bubbles.embed.node.show.text": "Afficher l'intégration",
|
||||
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Collez le lien ou le code...",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.text": "Fonctionne avec les PDF, les iframes, les sites web...",
|
||||
"editor.blocks.bubbles.image.node.clickToEdit.text": "Cliquez pour modifier...",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Redirection au clic",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texte alternatif du lien (description)",
|
||||
"editor.blocks.bubbles.textEditor.plate.label": "Éditeur de texte",
|
||||
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Rechercher une variable",
|
||||
"editor.blocks.bubbles.video.node.clickToEdit.text": "Cliquez pour modifier...",
|
||||
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Collez le lien de la vidéo...",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.text": "Fonctionne avec Youtube, Vimeo et autres",
|
||||
"editor.blocks.start.text": "Démarrer",
|
||||
"editor.editableTypebotName.tooltip.rename.label": "Renommer",
|
||||
"editor.gettingStartedModal.editorBasics.heading": "Principes de base de l'éditeur",
|
||||
"editor.gettingStartedModal.editorBasics.list.four.label": "Prévisualisez votre bot en cliquant sur le bouton \"Tester\" en haut à droite.",
|
||||
"editor.gettingStartedModal.editorBasics.list.label": "N'hésitez pas à utiliser la bulle en bas à droite pour me poser des questions. Je réponds généralement dans les 24 heures. \uD83D\uDE03",
|
||||
"editor.gettingStartedModal.editorBasics.list.one.label": "La barre latérale de gauche contient des blocs que vous pouvez glisser-déposer sur le graph.",
|
||||
"editor.gettingStartedModal.editorBasics.list.three.label": "Connectez les groupes ensemble.",
|
||||
"editor.gettingStartedModal.editorBasics.list.two.label": "Vous pouvez regrouper les blocs en les déposant les uns au-dessus ou en-dessous des autres.",
|
||||
"editor.gettingStartedModal.seeAction.item.label": "Autres vidéos",
|
||||
"editor.gettingStartedModal.seeAction.label": "Voir en action",
|
||||
"editor.gettingStartedModal.seeAction.time": "5 minutes",
|
||||
"editor.headers.flowButton.label": "Flow",
|
||||
"editor.headers.helpButton.label": "Aide",
|
||||
"editor.headers.previewButton.label": "Tester",
|
||||
"editor.headers.resultsButton.label": "Résultats",
|
||||
"editor.headers.savingSpinner.label": "Enregistrement...",
|
||||
"editor.headers.settingsButton.label": "Paramètres",
|
||||
"editor.headers.shareButton.label": "Partage",
|
||||
"editor.headers.themeButton.label": "Thème",
|
||||
"editor.sidebarBlock.abTest.label": "AB Test",
|
||||
"editor.sidebarBlock.analytics.label": "Analytics",
|
||||
"editor.sidebarBlock.audio.label": "Audio",
|
||||
"editor.sidebarBlock.button.label": "Boutons",
|
||||
"editor.sidebarBlock.chatwoot.label": "Chatwoot",
|
||||
"editor.sidebarBlock.condition.label": "Condition",
|
||||
"editor.sidebarBlock.date.label": "Date",
|
||||
"editor.sidebarBlock.email.label": "Email",
|
||||
"editor.sidebarBlock.embed.label": "Iframe",
|
||||
"editor.sidebarBlock.file.label": "Fichier",
|
||||
"editor.sidebarBlock.image.label": "Image",
|
||||
"editor.sidebarBlock.jump.label": "Sauter",
|
||||
"editor.sidebarBlock.makecom.label": "Make.com",
|
||||
"editor.sidebarBlock.number.label": "Nombre",
|
||||
"editor.sidebarBlock.openai.label": "OpenAI",
|
||||
"editor.sidebarBlock.pabbly.label": "Pabbly",
|
||||
"editor.sidebarBlock.payment.label": "Paiement",
|
||||
"editor.sidebarBlock.phone.label": "Téléphone",
|
||||
"editor.sidebarBlock.picChoice.label": "Choix image",
|
||||
"editor.sidebarBlock.pixel.label": "Pixel",
|
||||
"editor.sidebarBlock.rating.label": "Évaluation",
|
||||
"editor.sidebarBlock.redirect.label": "Rediriger",
|
||||
"editor.sidebarBlock.script.label": "Script",
|
||||
"editor.sidebarBlock.setVariable.label": "Définir variable",
|
||||
"editor.sidebarBlock.sheets.label": "Sheets",
|
||||
"editor.sidebarBlock.start.label": "Démarrer",
|
||||
"editor.sidebarBlock.text.label": "Texte",
|
||||
"editor.sidebarBlock.typebot.label": "Typebot",
|
||||
"editor.sidebarBlock.video.label": "Vidéo",
|
||||
"editor.sidebarBlock.wait.label": "Attendre",
|
||||
"editor.sidebarBlock.webhook.label": "Webhook",
|
||||
"editor.sidebarBlock.website.label": "Site web",
|
||||
"editor.sidebarBlock.zapier.label": "Zapier",
|
||||
"editor.sidebarBlock.zemanticAi.label": "Zemantic AI",
|
||||
"editor.sidebarBlocks.blockType.bubbles.heading": "Bulles",
|
||||
"editor.sidebarBlocks.blockType.inputs.heading": "Inputs",
|
||||
"editor.sidebarBlocks.blockType.integrations.heading": "Intégrations",
|
||||
"editor.sidebarBlocks.blockType.logic.heading": "Logique",
|
||||
"editor.sidebarBlocks.sidebar.icon.lock.label": "Fermée",
|
||||
"editor.sidebarBlocks.sidebar.icon.unlock.label": "Ouverte",
|
||||
"editor.sidebarBlocks.sidebar.lock.label": "Fermer la barre latérale",
|
||||
"editor.sidebarBlocks.sidebar.unlock.label": "Ouvrir la barre latérale",
|
||||
"errorMessage": "Une erreur s'est produite",
|
||||
"folders.createFolderButton.label": "Créer un dossier",
|
||||
"folders.createTypebotButton.label": "Créer un typebot",
|
||||
"folders.folderButton.deleteConfirmationMessage": "Es-tu sûr de vouloir supprimer le dossier <strong>folderName</strong> ? (Tout ce qui est à l'intérieur sera déplacé dans le dossier parent ou sur votre tableau de bord)",
|
||||
"folders.typebotButton.delete": "Supprimer",
|
||||
"folders.typebotButton.deleteConfirmationMessage": "Es-tu sûr de vouloir supprimer votre typebot <strong>typebotName</strong> ?",
|
||||
"folders.typebotButton.deleteConfirmationMessageWarning": "Toutes les données associées seront supprimées et ne pourront pas être récupérées.",
|
||||
"folders.typebotButton.duplicate": "Dupliquer",
|
||||
"folders.typebotButton.live": "Live",
|
||||
"folders.typebotButton.showMoreOptions": "Afficher plus d'options",
|
||||
"folders.typebotButton.unpublish": "Dépublier",
|
||||
"pending": "En attente",
|
||||
"remove": "Retirer",
|
||||
"skip": "Passer",
|
||||
"templates.buttons.fromScratchButton.label": "Commencer à partir de zéro",
|
||||
"templates.buttons.fromTemplateButton.label": "Commencer à partir d'un modèle",
|
||||
"templates.buttons.heading": "Créer un nouveau typebot",
|
||||
"templates.buttons.importFileButton.label": "Importer un fichier",
|
||||
"templates.importFromFileButon.toastError.description": "Échec de l'analyse du fichier. Es-tu sûr que c'est un typebot ?",
|
||||
"templates.modal.menuHeading.marketing": "Marketing",
|
||||
"templates.modal.menuHeading.new.tag": "Nouveau",
|
||||
"templates.modal.menuHeading.other": "Autre",
|
||||
"templates.modal.menuHeading.product": "Produit",
|
||||
"templates.modal.useTemplateButton.label": "Utiliser ce modèle",
|
||||
"upgrade": "Upgrade",
|
||||
"workspace.dropdown.logoutButton.label": "Déconnexion",
|
||||
"workspace.dropdown.newButton.label": "Nouveau workspace",
|
||||
"workspace.membersList.inviteButton.label": "Inviter",
|
||||
"workspace.membersList.inviteInput.placeholder": "collegue@entreprise.fr",
|
||||
"workspace.membersList.title": "Membres",
|
||||
"workspace.membersList.unlockBanner.label": "Upgrade ton plan pour travailler les membres de ton équipe et débloquer d'autres fonctionnalités puissantes \uD83D\uDE80",
|
||||
"workspace.settings.deleteButton.confirmMessage": "Es-tu sûr(e) de vouloir supprimer le workspace {workspaceName} ? Tous ses dossiers, typebots et résultats seront supprimés pour toujours.",
|
||||
"workspace.settings.deleteButton.label": "Supprimer le workspace",
|
||||
"workspace.settings.icon.title": "Icône",
|
||||
"workspace.settings.modal.menu.billingAndUsage.label": "Facturation et utilisation",
|
||||
"workspace.settings.modal.menu.members.label": "Membres",
|
||||
"workspace.settings.modal.menu.myAccount.label": "Mon compte",
|
||||
"workspace.settings.modal.menu.preferences.label": "Préférences",
|
||||
"workspace.settings.modal.menu.settings.label": "Paramètres",
|
||||
"workspace.settings.modal.menu.version.label": "Version : {version}",
|
||||
"workspace.settings.modal.menu.workspace.label": "Workspace",
|
||||
"workspace.settings.name.label": "Nom:"
|
||||
}
|
251
apps/builder/public/locales/pt-BR.json
Normal file
251
apps/builder/public/locales/pt-BR.json
Normal file
@ -0,0 +1,251 @@
|
||||
{
|
||||
"account.apiTokens.createButton.label": "Criar",
|
||||
"account.apiTokens.createModal.copyInstruction": "Por favor, copie seu token e guarde-o em um lugar seguro.",
|
||||
"account.apiTokens.createModal.createButton.label": "Criar token",
|
||||
"account.apiTokens.createModal.createHeading": "Criar Token",
|
||||
"account.apiTokens.createModal.createdHeading": "Token Criado",
|
||||
"account.apiTokens.createModal.doneButton.label": "Concluído",
|
||||
"account.apiTokens.createModal.nameInput.label": "Insira um nome único para o seu token para diferenciá-lo de outros tokens.",
|
||||
"account.apiTokens.createModal.nameInput.placeholder": "Ex. Zapier, Github, Make.com",
|
||||
"account.apiTokens.createModal.securityWarning": "Por motivos de segurança, não podemos mostrá-lo novamente.",
|
||||
"account.apiTokens.deleteButton.label": "Excluir",
|
||||
"account.apiTokens.deleteConfirmationMessage": "O token <strong>tokenName</strong> será revogado permanentemente. Tem certeza de que deseja continuar?",
|
||||
"account.apiTokens.description": "Esses tokens permitem que outros aplicativos controlem toda a sua conta e typebots. Tenha cuidado!",
|
||||
"account.apiTokens.heading": "Tokens de API",
|
||||
"account.apiTokens.table.createdHeader": "Criado",
|
||||
"account.apiTokens.table.nameHeader": "Nome",
|
||||
"account.myAccount.changePhotoButton.label": "Alterar foto",
|
||||
"account.myAccount.changePhotoButton.specification": ".jpg ou.png, máximo 1MB",
|
||||
"account.myAccount.emailInput.disabledTooltip": "A atualização do e-mail não está disponível. Entre em contato com o suporte se quiser alterá-lo.",
|
||||
"account.myAccount.emailInput.label": "Endereço de e-mail:",
|
||||
"account.myAccount.nameInput.label": "Nome:",
|
||||
"account.preferences.appearance.darkLabel": "Escuro",
|
||||
"account.preferences.appearance.heading": "Aparência",
|
||||
"account.preferences.appearance.lightLabel": "Claro",
|
||||
"account.preferences.appearance.systemLabel": "Sistema",
|
||||
"account.preferences.graphNavigation.heading": "Navegação do Editor",
|
||||
"account.preferences.graphNavigation.mouse.description": "Mova arrastando o quadro e amplie/reduza usando a roda de rolagem",
|
||||
"account.preferences.graphNavigation.mouse.label": "Mouse",
|
||||
"account.preferences.graphNavigation.trackpad.description": "Mova o quadro usando 2 dedos e amplie/reduza fazendo pinça",
|
||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||
"account.preferences.language.heading": "Idioma",
|
||||
"account.preferences.language.tooltip": "As traduções ainda não estão completas. É um trabalho em andamento. \uD83E\uDD13",
|
||||
"analytics.completionRateLabel": "Taxa de conclusão",
|
||||
"analytics.notAvailableLabel": "Não disponível",
|
||||
"analytics.startsLabel": "Inícios",
|
||||
"analytics.viewsLabel": "Visualizações",
|
||||
"auth.emailSubmitButton.label": "Enviar",
|
||||
"auth.error.default": "Tente entrar com uma conta diferente.",
|
||||
"auth.error.email": "E-mail não encontrado. Tente entrar com um provedor diferente.",
|
||||
"auth.error.oauthNotLinked": "Já existe uma conta vinculada a esse E-mail, entre com a mesma conta que você usou originalmente.",
|
||||
"auth.error.unknown": "Ocorreu um erro. Tente novamente.",
|
||||
"auth.magicLink.description": "Certifique-se de verificar sua pasta de spam.",
|
||||
"auth.magicLink.title": "Um email com o link mágico foi enviado. \uD83E\uDE84",
|
||||
"auth.noProvider.link": "configurar pelo menos um provedor de autenticação (E-mail, Google, GitHub, Facebook ou Azure AD).",
|
||||
"auth.noProvider.preLink": "Você precisa",
|
||||
"auth.orEmailLabel": "Ou com seu email",
|
||||
"auth.register.aggreeToTerms": "Ao se cadastrar, você concorda com nossos <terms>termsOfService</terms> e <privacy>privacyPolicy</privacy>.",
|
||||
"auth.register.alreadyHaveAccountLabel.link": "Entrar",
|
||||
"auth.register.alreadyHaveAccountLabel.preLink": "Já tem uma conta?",
|
||||
"auth.register.heading": "Criar uma conta",
|
||||
"auth.signin.heading": "Entrar",
|
||||
"auth.signin.noAccountLabel.link": "Registre-se gratuitamente",
|
||||
"auth.signin.noAccountLabel.preLink": "Não tem uma conta?",
|
||||
"auth.signinErrorToast.description": "As inscrições estão desativadas.",
|
||||
"auth.signinErrorToast.title": "Não autorizado",
|
||||
"auth.signinErrorToast.tooManyRequests": "Muitas tentativas. Tente novamente mais tarde.",
|
||||
"auth.socialLogin.azureButton.label": "Continuar com {azureProviderName}",
|
||||
"auth.socialLogin.customButton.label": "Continuar com {customProviderName}",
|
||||
"auth.socialLogin.facebookButton.label": "Continuar com Facebook",
|
||||
"auth.socialLogin.githubButton.label": "Continuar com GitHub",
|
||||
"auth.socialLogin.gitlabButton.label": "Continuar com {gitlabProviderName}",
|
||||
"auth.socialLogin.googleButton.label": "Continuar com Google",
|
||||
"back": "Voltar",
|
||||
"billing.billingPortalButton.label": "Portal de cobrança",
|
||||
"billing.contribution.link": "Saiba mais.",
|
||||
"billing.contribution.preLink": "A Typebot está contribuindo com 1% da sua assinatura para remover o CO₂ da atmosfera.",
|
||||
"billing.currentSubscription.cancelDate": "Será cancelado em",
|
||||
"billing.currentSubscription.heading": "Assinatura",
|
||||
"billing.currentSubscription.pastDueAlert": "O último pagamento falhou. Acesse o portal de faturamento para prosseguir e evitar o cancelamento da sua assinatura.",
|
||||
"billing.currentSubscription.subheading": "Assinatura atual do espaço de trabalho:",
|
||||
"billing.customLimit.link": "Vamos conversar!",
|
||||
"billing.customLimit.preLink": "Precisa de limites personalizados? Recursos específicos?",
|
||||
"billing.invoices.empty": "Nenhuma fatura encontrada para este espaço de trabalho.",
|
||||
"billing.invoices.heading": "Faturas",
|
||||
"billing.invoices.paidAt": "Pago em",
|
||||
"billing.invoices.subtotal": "Subtotal",
|
||||
"billing.limitMessage.analytics": "desbloquear análises aprofundadas",
|
||||
"billing.limitMessage.brand": "remover a marca",
|
||||
"billing.limitMessage.customDomain": "adicionar domínios personalizados",
|
||||
"billing.limitMessage.fileInput": "usar blocos de envio de arquivo",
|
||||
"billing.limitMessage.folder": "criar pastas",
|
||||
"billing.preCheckoutModal.companyInput.label": "Nome da empresa:",
|
||||
"billing.preCheckoutModal.emailInput.label": "E-mail:",
|
||||
"billing.preCheckoutModal.submitButton.label": "Ir para a finalização da compra",
|
||||
"billing.preCheckoutModal.taxId.label": "Identificação fiscal (CPF):",
|
||||
"billing.preCheckoutModal.taxId.placeholder": "Tipo de ID",
|
||||
"billing.pricingCard.chatsPerMonth": "chats/mês",
|
||||
"billing.pricingCard.chatsTooltip": "Um chat é contado sempre que um usuário inicia uma discussão. Ele é independente do número de mensagens que ele envia e recebe.",
|
||||
"billing.pricingCard.heading": "Mudar para <strong>plan</strong>",
|
||||
"billing.pricingCard.perMonth": "/ mês",
|
||||
"billing.pricingCard.plus": ", mais:",
|
||||
"billing.pricingCard.pro.analytics": "Análises aprofundadas",
|
||||
"billing.pricingCard.pro.customDomains": "Domínios personalizados",
|
||||
"billing.pricingCard.pro.description": "Para agências e startups em crescimento.",
|
||||
"billing.pricingCard.pro.everythingFromStarter": "Tudo em Starter",
|
||||
"billing.pricingCard.pro.includedSeats": "5 assentos incluídos",
|
||||
"billing.pricingCard.pro.mostPopularLabel": "Mais popular",
|
||||
"billing.pricingCard.pro.whatsAppIntegration": "Integração do WhatsApp",
|
||||
"billing.pricingCard.starter.brandingRemoved": "Marca removida",
|
||||
"billing.pricingCard.starter.createFolders": "Criar pastas",
|
||||
"billing.pricingCard.starter.description": "Para indivíduos e pequenas empresas.",
|
||||
"billing.pricingCard.starter.fileUploadBlock": "Bloco de envio de arquivo",
|
||||
"billing.pricingCard.starter.includedSeats": "2 assentos incluídos",
|
||||
"billing.pricingCard.upgradeButton.current": "Sua assinatura atual",
|
||||
"billing.updateSuccessToast.description": "Sua assinatura {plan} foi atualizada com sucesso \uD83C\uDF89",
|
||||
"billing.upgradeAlert.buttonDefaultLabel": "Mais informações",
|
||||
"billing.upgradeLimitLabel": "Você precisa atualizar sua assinatura para {type}",
|
||||
"billing.usage.chats.alert.soonReach": "Seus typebots são populares! Você logo alcançará o limite de chats de seu plano. \uD83D\uDE80",
|
||||
"billing.usage.chats.alert.updatePlan": "Certifique-se de atualizar seu plano para aumentar esse limite e continuar conversando com seus usuários.",
|
||||
"billing.usage.chats.heading": "Chats",
|
||||
"billing.usage.heading": "Uso",
|
||||
"billing.usage.unlimited": "Ilimitado",
|
||||
"cancel": "Cancelar",
|
||||
"confirmModal.defaultTitle": "Tem certeza?",
|
||||
"dashboard.header.settingsButton.label": "Configurações & Membros",
|
||||
"dashboard.redirectionMessage": "Você está sendo redirecionado...",
|
||||
"dashboard.title": "Meus typebots",
|
||||
"delete": "Apagar",
|
||||
"downgrade": "Downgrade",
|
||||
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
|
||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros",
|
||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
||||
"editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript",
|
||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo",
|
||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot",
|
||||
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática",
|
||||
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um arquivo",
|
||||
"editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link",
|
||||
"editor.blocks.bubbles.audio.settings.upload.label": "Carregar",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do arquivo de áudio...",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs",
|
||||
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação",
|
||||
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...",
|
||||
"editor.blocks.bubbles.image.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)",
|
||||
"editor.blocks.bubbles.textEditor.plate.label": "Editor de texto",
|
||||
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável",
|
||||
"editor.blocks.bubbles.video.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Colar o link do vídeo...",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.text": "Compatível com Youtube, Vimeo e outros",
|
||||
"editor.blocks.start.text": "Início",
|
||||
"editor.editableTypebotName.tooltip.rename.label": "Renomear",
|
||||
"editor.gettingStartedModal.editorBasics.heading": "Fundamentos do Editor",
|
||||
"editor.gettingStartedModal.editorBasics.list.four.label": "Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito",
|
||||
"editor.gettingStartedModal.editorBasics.list.label": "Sinta-se à vontade para usar o chat no canto inferior direito para entrar em contato se tiver alguma dúvida. Normalmente, respondo nas próximas 24 horas. \uD83D\uDE03",
|
||||
"editor.gettingStartedModal.editorBasics.list.one.label": "A barra lateral esquerda contém blocos que podem ser arrastados e soltos no quadro.",
|
||||
"editor.gettingStartedModal.editorBasics.list.three.label": "Conecte os grupos entre eles",
|
||||
"editor.gettingStartedModal.editorBasics.list.two.label": "Você pode agrupar blocos juntos, colocando-os abaixo ou acima dos outros",
|
||||
"editor.gettingStartedModal.seeAction.item.label": "Outros vídeos",
|
||||
"editor.gettingStartedModal.seeAction.label": "Veja como funciona em",
|
||||
"editor.gettingStartedModal.seeAction.time": "5 minutos",
|
||||
"editor.headers.flowButton.label": "Fluxo",
|
||||
"editor.headers.helpButton.label": "Ajuda",
|
||||
"editor.headers.previewButton.label": "Visualizar",
|
||||
"editor.headers.resultsButton.label": "Resultados",
|
||||
"editor.headers.savingSpinner.label": "Salvando...",
|
||||
"editor.headers.settingsButton.label": "Configurações",
|
||||
"editor.headers.shareButton.label": "Compartilhar",
|
||||
"editor.headers.themeButton.label": "Tema",
|
||||
"editor.sidebarBlock.abTest.label": "Teste AB",
|
||||
"editor.sidebarBlock.analytics.label": "Analytics",
|
||||
"editor.sidebarBlock.audio.label": "Áudio",
|
||||
"editor.sidebarBlock.button.label": "Botão",
|
||||
"editor.sidebarBlock.chatwoot.label": "Chatwoot",
|
||||
"editor.sidebarBlock.condition.label": "Condição",
|
||||
"editor.sidebarBlock.date.label": "Data",
|
||||
"editor.sidebarBlock.email.label": "Email",
|
||||
"editor.sidebarBlock.embed.label": "Incorporar",
|
||||
"editor.sidebarBlock.file.label": "Arquivo",
|
||||
"editor.sidebarBlock.image.label": "Imagem",
|
||||
"editor.sidebarBlock.jump.label": "Pular",
|
||||
"editor.sidebarBlock.makecom.label": "Make.com",
|
||||
"editor.sidebarBlock.number.label": "Número",
|
||||
"editor.sidebarBlock.openai.label": "OpenAI",
|
||||
"editor.sidebarBlock.pabbly.label": "Pabbly",
|
||||
"editor.sidebarBlock.payment.label": "Pagamento",
|
||||
"editor.sidebarBlock.phone.label": "Telefone",
|
||||
"editor.sidebarBlock.picChoice.label": "Seleção de Imagem",
|
||||
"editor.sidebarBlock.pixel.label": "Pixel",
|
||||
"editor.sidebarBlock.rating.label": "Avaliação",
|
||||
"editor.sidebarBlock.redirect.label": "Redirecionar",
|
||||
"editor.sidebarBlock.script.label": "Script",
|
||||
"editor.sidebarBlock.setVariable.label": "Variável",
|
||||
"editor.sidebarBlock.sheets.label": "Sheets",
|
||||
"editor.sidebarBlock.start.label": "Início",
|
||||
"editor.sidebarBlock.text.label": "Texto",
|
||||
"editor.sidebarBlock.typebot.label": "Typebot",
|
||||
"editor.sidebarBlock.video.label": "Vídeo",
|
||||
"editor.sidebarBlock.wait.label": "Espera",
|
||||
"editor.sidebarBlock.webhook.label": "Webhook",
|
||||
"editor.sidebarBlock.website.label": "Website",
|
||||
"editor.sidebarBlock.zapier.label": "Zapier",
|
||||
"editor.sidebarBlock.zemanticAi.label": "Zemantic AI",
|
||||
"editor.sidebarBlocks.blockType.bubbles.heading": "Bubbles",
|
||||
"editor.sidebarBlocks.blockType.inputs.heading": "Inputs",
|
||||
"editor.sidebarBlocks.blockType.integrations.heading": "Integrações",
|
||||
"editor.sidebarBlocks.blockType.logic.heading": "Condicionais",
|
||||
"editor.sidebarBlocks.sidebar.icon.lock.label": "Bloquear",
|
||||
"editor.sidebarBlocks.sidebar.icon.unlock.label": "Desbloquear",
|
||||
"editor.sidebarBlocks.sidebar.lock.label": "Bloquear barra lateral",
|
||||
"editor.sidebarBlocks.sidebar.unlock.label": "Desbloquear barra lateral",
|
||||
"errorMessage": "Ocorreu um erro",
|
||||
"folders.createFolderButton.label": "Criar uma pasta",
|
||||
"folders.createTypebotButton.label": "Criar um typebot",
|
||||
"folders.folderButton.deleteConfirmationMessage": "Tem certeza de que deseja excluir a pasta <strong>folderName</strong>? (Tudo o que estiver dentro será movido para o seu painel)",
|
||||
"folders.typebotButton.delete": "Apagar",
|
||||
"folders.typebotButton.deleteConfirmationMessage": "Tem certeza de que deseja excluir seu typebot <strong>typebotName</strong>?",
|
||||
"folders.typebotButton.deleteConfirmationMessageWarning": "Todos os dados associados serão excluídos e não poderão ser recuperados.",
|
||||
"folders.typebotButton.duplicate": "Duplicar",
|
||||
"folders.typebotButton.live": "Live",
|
||||
"folders.typebotButton.showMoreOptions": "Mostrar mais opções",
|
||||
"folders.typebotButton.unpublish": "Despublicar",
|
||||
"pending": "Pendente",
|
||||
"remove": "Remover",
|
||||
"skip": "Pular",
|
||||
"templates.buttons.fromScratchButton.label": "Comece do zero",
|
||||
"templates.buttons.fromTemplateButton.label": "Comece a partir de um modelo",
|
||||
"templates.buttons.heading": "Criar um novo typebot",
|
||||
"templates.buttons.importFileButton.label": "Importar um arquivo",
|
||||
"templates.importFromFileButon.toastError.description": "Falha ao analisar o arquivo. Tem certeza de que é um typebot?",
|
||||
"templates.modal.menuHeading.marketing": "Marketing",
|
||||
"templates.modal.menuHeading.new.tag": "Novo",
|
||||
"templates.modal.menuHeading.other": "Outros",
|
||||
"templates.modal.menuHeading.product": "Produto",
|
||||
"templates.modal.useTemplateButton.label": "Usar esse modelo",
|
||||
"upgrade": "Upgrade",
|
||||
"workspace.dropdown.logoutButton.label": "Sair",
|
||||
"workspace.dropdown.newButton.label": "Novo espaço de trabalho",
|
||||
"workspace.membersList.inviteButton.label": "Convidar",
|
||||
"workspace.membersList.inviteInput.placeholder": "colega@empresa.com",
|
||||
"workspace.membersList.title": "Membros",
|
||||
"workspace.membersList.unlockBanner.label": "Atualize seu plano para trabalhar com mais membros da equipe e desbloqueie recursos incríveis \uD83D\uDE80",
|
||||
"workspace.settings.deleteButton.confirmMessage": "Você tem certeza de que deseja excluir o espaço de trabalho {workspaceName}? Todas as suas pastas, typebots e resultados serão excluídos permanentemente.",
|
||||
"workspace.settings.deleteButton.label": "Excluir espaço de trabalho",
|
||||
"workspace.settings.icon.title": "Ícone",
|
||||
"workspace.settings.modal.menu.billingAndUsage.label": "Faturamento e uso",
|
||||
"workspace.settings.modal.menu.members.label": "Membros",
|
||||
"workspace.settings.modal.menu.myAccount.label": "Minha conta",
|
||||
"workspace.settings.modal.menu.preferences.label": "Preferências",
|
||||
"workspace.settings.modal.menu.settings.label": "Configurações",
|
||||
"workspace.settings.modal.menu.version.label": "Versão: {version}",
|
||||
"workspace.settings.modal.menu.workspace.label": "Espaço de trabalho",
|
||||
"workspace.settings.name.label": "Nome:"
|
||||
}
|
251
apps/builder/public/locales/pt.json
Normal file
251
apps/builder/public/locales/pt.json
Normal file
@ -0,0 +1,251 @@
|
||||
{
|
||||
"account.apiTokens.createButton.label": "Criar",
|
||||
"account.apiTokens.createModal.copyInstruction": "Por favor, copie o seu token e guarde-o num lugar seguro.",
|
||||
"account.apiTokens.createModal.createButton.label": "Criar token",
|
||||
"account.apiTokens.createModal.createHeading": "Criar Token",
|
||||
"account.apiTokens.createModal.createdHeading": "Token Criado",
|
||||
"account.apiTokens.createModal.doneButton.label": "Concluído",
|
||||
"account.apiTokens.createModal.nameInput.label": "Insira um nome único para o seu token para o diferenciar de outros tokens.",
|
||||
"account.apiTokens.createModal.nameInput.placeholder": "Ex. Zapier, Github, Make.com",
|
||||
"account.apiTokens.createModal.securityWarning": "Por razões de segurança, não o podemos mostrar novamente.",
|
||||
"account.apiTokens.deleteButton.label": "Excluir",
|
||||
"account.apiTokens.deleteConfirmationMessage": "O token <strong>tokenName</strong> será revogado permanentemente. Tem a certeza de que deseja continuar?",
|
||||
"account.apiTokens.description": "Estes tokens permitem que outras aplicações controlem toda a sua conta e typebots. Tenha cuidado!",
|
||||
"account.apiTokens.heading": "Tokens de API",
|
||||
"account.apiTokens.table.createdHeader": "Criado",
|
||||
"account.apiTokens.table.nameHeader": "Nome",
|
||||
"account.myAccount.changePhotoButton.label": "Alterar foto",
|
||||
"account.myAccount.changePhotoButton.specification": ".jpg ou.png, máximo 1MB",
|
||||
"account.myAccount.emailInput.disabledTooltip": "A atualização do e-mail não está disponível. Entre em contacto com o apoio se quiser alterá-lo.",
|
||||
"account.myAccount.emailInput.label": "Endereço de e-mail:",
|
||||
"account.myAccount.nameInput.label": "Nome:",
|
||||
"account.preferences.appearance.darkLabel": "Escuro",
|
||||
"account.preferences.appearance.heading": "Aparência",
|
||||
"account.preferences.appearance.lightLabel": "Claro",
|
||||
"account.preferences.appearance.systemLabel": "Sistema",
|
||||
"account.preferences.graphNavigation.heading": "Navegação do Editor",
|
||||
"account.preferences.graphNavigation.mouse.description": "Mova arrastando o quadro e amplie/reduza usando a roda de deslocamento",
|
||||
"account.preferences.graphNavigation.mouse.label": "Rato",
|
||||
"account.preferences.graphNavigation.trackpad.description": "Mova o quadro usando 2 dedos e amplie/reduza fazendo pinça",
|
||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||
"account.preferences.language.heading": "Idioma",
|
||||
"account.preferences.language.tooltip": "As traduções ainda não estão completas. É um trabalho em curso. \uD83E\uDD13",
|
||||
"analytics.completionRateLabel": "Taxa de conclusão",
|
||||
"analytics.notAvailableLabel": "Não disponível",
|
||||
"analytics.startsLabel": "Inícios",
|
||||
"analytics.viewsLabel": "Visualizações",
|
||||
"auth.emailSubmitButton.label": "Enviar",
|
||||
"auth.error.default": "Tente entrar com uma conta diferente.",
|
||||
"auth.error.email": "E-mail não encontrado. Tente entrar com um fornecedor diferente.",
|
||||
"auth.error.oauthNotLinked": "Para confirmar a sua identidade, entre com a mesma conta que usou originalmente.",
|
||||
"auth.error.unknown": "Ocorreu um erro. Tente novamente.",
|
||||
"auth.magicLink.description": "Certifique-se de verificar a sua pasta de spam.",
|
||||
"auth.magicLink.title": "Foi enviado um e-mail com a ligação mágica. \uD83E\uDE84",
|
||||
"auth.noProvider.link": "configurar pelo menos um fornecedor de autenticação (E-mail, Google, GitHub, Facebook ou Azure AD).",
|
||||
"auth.noProvider.preLink": "Precisa de",
|
||||
"auth.orEmailLabel": "Ou com o seu e-mail",
|
||||
"auth.register.aggreeToTerms": "Ao registar-se, concorda com os nossos <terms>termsOfService</terms> e <privacy>privacyPolicy</privacy>.",
|
||||
"auth.register.alreadyHaveAccountLabel.link": "Entrar",
|
||||
"auth.register.alreadyHaveAccountLabel.preLink": "Já tem uma conta?",
|
||||
"auth.register.heading": "Criar uma conta",
|
||||
"auth.signin.heading": "Entrar",
|
||||
"auth.signin.noAccountLabel.link": "Registe-se gratuitamente",
|
||||
"auth.signin.noAccountLabel.preLink": "Não tem uma conta?",
|
||||
"auth.signinErrorToast.description": "As inscrições estão desativadas.",
|
||||
"auth.signinErrorToast.title": "Não autorizado",
|
||||
"auth.signinErrorToast.tooManyRequests": "Muitas tentativas. Tente novamente mais tarde.",
|
||||
"auth.socialLogin.azureButton.label": "Continuar com {azureProviderName}",
|
||||
"auth.socialLogin.customButton.label": "Continuar com {customProviderName}",
|
||||
"auth.socialLogin.facebookButton.label": "Continuar com Facebook",
|
||||
"auth.socialLogin.githubButton.label": "Continuar com GitHub",
|
||||
"auth.socialLogin.gitlabButton.label": "Continuar com {gitlabProviderName}",
|
||||
"auth.socialLogin.googleButton.label": "Continuar com Google",
|
||||
"back": "Voltar",
|
||||
"billing.billingPortalButton.label": "Portal de facturação",
|
||||
"billing.contribution.link": "Saiba mais.",
|
||||
"billing.contribution.preLink": "A Typebot está a contribuir com 1% da sua subscrição para remover o CO₂ da atmosfera.",
|
||||
"billing.currentSubscription.cancelDate": "Será cancelado em",
|
||||
"billing.currentSubscription.heading": "Subscrição",
|
||||
"billing.currentSubscription.pastDueAlert": "O último pagamento falhou. Acesse o portal de faturamento para continuar e evitar o cancelamento da sua assinatura.",
|
||||
"billing.currentSubscription.subheading": "Subscrição actual do espaço de trabalho:",
|
||||
"billing.customLimit.link": "Vamos falar!",
|
||||
"billing.customLimit.preLink": "Precisa de limites personalizados? Funcionalidades específicas?",
|
||||
"billing.invoices.empty": "Nenhuma factura encontrada para este espaço de trabalho.",
|
||||
"billing.invoices.heading": "Facturas",
|
||||
"billing.invoices.paidAt": "Pago em",
|
||||
"billing.invoices.subtotal": "Subtotal",
|
||||
"billing.limitMessage.analytics": "desbloquear análises aprofundadas",
|
||||
"billing.limitMessage.brand": "remover a marca",
|
||||
"billing.limitMessage.customDomain": "adicionar domínios personalizados",
|
||||
"billing.limitMessage.fileInput": "usar blocos de envio de ficheiros",
|
||||
"billing.limitMessage.folder": "criar pastas",
|
||||
"billing.preCheckoutModal.companyInput.label": "Nome da empresa:",
|
||||
"billing.preCheckoutModal.emailInput.label": "E-mail:",
|
||||
"billing.preCheckoutModal.submitButton.label": "Ir para a finalização da compra",
|
||||
"billing.preCheckoutModal.taxId.label": "Identificação fiscal (NIF):",
|
||||
"billing.preCheckoutModal.taxId.placeholder": "Tipo de ID",
|
||||
"billing.pricingCard.chatsPerMonth": "chats/mês",
|
||||
"billing.pricingCard.chatsTooltip": "Um chat é contado sempre que um utilizador inicia uma discussão. Ele é independente do número de mensagens que envia e recebe.",
|
||||
"billing.pricingCard.heading": "Mudar para <strong>plan</strong>",
|
||||
"billing.pricingCard.perMonth": "/ mês",
|
||||
"billing.pricingCard.plus": ", mais:",
|
||||
"billing.pricingCard.pro.analytics": "Análises aprofundadas",
|
||||
"billing.pricingCard.pro.customDomains": "Domínios personalizados",
|
||||
"billing.pricingCard.pro.description": "Para agências e startups em crescimento.",
|
||||
"billing.pricingCard.pro.everythingFromStarter": "Tudo em Starter",
|
||||
"billing.pricingCard.pro.includedSeats": "5 lugares incluídos",
|
||||
"billing.pricingCard.pro.mostPopularLabel": "Mais popular",
|
||||
"billing.pricingCard.pro.whatsAppIntegration": "Integração do WhatsApp",
|
||||
"billing.pricingCard.starter.brandingRemoved": "Marca removida",
|
||||
"billing.pricingCard.starter.createFolders": "Criar pastas",
|
||||
"billing.pricingCard.starter.description": "Para indivíduos e pequenas empresas.",
|
||||
"billing.pricingCard.starter.fileUploadBlock": "Bloco de envio de ficheiro",
|
||||
"billing.pricingCard.starter.includedSeats": "2 lugares incluídos",
|
||||
"billing.pricingCard.upgradeButton.current": "A sua subscrição atual",
|
||||
"billing.updateSuccessToast.description": "A sua subscrição {plan} foi atualizada com sucesso \uD83C\uDF89",
|
||||
"billing.upgradeAlert.buttonDefaultLabel": "Mais informações",
|
||||
"billing.upgradeLimitLabel": "Precisa de atualizar a sua subscrição para {type}",
|
||||
"billing.usage.chats.alert.soonReach": "Os seus typebots são populares! Vai alcançar em breve o limite de chats do seu plano. \uD83D\uDE80",
|
||||
"billing.usage.chats.alert.updatePlan": "Certifique-se de atualizar o seu plano para aumentar esse limite e continuar a conversar com os seus utilizadores.",
|
||||
"billing.usage.chats.heading": "Chats",
|
||||
"billing.usage.heading": "Uso",
|
||||
"billing.usage.unlimited": "Ilimitado",
|
||||
"cancel": "Cancelar",
|
||||
"confirmModal.defaultTitle": "Tem a certeza?",
|
||||
"dashboard.header.settingsButton.label": "Configurações & Membros",
|
||||
"dashboard.redirectionMessage": "Está a ser redirecionado...",
|
||||
"dashboard.title": "Os meus typebots",
|
||||
"delete": "Apagar",
|
||||
"downgrade": "Downgrade",
|
||||
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
|
||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Carregar Ficheiros",
|
||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
||||
"editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript",
|
||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo",
|
||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot",
|
||||
"editor.blocks.bubbles.audio.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.audio.settings.autoplay.label": "Ativar reprodução automática",
|
||||
"editor.blocks.bubbles.audio.settings.chooseFile.label": "Escolher um ficheiro",
|
||||
"editor.blocks.bubbles.audio.settings.embedLink.label": "Incorporar link",
|
||||
"editor.blocks.bubbles.audio.settings.upload.label": "Carregar",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.placeholder": "Colar o link do ficheiro de áudio...",
|
||||
"editor.blocks.bubbles.audio.settings.worksWith.text": "Compatível com .MP3s e .WAVs",
|
||||
"editor.blocks.bubbles.embed.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.embed.node.show.text": "Mostrar incorporação",
|
||||
"editor.blocks.bubbles.embed.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.placeholder": "Colar o link ou código...",
|
||||
"editor.blocks.bubbles.embed.settings.worksWith.text": "Compatível com PDFs, iframes, websites...",
|
||||
"editor.blocks.bubbles.image.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.label": "Link ao clicar",
|
||||
"editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder": "Texto alternativo do link (descrição)",
|
||||
"editor.blocks.bubbles.textEditor.plate.label": "Editor de texto",
|
||||
"editor.blocks.bubbles.textEditor.searchVariable.placeholder": "Pesquisar uma variável",
|
||||
"editor.blocks.bubbles.video.node.clickToEdit.text": "Clique para editar...",
|
||||
"editor.blocks.bubbles.video.settings.numberInput.unit": "px",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.placeholder": "Colar o link do vídeo...",
|
||||
"editor.blocks.bubbles.video.settings.worksWith.text": "Compatível com Youtube, Vimeo e outros",
|
||||
"editor.blocks.start.text": "Começar",
|
||||
"editor.editableTypebotName.tooltip.rename.label": "Renomear",
|
||||
"editor.gettingStartedModal.editorBasics.heading": "Noções básicas de editor",
|
||||
"editor.gettingStartedModal.editorBasics.list.four.label": "Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito",
|
||||
"editor.gettingStartedModal.editorBasics.list.label": "Sinta-se à vontade para usar o chat no canto inferior direito para entrar em contacto se tiver alguma questão. Normalmente, respondo nas próximas 24 horas. \uD83D\uDE03",
|
||||
"editor.gettingStartedModal.editorBasics.list.one.label": "A barra lateral esquerda contém blocos que pode arrastar e largar no quadro.",
|
||||
"editor.gettingStartedModal.editorBasics.list.three.label": "Ligue os grupos entre si",
|
||||
"editor.gettingStartedModal.editorBasics.list.two.label": "Pode agrupar blocos juntos, colocando-os uns abaixo ou acima dos outros",
|
||||
"editor.gettingStartedModal.seeAction.item.label": "Outros vídeos",
|
||||
"editor.gettingStartedModal.seeAction.label": "Veja o funcionamento em",
|
||||
"editor.gettingStartedModal.seeAction.time": "5 minutos",
|
||||
"editor.headers.flowButton.label": "Fluxo",
|
||||
"editor.headers.helpButton.label": "Ajuda",
|
||||
"editor.headers.previewButton.label": "Visualizar",
|
||||
"editor.headers.resultsButton.label": "Resultados",
|
||||
"editor.headers.savingSpinner.label": "Salvando...",
|
||||
"editor.headers.settingsButton.label": "Configurações",
|
||||
"editor.headers.shareButton.label": "Compartilhar",
|
||||
"editor.headers.themeButton.label": "Tema",
|
||||
"editor.sidebarBlock.abTest.label": "Teste AB",
|
||||
"editor.sidebarBlock.analytics.label": "Analytics",
|
||||
"editor.sidebarBlock.audio.label": "Áudio",
|
||||
"editor.sidebarBlock.button.label": "Botão",
|
||||
"editor.sidebarBlock.chatwoot.label": "Chatwoot",
|
||||
"editor.sidebarBlock.condition.label": "Condição",
|
||||
"editor.sidebarBlock.date.label": "Data",
|
||||
"editor.sidebarBlock.email.label": "Email",
|
||||
"editor.sidebarBlock.embed.label": "Incorporar",
|
||||
"editor.sidebarBlock.file.label": "Ficheiro",
|
||||
"editor.sidebarBlock.image.label": "Imagem",
|
||||
"editor.sidebarBlock.jump.label": "Saltar",
|
||||
"editor.sidebarBlock.makecom.label": "Make.com",
|
||||
"editor.sidebarBlock.number.label": "Número",
|
||||
"editor.sidebarBlock.openai.label": "OpenAI",
|
||||
"editor.sidebarBlock.pabbly.label": "Pabbly",
|
||||
"editor.sidebarBlock.payment.label": "Pagamento",
|
||||
"editor.sidebarBlock.phone.label": "Telefone",
|
||||
"editor.sidebarBlock.picChoice.label": "Seleção de Imagem",
|
||||
"editor.sidebarBlock.pixel.label": "Pixel",
|
||||
"editor.sidebarBlock.rating.label": "Classificação",
|
||||
"editor.sidebarBlock.redirect.label": "Redirecionar",
|
||||
"editor.sidebarBlock.script.label": "Script",
|
||||
"editor.sidebarBlock.setVariable.label": "Variável",
|
||||
"editor.sidebarBlock.sheets.label": "Sheets",
|
||||
"editor.sidebarBlock.start.label": "Início",
|
||||
"editor.sidebarBlock.text.label": "Texto",
|
||||
"editor.sidebarBlock.typebot.label": "Typebot",
|
||||
"editor.sidebarBlock.video.label": "Vídeo",
|
||||
"editor.sidebarBlock.wait.label": "Espera",
|
||||
"editor.sidebarBlock.webhook.label": "Webhook",
|
||||
"editor.sidebarBlock.website.label": "Website",
|
||||
"editor.sidebarBlock.zapier.label": "Zapier",
|
||||
"editor.sidebarBlock.zemanticAi.label": "Zemantic AI",
|
||||
"editor.sidebarBlocks.blockType.bubbles.heading": "Bubbles",
|
||||
"editor.sidebarBlocks.blockType.inputs.heading": "Inputs",
|
||||
"editor.sidebarBlocks.blockType.integrations.heading": "Integrações",
|
||||
"editor.sidebarBlocks.blockType.logic.heading": "Condicionais",
|
||||
"editor.sidebarBlocks.sidebar.icon.lock.label": "Bloquear",
|
||||
"editor.sidebarBlocks.sidebar.icon.unlock.label": "Desbloquear",
|
||||
"editor.sidebarBlocks.sidebar.lock.label": "Bloquear barra lateral",
|
||||
"editor.sidebarBlocks.sidebar.unlock.label": "Desbloquear barra lateral",
|
||||
"errorMessage": "Ocorreu um erro",
|
||||
"folders.createFolderButton.label": "Criar uma pasta",
|
||||
"folders.createTypebotButton.label": "Criar um typebot",
|
||||
"folders.folderButton.deleteConfirmationMessage": "Tem a certeza de que deseja excluir a pasta <strong>folderName</strong>? (Tudo o que estiver dentro será movido para o seu painel)",
|
||||
"folders.typebotButton.delete": "Apagar",
|
||||
"folders.typebotButton.deleteConfirmationMessage": "Tem a certeza de que deseja excluir o seu typebot <strong>typebotName</strong>?",
|
||||
"folders.typebotButton.deleteConfirmationMessageWarning": "Todos os dados associados serão excluídos e não poderão ser recuperados.",
|
||||
"folders.typebotButton.duplicate": "Duplicar",
|
||||
"folders.typebotButton.live": "Ao Vivo",
|
||||
"folders.typebotButton.showMoreOptions": "Mostrar mais opções",
|
||||
"folders.typebotButton.unpublish": "Despublicar",
|
||||
"pending": "Pendente",
|
||||
"remove": "Remover",
|
||||
"skip": "Saltar",
|
||||
"templates.buttons.fromScratchButton.label": "Comece do zero",
|
||||
"templates.buttons.fromTemplateButton.label": "Comece a partir de um modelo",
|
||||
"templates.buttons.heading": "Criar um novo typebot",
|
||||
"templates.buttons.importFileButton.label": "Importar um ficheiro",
|
||||
"templates.importFromFileButon.toastError.description": "Falha ao analisar o ficheiro. Tem certeza de que é um typebot?",
|
||||
"templates.modal.menuHeading.marketing": "Marketing",
|
||||
"templates.modal.menuHeading.new.tag": "Novo",
|
||||
"templates.modal.menuHeading.other": "Outros",
|
||||
"templates.modal.menuHeading.product": "Produto",
|
||||
"templates.modal.useTemplateButton.label": "Usar este modelo",
|
||||
"upgrade": "Upgrade",
|
||||
"workspace.dropdown.logoutButton.label": "Sair",
|
||||
"workspace.dropdown.newButton.label": "Novo espaço de trabalho",
|
||||
"workspace.membersList.inviteButton.label": "Convidar",
|
||||
"workspace.membersList.inviteInput.placeholder": "colega@empresa.com",
|
||||
"workspace.membersList.title": "Membros",
|
||||
"workspace.membersList.unlockBanner.label": "Atualize o seu plano para trabalhar com mais membros da equipa e desbloquear funcionalidades incríveis \uD83D\uDE80",
|
||||
"workspace.settings.deleteButton.confirmMessage": "Tem a certeza de que deseja eliminar o espaço de trabalho {workspaceName}? Todas as suas pastas, typebots e resultados serão excluídos permanentemente.",
|
||||
"workspace.settings.deleteButton.label": "Eliminar espaço de trabalho",
|
||||
"workspace.settings.icon.title": "Ícone",
|
||||
"workspace.settings.modal.menu.billingAndUsage.label": "Faturação e uso",
|
||||
"workspace.settings.modal.menu.members.label": "Membros",
|
||||
"workspace.settings.modal.menu.myAccount.label": "A minha conta",
|
||||
"workspace.settings.modal.menu.preferences.label": "Preferências",
|
||||
"workspace.settings.modal.menu.settings.label": "Configurações",
|
||||
"workspace.settings.modal.menu.version.label": "Versão: {version}",
|
||||
"workspace.settings.modal.menu.workspace.label": "Espaço de trabalho",
|
||||
"workspace.settings.name.label": "Nome:"
|
||||
}
|
@ -8,7 +8,7 @@ import {
|
||||
AlertDialogOverlay,
|
||||
Button,
|
||||
} from '@chakra-ui/react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type ConfirmDeleteModalProps = {
|
||||
isOpen: boolean
|
||||
@ -29,7 +29,7 @@ export const ConfirmModal = ({
|
||||
onConfirm,
|
||||
confirmButtonColor = 'red',
|
||||
}: ConfirmDeleteModalProps) => {
|
||||
const scopedT = useScopedI18n('confirmModal')
|
||||
const { t } = useTranslate()
|
||||
const [confirmLoading, setConfirmLoading] = useState(false)
|
||||
const cancelRef = useRef(null)
|
||||
|
||||
@ -54,7 +54,7 @@ export const ConfirmModal = ({
|
||||
<AlertDialogOverlay>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader fontSize="lg" fontWeight="bold">
|
||||
{title ?? scopedT('defaultTitle')}
|
||||
{title ?? t('confirmModal.defaultTitle')}
|
||||
</AlertDialogHeader>
|
||||
|
||||
<AlertDialogBody>{message}</AlertDialogBody>
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
ChangePlanModal,
|
||||
ChangePlanModalProps,
|
||||
} from '@/features/billing/components/ChangePlanModal'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
buttonLabel?: string
|
||||
@ -25,7 +25,7 @@ export const UnlockPlanAlertInfo = ({
|
||||
excludedPlans,
|
||||
...props
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
return (
|
||||
<Alert
|
||||
|
@ -5,8 +5,8 @@ export const whatsAppBrandColor = '#25D366'
|
||||
export const WhatsAppLogo = (props: IconProps) => (
|
||||
<Icon viewBox="0 0 510 513" {...props}>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M435.689 74.468C387.754 26.471 324 0.025 256.071 0C116.098 0 2.18 113.906 2.131 253.916C2.107 298.674 13.808 342.361 36.029 380.862L0 512.459L134.617 477.148C171.704 497.386 213.467 508.039 255.962 508.051H256.071C396.02 508.051 509.951 394.134 509.999 254.123C510.023 186.268 483.638 122.478 435.689 74.48V74.468ZM256.071 465.168H255.986C218.118 465.157 180.97 454.976 148.558 435.751L140.851 431.174L60.965 452.127L82.285 374.238L77.268 366.251C56.143 332.646 44.978 293.804 45.002 253.929C45.051 137.563 139.731 42.883 256.157 42.883C312.53 42.908 365.521 64.886 405.371 104.786C445.224 144.674 467.152 197.713 467.128 254.099C467.078 370.476 372.4 465.157 256.071 465.157V465.168ZM371.839 307.101C365.495 303.923 334.302 288.581 328.481 286.462C322.661 284.343 318.437 283.285 314.211 289.64C309.986 295.997 297.823 310.291 294.121 314.515C290.419 318.753 286.718 319.277 280.374 316.098C274.031 312.92 253.587 306.224 229.345 284.611C210.485 267.784 197.748 247.013 194.048 240.656C190.346 234.301 193.658 230.867 196.823 227.713C199.672 224.865 203.167 220.299 206.345 216.597C209.523 212.895 210.57 210.242 212.688 206.016C214.808 201.778 213.748 198.079 212.166 194.899C210.582 191.722 197.895 160.49 192.598 147.791C187.447 135.421 182.213 137.101 178.329 136.894C174.626 136.711 170.402 136.675 166.165 136.675C161.928 136.675 155.06 138.257 149.24 144.614C143.42 150.968 127.031 166.323 127.031 197.541C127.031 228.761 149.764 258.946 152.942 263.183C156.119 267.42 197.687 331.501 261.331 358.995C276.466 365.533 288.288 369.441 297.506 372.363C312.702 377.197 326.533 376.516 337.466 374.883C349.656 373.058 375.006 359.53 380.29 344.711C385.573 329.893 385.573 317.182 383.991 314.539C382.409 311.898 378.172 310.302 371.828 307.125L371.839 307.101Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
|
@ -25,12 +25,12 @@ import { useApiTokens } from '../hooks/useApiTokens'
|
||||
import { ApiTokenFromServer } from '../types'
|
||||
import { parseTimeSince } from '@/helpers/parseTimeSince'
|
||||
import { deleteApiTokenQuery } from '../queries/deleteApiTokenQuery'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { T, useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = { user: User }
|
||||
|
||||
export const ApiTokensList = ({ user }: Props) => {
|
||||
const scopedT = useScopedI18n('account.apiTokens')
|
||||
const { t } = useTranslate()
|
||||
const { showToast } = useToast()
|
||||
const { apiTokens, isLoading, mutate } = useApiTokens({
|
||||
userId: user.id,
|
||||
@ -57,10 +57,12 @@ export const ApiTokensList = ({ user }: Props) => {
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<Heading fontSize="2xl">{scopedT('heading')}</Heading>
|
||||
<Text>{scopedT('description')}</Text>
|
||||
<Heading fontSize="2xl">{t('account.apiTokens.heading')}</Heading>
|
||||
<Text>{t('account.apiTokens.description')}</Text>
|
||||
<Flex justifyContent="flex-end">
|
||||
<Button onClick={onCreateOpen}>{scopedT('createButton.label')}</Button>
|
||||
<Button onClick={onCreateOpen}>
|
||||
{t('account.apiTokens.createButton.label')}
|
||||
</Button>
|
||||
<CreateTokenModal
|
||||
userId={user.id}
|
||||
isOpen={isCreateOpen}
|
||||
@ -73,8 +75,8 @@ export const ApiTokensList = ({ user }: Props) => {
|
||||
<Table>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{scopedT('table.nameHeader')}</Th>
|
||||
<Th w="130px">{scopedT('table.createdHeader')}</Th>
|
||||
<Th>{t('account.apiTokens.table.nameHeader')}</Th>
|
||||
<Th w="130px">{t('account.apiTokens.table.createdHeader')}</Th>
|
||||
<Th w="0" />
|
||||
</Tr>
|
||||
</Thead>
|
||||
@ -90,7 +92,7 @@ export const ApiTokensList = ({ user }: Props) => {
|
||||
variant="outline"
|
||||
onClick={() => setDeletingId(token.id)}
|
||||
>
|
||||
{scopedT('deleteButton.label')}
|
||||
{t('account.apiTokens.deleteButton.label')}
|
||||
</Button>
|
||||
</Td>
|
||||
</Tr>
|
||||
@ -118,14 +120,17 @@ export const ApiTokensList = ({ user }: Props) => {
|
||||
onClose={() => setDeletingId(undefined)}
|
||||
message={
|
||||
<Text>
|
||||
{scopedT('deleteConfirmationMessage', {
|
||||
tokenName: (
|
||||
<strong>{apiTokens?.find(byId(deletingId))?.name}</strong>
|
||||
),
|
||||
})}
|
||||
<T
|
||||
keyName="account.apiTokens.deleteConfirmationMessage"
|
||||
params={{
|
||||
strong: (
|
||||
<strong>{apiTokens?.find(byId(deletingId))?.name}</strong>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
}
|
||||
confirmButtonLabel={scopedT('deleteButton.label')}
|
||||
confirmButtonLabel={t('account.apiTokens.deleteButton.label')}
|
||||
/>
|
||||
</Stack>
|
||||
)
|
||||
|
@ -10,7 +10,7 @@ import Image from 'next/image'
|
||||
import lightModeIllustration from 'public/images/light-mode.png'
|
||||
import darkModeIllustration from 'public/images/dark-mode.png'
|
||||
import systemModeIllustration from 'public/images/system-mode.png'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
defaultValue: string
|
||||
@ -18,22 +18,22 @@ type Props = {
|
||||
}
|
||||
|
||||
export const AppearanceRadioGroup = ({ defaultValue, onChange }: Props) => {
|
||||
const scopedT = useScopedI18n('account.preferences.appearance')
|
||||
const { t } = useTranslate()
|
||||
|
||||
const appearanceData = [
|
||||
{
|
||||
value: 'light',
|
||||
label: scopedT('lightLabel'),
|
||||
label: t('account.preferences.appearance.lightLabel'),
|
||||
image: lightModeIllustration,
|
||||
},
|
||||
{
|
||||
value: 'dark',
|
||||
label: scopedT('darkLabel'),
|
||||
label: t('account.preferences.appearance.darkLabel'),
|
||||
image: darkModeIllustration,
|
||||
},
|
||||
{
|
||||
value: 'system',
|
||||
label: scopedT('systemLabel'),
|
||||
label: t('account.preferences.appearance.systemLabel'),
|
||||
image: systemModeIllustration,
|
||||
},
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CopyButton } from '@/components/CopyButton'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import {
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
@ -33,7 +33,7 @@ export const CreateTokenModal = ({
|
||||
onNewToken,
|
||||
}: Props) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
const scopedT = useScopedI18n('account.apiTokens.createModal')
|
||||
const { t } = useTranslate()
|
||||
const [name, setName] = useState('')
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [newTokenValue, setNewTokenValue] = useState<string>()
|
||||
@ -54,14 +54,18 @@ export const CreateTokenModal = ({
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>
|
||||
{newTokenValue ? scopedT('createdHeading') : scopedT('createHeading')}
|
||||
{newTokenValue
|
||||
? t('account.apiTokens.createModal.createdHeading')
|
||||
: t('account.apiTokens.createModal.createHeading')}
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
{newTokenValue ? (
|
||||
<ModalBody as={Stack} spacing="4">
|
||||
<Text>
|
||||
{scopedT('copyInstruction')}{' '}
|
||||
<strong>{scopedT('securityWarning')}</strong>
|
||||
{t('account.apiTokens.createModal.copyInstruction')}{' '}
|
||||
<strong>
|
||||
{t('account.apiTokens.createModal.securityWarning')}
|
||||
</strong>
|
||||
</Text>
|
||||
<InputGroup size="md">
|
||||
<Input readOnly pr="4.5rem" value={newTokenValue} />
|
||||
@ -72,10 +76,14 @@ export const CreateTokenModal = ({
|
||||
</ModalBody>
|
||||
) : (
|
||||
<ModalBody as="form" onSubmit={createToken}>
|
||||
<Text mb="4">{scopedT('nameInput.label')}</Text>
|
||||
<Text mb="4">
|
||||
{t('account.apiTokens.createModal.nameInput.label')}
|
||||
</Text>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
placeholder={scopedT('nameInput.placeholder')}
|
||||
placeholder={t(
|
||||
'account.apiTokens.createModal.nameInput.placeholder'
|
||||
)}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</ModalBody>
|
||||
@ -84,7 +92,7 @@ export const CreateTokenModal = ({
|
||||
<ModalFooter>
|
||||
{newTokenValue ? (
|
||||
<Button onClick={onClose} colorScheme="blue">
|
||||
{scopedT('doneButton.label')}
|
||||
{t('account.apiTokens.createModal.doneButton.label')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
@ -93,7 +101,7 @@ export const CreateTokenModal = ({
|
||||
isLoading={isSubmitting}
|
||||
onClick={createToken}
|
||||
>
|
||||
{scopedT('createButton.label')}
|
||||
{t('account.apiTokens.createModal.createButton.label')}
|
||||
</Button>
|
||||
)}
|
||||
</ModalFooter>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { MouseIcon, LaptopIcon } from '@/components/icons'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import {
|
||||
HStack,
|
||||
Radio,
|
||||
@ -18,18 +18,20 @@ export const GraphNavigationRadioGroup = ({
|
||||
defaultValue,
|
||||
onChange,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('account.preferences.graphNavigation')
|
||||
const { t } = useTranslate()
|
||||
const graphNavigationData = [
|
||||
{
|
||||
value: GraphNavigation.MOUSE,
|
||||
label: scopedT('mouse.label'),
|
||||
description: scopedT('mouse.description'),
|
||||
label: t('account.preferences.graphNavigation.mouse.label'),
|
||||
description: t('account.preferences.graphNavigation.mouse.description'),
|
||||
icon: <MouseIcon boxSize="35px" />,
|
||||
},
|
||||
{
|
||||
value: GraphNavigation.TRACKPAD,
|
||||
label: scopedT('trackpad.label'),
|
||||
description: scopedT('trackpad.description'),
|
||||
label: t('account.preferences.graphNavigation.trackpad.label'),
|
||||
description: t(
|
||||
'account.preferences.graphNavigation.trackpad.description'
|
||||
),
|
||||
icon: <LaptopIcon boxSize="35px" />,
|
||||
},
|
||||
]
|
||||
|
@ -5,10 +5,10 @@ import { ApiTokensList } from './ApiTokensList'
|
||||
import { UploadButton } from '@/components/ImageUploadContent/UploadButton'
|
||||
import { useUser } from '../hooks/useUser'
|
||||
import { TextInput } from '@/components/inputs/TextInput'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const MyAccountForm = () => {
|
||||
const scopedT = useScopedI18n('account.myAccount')
|
||||
const { t } = useTranslate()
|
||||
const { user, updateUser } = useUser()
|
||||
const [name, setName] = useState(user?.name ?? '')
|
||||
const [email, setEmail] = useState(user?.email ?? '')
|
||||
@ -47,11 +47,11 @@ export const MyAccountForm = () => {
|
||||
leftIcon={<UploadIcon />}
|
||||
onFileUploaded={handleFileUploaded}
|
||||
>
|
||||
{scopedT('changePhotoButton.label')}
|
||||
{t('account.myAccount.changePhotoButton.label')}
|
||||
</UploadButton>
|
||||
)}
|
||||
<Text color="gray.500" fontSize="sm">
|
||||
{scopedT('changePhotoButton.specification')}
|
||||
{t('account.myAccount.changePhotoButton.specification')}
|
||||
</Text>
|
||||
</Stack>
|
||||
</HStack>
|
||||
@ -59,17 +59,17 @@ export const MyAccountForm = () => {
|
||||
<TextInput
|
||||
defaultValue={name}
|
||||
onChange={handleNameChange}
|
||||
label={scopedT('nameInput.label')}
|
||||
label={t('account.myAccount.nameInput.label')}
|
||||
withVariableButton={false}
|
||||
debounceTimeout={0}
|
||||
/>
|
||||
<Tooltip label={scopedT('emailInput.disabledTooltip')}>
|
||||
<Tooltip label={t('account.myAccount.emailInput.disabledTooltip')}>
|
||||
<span>
|
||||
<TextInput
|
||||
type="email"
|
||||
defaultValue={email}
|
||||
onChange={handleEmailChange}
|
||||
label={scopedT('emailInput.label')}
|
||||
label={t('account.myAccount.emailInput.label')}
|
||||
withVariableButton={false}
|
||||
debounceTimeout={0}
|
||||
isDisabled
|
||||
|
@ -14,9 +14,10 @@ import React, { useEffect } from 'react'
|
||||
import { GraphNavigationRadioGroup } from './GraphNavigationRadioGroup'
|
||||
import { AppearanceRadioGroup } from './AppearanceRadioGroup'
|
||||
import { useUser } from '../hooks/useUser'
|
||||
import { useChangeLocale, useCurrentLocale, useScopedI18n } from '@/locales'
|
||||
import { ChevronDownIcon } from '@/components/icons'
|
||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||
import { useTranslate, useTolgee } from '@tolgee/react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const localeHumanReadable = {
|
||||
en: 'English',
|
||||
@ -27,11 +28,11 @@ const localeHumanReadable = {
|
||||
} as const
|
||||
|
||||
export const UserPreferencesForm = () => {
|
||||
const scopedT = useScopedI18n('account.preferences')
|
||||
const { getLanguage } = useTolgee()
|
||||
const router = useRouter()
|
||||
const { t } = useTranslate()
|
||||
const { colorMode } = useColorMode()
|
||||
const { user, updateUser } = useUser()
|
||||
const changeLocale = useChangeLocale()
|
||||
const currentLocale = useCurrentLocale()
|
||||
|
||||
useEffect(() => {
|
||||
if (!user?.graphNavigation)
|
||||
@ -47,17 +48,23 @@ export const UserPreferencesForm = () => {
|
||||
}
|
||||
|
||||
const updateLocale = (locale: keyof typeof localeHumanReadable) => () => {
|
||||
changeLocale(locale)
|
||||
document.cookie = `NEXT_LOCALE=${locale}; path=/; max-age=31536000`
|
||||
router.replace(router.pathname, undefined, { locale })
|
||||
}
|
||||
|
||||
const currentLanguage = getLanguage()
|
||||
|
||||
return (
|
||||
<Stack spacing={12}>
|
||||
<HStack spacing={4}>
|
||||
<Heading size="md">{scopedT('language.heading')}</Heading>
|
||||
<Heading size="md">{t('account.preferences.language.heading')}</Heading>
|
||||
<Menu>
|
||||
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
|
||||
{localeHumanReadable[currentLocale]}
|
||||
{currentLanguage
|
||||
? localeHumanReadable[
|
||||
currentLanguage as keyof typeof localeHumanReadable
|
||||
]
|
||||
: 'Loading...'}
|
||||
</MenuButton>
|
||||
<MenuList>
|
||||
{Object.keys(localeHumanReadable).map((locale) => (
|
||||
@ -76,19 +83,25 @@ export const UserPreferencesForm = () => {
|
||||
))}
|
||||
</MenuList>
|
||||
</Menu>
|
||||
{currentLocale !== 'en' && (
|
||||
<MoreInfoTooltip>{scopedT('language.tooltip')}</MoreInfoTooltip>
|
||||
{currentLanguage !== 'en' && (
|
||||
<MoreInfoTooltip>
|
||||
{t('account.preferences.language.tooltip')}
|
||||
</MoreInfoTooltip>
|
||||
)}
|
||||
</HStack>
|
||||
<Stack spacing={6}>
|
||||
<Heading size="md">{scopedT('graphNavigation.heading')}</Heading>
|
||||
<Heading size="md">
|
||||
{t('account.preferences.graphNavigation.heading')}
|
||||
</Heading>
|
||||
<GraphNavigationRadioGroup
|
||||
defaultValue={user?.graphNavigation ?? GraphNavigation.TRACKPAD}
|
||||
onChange={changeGraphNavigation}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack spacing={6}>
|
||||
<Heading size="md">{scopedT('appearance.heading')}</Heading>
|
||||
<Heading size="md">
|
||||
{t('account.preferences.appearance.heading')}
|
||||
</Heading>
|
||||
<AppearanceRadioGroup
|
||||
defaultValue={
|
||||
user?.preferredAppAppearance
|
||||
|
@ -12,12 +12,12 @@ import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||
import { Graph } from '@/features/graph/components/Graph'
|
||||
import { GraphProvider } from '@/features/graph/providers/GraphProvider'
|
||||
import { GroupsCoordinatesProvider } from '@/features/graph/providers/GroupsCoordinateProvider'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
|
||||
export const AnalyticsGraphContainer = ({ stats }: { stats?: Stats }) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
const { typebot, publishedTypebot } = useTypebot()
|
||||
const { data } = trpc.analytics.getTotalAnswersInBlocks.useQuery(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import {
|
||||
GridProps,
|
||||
SimpleGrid,
|
||||
@ -22,13 +22,13 @@ export const StatsCards = ({
|
||||
stats,
|
||||
...props
|
||||
}: { stats?: Stats } & GridProps) => {
|
||||
const scopedT = useScopedI18n('analytics')
|
||||
const { t } = useTranslate()
|
||||
const bg = useColorModeValue('white', 'gray.900')
|
||||
|
||||
return (
|
||||
<SimpleGrid columns={{ base: 1, md: 3 }} spacing="6" {...props}>
|
||||
<Stat bgColor={bg} p="4" rounded="md" boxShadow="md">
|
||||
<StatLabel>{scopedT('viewsLabel')}</StatLabel>
|
||||
<StatLabel>{t('analytics.viewsLabel')}</StatLabel>
|
||||
{stats ? (
|
||||
<StatNumber>{stats.totalViews}</StatNumber>
|
||||
) : (
|
||||
@ -36,7 +36,7 @@ export const StatsCards = ({
|
||||
)}
|
||||
</Stat>
|
||||
<Stat bgColor={bg} p="4" rounded="md" boxShadow="md">
|
||||
<StatLabel>{scopedT('startsLabel')}</StatLabel>
|
||||
<StatLabel>{t('analytics.startsLabel')}</StatLabel>
|
||||
{stats ? (
|
||||
<StatNumber>{stats.totalStarts}</StatNumber>
|
||||
) : (
|
||||
@ -44,10 +44,10 @@ export const StatsCards = ({
|
||||
)}
|
||||
</Stat>
|
||||
<Stat bgColor={bg} p="4" rounded="md" boxShadow="md">
|
||||
<StatLabel>{scopedT('completionRateLabel')}</StatLabel>
|
||||
<StatLabel>{t('analytics.completionRateLabel')}</StatLabel>
|
||||
{stats ? (
|
||||
<StatNumber>
|
||||
{computeCompletionRate(scopedT('notAvailableLabel'))(
|
||||
{computeCompletionRate(t('analytics.notAvailableLabel'))(
|
||||
stats.totalCompleted,
|
||||
stats.totalStarts
|
||||
)}
|
||||
|
@ -13,13 +13,13 @@ import { useRouter } from 'next/router'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import confetti from 'canvas-confetti'
|
||||
import { useUser } from '@/features/account/hooks/useUser'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
const totalSteps = 5
|
||||
|
||||
export const OnboardingPage = () => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { push, replace } = useRouter()
|
||||
const confettiCanvaContainer = useRef<HTMLCanvasElement | null>(null)
|
||||
const confettiCanon = useRef<confetti.CreateTypes>()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Alert } from '@chakra-ui/react'
|
||||
|
||||
type Props = {
|
||||
@ -6,16 +6,16 @@ type Props = {
|
||||
}
|
||||
|
||||
export const SignInError = ({ error }: Props) => {
|
||||
const scopedT = useScopedI18n('auth.error')
|
||||
const { t } = useTranslate()
|
||||
const errors: Record<string, string> = {
|
||||
Signin: scopedT('default'),
|
||||
OAuthSignin: scopedT('default'),
|
||||
OAuthCallback: scopedT('default'),
|
||||
OAuthCreateAccount: scopedT('email'),
|
||||
EmailCreateAccount: scopedT('default'),
|
||||
Callback: scopedT('default'),
|
||||
OAuthAccountNotLinked: scopedT('oauthNotLinked'),
|
||||
default: scopedT('unknown'),
|
||||
Signin: t('auth.error.default'),
|
||||
OAuthSignin: t('auth.error.default'),
|
||||
OAuthCallback: t('auth.error.default'),
|
||||
OAuthCreateAccount: t('auth.error.email'),
|
||||
EmailCreateAccount: t('auth.error.default'),
|
||||
Callback: t('auth.error.default'),
|
||||
OAuthAccountNotLinked: t('auth.error.oauthNotLinked'),
|
||||
default: t('auth.error.unknown'),
|
||||
}
|
||||
return (
|
||||
<Alert status="error" variant="solid" rounded="md">
|
||||
|
@ -27,7 +27,7 @@ import { BuiltInProviderType } from 'next-auth/providers'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { TextLink } from '@/components/TextLink'
|
||||
import { SignInError } from './SignInError'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
defaultEmail?: string
|
||||
@ -35,7 +35,7 @@ type Props = {
|
||||
export const SignInForm = ({
|
||||
defaultEmail,
|
||||
}: Props & HTMLChakraProps<'form'>) => {
|
||||
const scopedT = useScopedI18n('auth')
|
||||
const { t } = useTranslate()
|
||||
const router = useRouter()
|
||||
const { status } = useSession()
|
||||
const [authLoading, setAuthLoading] = useState(false)
|
||||
@ -79,8 +79,8 @@ export const SignInForm = ({
|
||||
})
|
||||
if (response?.error) {
|
||||
showToast({
|
||||
title: scopedT('signinErrorToast.title'),
|
||||
description: scopedT('signinErrorToast.description'),
|
||||
title: t('auth.signinErrorToast.title'),
|
||||
description: t('auth.signinErrorToast.description'),
|
||||
})
|
||||
} else {
|
||||
setIsMagicLinkSent(true)
|
||||
@ -88,7 +88,7 @@ export const SignInForm = ({
|
||||
} catch {
|
||||
showToast({
|
||||
status: 'info',
|
||||
description: scopedT('signinErrorToast.tooManyRequests'),
|
||||
description: t('auth.signinErrorToast.tooManyRequests'),
|
||||
})
|
||||
}
|
||||
setAuthLoading(false)
|
||||
@ -98,12 +98,12 @@ export const SignInForm = ({
|
||||
if (hasNoAuthProvider)
|
||||
return (
|
||||
<Text>
|
||||
{scopedT('noProvider.preLink')}{' '}
|
||||
{t('auth.noProvider.preLink')}{' '}
|
||||
<TextLink
|
||||
href="https://docs.typebot.io/self-hosting/configuration"
|
||||
isExternal
|
||||
>
|
||||
{scopedT('noProvider.link')}
|
||||
{t('auth.noProvider.link')}
|
||||
</TextLink>
|
||||
</Text>
|
||||
)
|
||||
@ -114,9 +114,7 @@ export const SignInForm = ({
|
||||
<SocialLoginButtons providers={providers} />
|
||||
{providers?.email && (
|
||||
<>
|
||||
<DividerWithText mt="6">
|
||||
{scopedT('orEmailLabel')}
|
||||
</DividerWithText>
|
||||
<DividerWithText mt="6">{t('auth.orEmailLabel')}</DividerWithText>
|
||||
<HStack as="form" onSubmit={handleEmailSubmit}>
|
||||
<Input
|
||||
name="email"
|
||||
@ -134,7 +132,7 @@ export const SignInForm = ({
|
||||
}
|
||||
isDisabled={isMagicLinkSent}
|
||||
>
|
||||
{scopedT('emailSubmitButton.label')}
|
||||
{t('auth.emailSubmitButton.label')}
|
||||
</Button>
|
||||
</HStack>
|
||||
</>
|
||||
@ -150,8 +148,8 @@ export const SignInForm = ({
|
||||
<HStack>
|
||||
<AlertIcon />
|
||||
<Stack spacing={1}>
|
||||
<Text fontWeight="semibold">{scopedT('magicLink.title')}</Text>
|
||||
<Text fontSize="sm">{scopedT('magicLink.description')}</Text>
|
||||
<Text fontWeight="semibold">{t('auth.magicLink.title')}</Text>
|
||||
<Text fontSize="sm">{t('auth.magicLink.description')}</Text>
|
||||
</Stack>
|
||||
</HStack>
|
||||
</Alert>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Seo } from '@/components/Seo'
|
||||
import { TextLink } from '@/components/TextLink'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { T, useTranslate } from '@tolgee/react'
|
||||
import { VStack, Heading, Text } from '@chakra-ui/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { SignInForm } from './SignInForm'
|
||||
@ -11,7 +11,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const SignInPage = ({ type }: Props) => {
|
||||
const scopedT = useScopedI18n('auth')
|
||||
const { t } = useTranslate()
|
||||
const { query } = useRouter()
|
||||
|
||||
return (
|
||||
@ -19,8 +19,8 @@ export const SignInPage = ({ type }: Props) => {
|
||||
<Seo
|
||||
title={
|
||||
type === 'signin'
|
||||
? scopedT('signin.heading')
|
||||
: scopedT('register.heading')
|
||||
? t('auth.signin.heading')
|
||||
: t('auth.register.heading')
|
||||
}
|
||||
/>
|
||||
<Heading
|
||||
@ -29,39 +29,36 @@ export const SignInPage = ({ type }: Props) => {
|
||||
}}
|
||||
>
|
||||
{type === 'signin'
|
||||
? scopedT('signin.heading')
|
||||
: scopedT('register.heading')}
|
||||
? t('auth.signin.heading')
|
||||
: t('auth.register.heading')}
|
||||
</Heading>
|
||||
{type === 'signin' ? (
|
||||
<Text>
|
||||
{scopedT('signin.noAccountLabel.preLink')}{' '}
|
||||
{t('auth.signin.noAccountLabel.preLink')}{' '}
|
||||
<TextLink href="/register">
|
||||
{scopedT('signin.noAccountLabel.link')}
|
||||
{t('auth.signin.noAccountLabel.link')}
|
||||
</TextLink>
|
||||
</Text>
|
||||
) : (
|
||||
<Text>
|
||||
{scopedT('register.alreadyHaveAccountLabel.preLink')}{' '}
|
||||
{t('auth.register.alreadyHaveAccountLabel.preLink')}{' '}
|
||||
<TextLink href="/signin">
|
||||
{scopedT('register.alreadyHaveAccountLabel.link')}
|
||||
{t('auth.register.alreadyHaveAccountLabel.link')}
|
||||
</TextLink>
|
||||
</Text>
|
||||
)}
|
||||
<SignInForm defaultEmail={query.g?.toString()} />
|
||||
{type === 'signup' ? (
|
||||
<Text fontSize="sm" maxW="400px" textAlign="center">
|
||||
{scopedT('register.aggreeToTerms', {
|
||||
termsOfService: (
|
||||
<TextLink href={'https://typebot.io/terms-of-service'}>
|
||||
{scopedT('register.termsOfService')}
|
||||
</TextLink>
|
||||
),
|
||||
privacyPolicy: (
|
||||
<TextLink href={'https://typebot.io/privacy-policies'}>
|
||||
{scopedT('register.privacyPolicy')}
|
||||
</TextLink>
|
||||
),
|
||||
})}
|
||||
<T
|
||||
keyName="auth.register.aggreeToTerms"
|
||||
params={{
|
||||
terms: <TextLink href={'https://typebot.io/terms-of-service'} />,
|
||||
privacy: (
|
||||
<TextLink href={'https://typebot.io/privacy-policies'} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
) : null}
|
||||
</VStack>
|
||||
|
@ -15,7 +15,7 @@ import { omit } from '@typebot.io/lib'
|
||||
import { AzureAdLogo } from '@/components/logos/AzureAdLogo'
|
||||
import { FacebookLogo } from '@/components/logos/FacebookLogo'
|
||||
import { GitlabLogo } from '@/components/logos/GitlabLogo'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
providers:
|
||||
@ -24,7 +24,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
const scopedT = useScopedI18n('auth.socialLogin')
|
||||
const { t } = useTranslate()
|
||||
const { query } = useRouter()
|
||||
const { status } = useSession()
|
||||
const [authLoading, setAuthLoading] =
|
||||
@ -65,7 +65,7 @@ export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
{scopedT('githubButton.label')}
|
||||
{t('auth.socialLogin.githubButton.label')}
|
||||
</Button>
|
||||
)}
|
||||
{providers?.google && (
|
||||
@ -79,7 +79,7 @@ export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
{scopedT('googleButton.label')}
|
||||
{t('auth.socialLogin.googleButton.label')}
|
||||
</Button>
|
||||
)}
|
||||
{providers?.facebook && (
|
||||
@ -93,7 +93,7 @@ export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
{scopedT('facebookButton.label')}
|
||||
{t('auth.socialLogin.facebookButton.label')}
|
||||
</Button>
|
||||
)}
|
||||
{providers?.gitlab && (
|
||||
@ -107,7 +107,7 @@ export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
{scopedT('gitlabButton.label', {
|
||||
{t('auth.socialLogin.gitlabButton.label', {
|
||||
gitlabProviderName: providers.gitlab.name,
|
||||
})}
|
||||
</Button>
|
||||
@ -123,7 +123,7 @@ export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
{scopedT('azureButton.label', {
|
||||
{t('auth.socialLogin.azureButton.label', {
|
||||
azureProviderName: providers['azure-ad'].name,
|
||||
})}
|
||||
</Button>
|
||||
@ -137,7 +137,7 @@ export const SocialLoginButtons = ({ providers }: Props) => {
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
{scopedT('customButton.label', {
|
||||
{t('auth.socialLogin.customButton.label', {
|
||||
customProviderName: providers['custom-oauth'].name,
|
||||
})}
|
||||
</Button>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Button, ButtonProps, Link } from '@chakra-ui/react'
|
||||
|
||||
type Props = {
|
||||
@ -8,7 +8,7 @@ type Props = {
|
||||
} & Pick<ButtonProps, 'colorScheme'>
|
||||
|
||||
export const BillingPortalButton = ({ workspaceId, colorScheme }: Props) => {
|
||||
const scopedT = useScopedI18n('billing')
|
||||
const { t } = useTranslate()
|
||||
const { showToast } = useToast()
|
||||
const { data } = trpc.billing.getBillingPortalUrl.useQuery(
|
||||
{
|
||||
@ -29,7 +29,7 @@ export const BillingPortalButton = ({ workspaceId, colorScheme }: Props) => {
|
||||
isLoading={!data}
|
||||
colorScheme={colorScheme}
|
||||
>
|
||||
{scopedT('billingPortalButton.label')}
|
||||
{t('billing.billingPortalButton.label')}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { ParentModalProvider } from '@/features/graph/providers/ParentModalProvi
|
||||
import { useUser } from '@/features/account/hooks/useUser'
|
||||
import { StarterPlanPricingCard } from './StarterPlanPricingCard'
|
||||
import { ProPlanPricingCard } from './ProPlanPricingCard'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { StripeClimateLogo } from './StripeClimateLogo'
|
||||
import { guessIfUserIsEuropean } from '@typebot.io/lib/billing/guessIfUserIsEuropean'
|
||||
|
||||
@ -20,7 +20,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const ChangePlanForm = ({ workspace, excludedPlans }: Props) => {
|
||||
const scopedT = useScopedI18n('billing')
|
||||
const { t } = useTranslate()
|
||||
|
||||
const { user } = useUser()
|
||||
const { showToast } = useToast()
|
||||
@ -49,7 +49,7 @@ export const ChangePlanForm = ({ workspace, excludedPlans }: Props) => {
|
||||
trpcContext.workspace.getWorkspace.invalidate()
|
||||
showToast({
|
||||
status: 'success',
|
||||
description: scopedT('updateSuccessToast.description', {
|
||||
description: t('billing.updateSuccessToast.description', {
|
||||
plan: workspace?.plan,
|
||||
}),
|
||||
})
|
||||
@ -87,9 +87,9 @@ export const ChangePlanForm = ({ workspace, excludedPlans }: Props) => {
|
||||
<HStack maxW="500px">
|
||||
<StripeClimateLogo />
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
{scopedT('contribution.preLink')}{' '}
|
||||
{t('billing.contribution.preLink')}{' '}
|
||||
<TextLink href="https://climate.stripe.com/5VCRAq" isExternal>
|
||||
{scopedT('contribution.link')}
|
||||
{t('billing.contribution.link')}
|
||||
</TextLink>
|
||||
</Text>
|
||||
</HStack>
|
||||
@ -128,9 +128,9 @@ export const ChangePlanForm = ({ workspace, excludedPlans }: Props) => {
|
||||
)}
|
||||
|
||||
<Text color="gray.500">
|
||||
{scopedT('customLimit.preLink')}{' '}
|
||||
{t('billing.customLimit.preLink')}{' '}
|
||||
<TextLink href={'https://typebot.io/enterprise-lead-form'} isExternal>
|
||||
{scopedT('customLimit.link')}
|
||||
{t('billing.customLimit.link')}
|
||||
</TextLink>
|
||||
</Text>
|
||||
</Stack>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AlertInfo } from '@/components/AlertInfo'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import {
|
||||
Modal,
|
||||
ModalBody,
|
||||
@ -26,7 +26,7 @@ export const ChangePlanModal = ({
|
||||
type,
|
||||
excludedPlans,
|
||||
}: ChangePlanModalProps) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { workspace } = useWorkspace()
|
||||
return (
|
||||
<Modal
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
Thead,
|
||||
Tr,
|
||||
} from '@chakra-ui/react'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { proChatTiers } from '@typebot.io/lib/billing/constants'
|
||||
import { formatPrice } from '@typebot.io/lib/billing/formatPrice'
|
||||
|
||||
@ -25,12 +26,14 @@ type Props = {
|
||||
}
|
||||
|
||||
export const ChatsProTiersModal = ({ isOpen, onClose }: Props) => {
|
||||
const { t } = useTranslate()
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>
|
||||
<Heading size="lg">Chats pricing table</Heading>
|
||||
<Heading size="lg">{t('billing.tiersModal.heading')}</Heading>
|
||||
</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody as={Stack} spacing="6">
|
||||
|
@ -12,14 +12,14 @@ import { PlanTag } from './PlanTag'
|
||||
import { BillingPortalButton } from './BillingPortalButton'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { Workspace } from '@typebot.io/schemas'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
workspace: Pick<Workspace, 'id' | 'plan' | 'stripeId'>
|
||||
}
|
||||
|
||||
export const CurrentSubscriptionSummary = ({ workspace }: Props) => {
|
||||
const scopedT = useScopedI18n('billing.currentSubscription')
|
||||
const { t } = useTranslate()
|
||||
|
||||
const { data } = trpc.billing.getSubscription.useQuery({
|
||||
workspaceId: workspace.id,
|
||||
@ -31,13 +31,15 @@ export const CurrentSubscriptionSummary = ({ workspace }: Props) => {
|
||||
|
||||
return (
|
||||
<Stack spacing="4">
|
||||
<Heading fontSize="3xl">{scopedT('heading')}</Heading>
|
||||
<Heading fontSize="3xl">
|
||||
{t('billing.currentSubscription.heading')}
|
||||
</Heading>
|
||||
<HStack data-testid="current-subscription">
|
||||
<Text>{scopedT('subheading')} </Text>
|
||||
<Text>{t('billing.currentSubscription.subheading')} </Text>
|
||||
<PlanTag plan={workspace.plan} />
|
||||
{data?.subscription?.cancelDate && (
|
||||
<Text fontSize="sm">
|
||||
({scopedT('cancelDate')}{' '}
|
||||
({t('billing.currentSubscription.cancelDate')}{' '}
|
||||
{data.subscription.cancelDate.toDateString()})
|
||||
</Text>
|
||||
)}
|
||||
@ -45,7 +47,7 @@ export const CurrentSubscriptionSummary = ({ workspace }: Props) => {
|
||||
{data?.subscription?.status === 'past_due' && (
|
||||
<Alert fontSize="sm" status="error">
|
||||
<AlertIcon />
|
||||
{scopedT('pastDueAlert')}
|
||||
{t('billing.currentSubscription.pastDueAlert')}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
|
@ -18,14 +18,14 @@ import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
workspaceId: string
|
||||
}
|
||||
|
||||
export const InvoicesList = ({ workspaceId }: Props) => {
|
||||
const scopedT = useScopedI18n('billing.invoices')
|
||||
const { t } = useTranslate()
|
||||
const { showToast } = useToast()
|
||||
const { data, status } = trpc.billing.listInvoices.useQuery(
|
||||
{
|
||||
@ -40,9 +40,9 @@ export const InvoicesList = ({ workspaceId }: Props) => {
|
||||
|
||||
return (
|
||||
<Stack spacing={6}>
|
||||
<Heading fontSize="3xl">{scopedT('heading')}</Heading>
|
||||
<Heading fontSize="3xl">{t('billing.invoices.heading')}</Heading>
|
||||
{data?.invoices.length === 0 && status !== 'loading' ? (
|
||||
<Text>{scopedT('empty')}</Text>
|
||||
<Text>{t('billing.invoices.empty')}</Text>
|
||||
) : (
|
||||
<TableContainer>
|
||||
<Table>
|
||||
@ -50,8 +50,8 @@ export const InvoicesList = ({ workspaceId }: Props) => {
|
||||
<Tr>
|
||||
<Th w="0" />
|
||||
<Th>#</Th>
|
||||
<Th>{scopedT('paidAt')}</Th>
|
||||
<Th>{scopedT('subtotal')}</Th>
|
||||
<Th>{t('billing.invoices.paidAt')}</Th>
|
||||
<Th>{t('billing.invoices.subtotal')}</Th>
|
||||
<Th w="0" />
|
||||
</Tr>
|
||||
</Thead>
|
||||
|
@ -18,7 +18,7 @@ import { useRouter } from 'next/router'
|
||||
import React, { FormEvent, useState } from 'react'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { taxIdTypes } from '../taxIdTypes'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export type PreCheckoutModalProps = {
|
||||
selectedSubscription:
|
||||
@ -47,7 +47,7 @@ export const PreCheckoutModal = ({
|
||||
existingEmail,
|
||||
onClose,
|
||||
}: PreCheckoutModalProps) => {
|
||||
const scopedT = useScopedI18n('billing.preCheckoutModal')
|
||||
const { t } = useTranslate()
|
||||
const { ref } = useParentModal()
|
||||
const vatValueInputRef = React.useRef<HTMLInputElement>(null)
|
||||
const router = useRouter()
|
||||
@ -131,7 +131,7 @@ export const PreCheckoutModal = ({
|
||||
<Stack as="form" spacing="4" onSubmit={goToCheckout}>
|
||||
<TextInput
|
||||
isRequired
|
||||
label={scopedT('companyInput.label')}
|
||||
label={t('billing.preCheckoutModal.companyInput.label')}
|
||||
defaultValue={customer.company}
|
||||
onChange={updateCustomerCompany}
|
||||
withVariableButton={false}
|
||||
@ -140,17 +140,17 @@ export const PreCheckoutModal = ({
|
||||
<TextInput
|
||||
isRequired
|
||||
type="email"
|
||||
label={scopedT('emailInput.label')}
|
||||
label={t('billing.preCheckoutModal.emailInput.label')}
|
||||
defaultValue={customer.email}
|
||||
onChange={updateCustomerEmail}
|
||||
withVariableButton={false}
|
||||
debounceTimeout={0}
|
||||
/>
|
||||
<FormControl>
|
||||
<FormLabel>{scopedT('taxId.label')}</FormLabel>
|
||||
<FormLabel>{t('billing.preCheckoutModal.taxId.label')}</FormLabel>
|
||||
<HStack>
|
||||
<Select
|
||||
placeholder={scopedT('taxId.placeholder')}
|
||||
placeholder={t('billing.preCheckoutModal.taxId.placeholder')}
|
||||
items={vatCodeLabels}
|
||||
isPopoverMatchingInputWidth={false}
|
||||
onSelect={updateVatType}
|
||||
@ -171,7 +171,7 @@ export const PreCheckoutModal = ({
|
||||
colorScheme="blue"
|
||||
isDisabled={customer.company === '' || customer.email === ''}
|
||||
>
|
||||
{scopedT('submitButton.label')}
|
||||
{t('billing.preCheckoutModal.submitButton.label')}
|
||||
</Button>
|
||||
</Stack>
|
||||
</ModalBody>
|
||||
|
@ -14,10 +14,10 @@ import {
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import { FeaturesList } from './FeaturesList'
|
||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||
import { useI18n, useScopedI18n } from '@/locales'
|
||||
import { formatPrice } from '@typebot.io/lib/billing/formatPrice'
|
||||
import { ChatsProTiersModal } from './ChatsProTiersModal'
|
||||
import { prices } from '@typebot.io/lib/billing/constants'
|
||||
import { T, useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
currentPlan: Plan
|
||||
@ -32,12 +32,12 @@ export const ProPlanPricingCard = ({
|
||||
isLoading,
|
||||
onPayClick,
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const scopedT = useScopedI18n('billing.pricingCard')
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
const { t } = useTranslate()
|
||||
|
||||
const getButtonLabel = () => {
|
||||
if (currentPlan === Plan.PRO) return scopedT('upgradeButton.current')
|
||||
if (currentPlan === Plan.PRO)
|
||||
return t('billing.pricingCard.upgradeButton.current')
|
||||
return t('upgrade')
|
||||
}
|
||||
|
||||
@ -65,38 +65,41 @@ export const ProPlanPricingCard = ({
|
||||
fontWeight="semibold"
|
||||
style={{ marginTop: 0 }}
|
||||
>
|
||||
{scopedT('pro.mostPopularLabel')}
|
||||
{t('billing.pricingCard.pro.mostPopularLabel')}
|
||||
</Tag>
|
||||
</Flex>
|
||||
<Stack justifyContent="space-between" h="full">
|
||||
<Stack spacing="4" mt={2}>
|
||||
<Heading fontSize="2xl">
|
||||
{scopedT('heading', {
|
||||
plan: (
|
||||
<chakra.span
|
||||
color={useColorModeValue('blue.400', 'blue.300')}
|
||||
>
|
||||
Pro
|
||||
</chakra.span>
|
||||
),
|
||||
})}
|
||||
<T
|
||||
keyName="billing.pricingCard.heading"
|
||||
params={{
|
||||
strong: (
|
||||
<chakra.span
|
||||
color={useColorModeValue('blue.400', 'blue.300')}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Heading>
|
||||
<Text>{scopedT('pro.description')}</Text>
|
||||
<Text>{t('billing.pricingCard.pro.description')}</Text>
|
||||
</Stack>
|
||||
<Stack spacing="8">
|
||||
<Stack spacing="4">
|
||||
<Heading>
|
||||
{formatPrice(prices.PRO, { currency })}
|
||||
<chakra.span fontSize="md">{scopedT('perMonth')}</chakra.span>
|
||||
<chakra.span fontSize="md">
|
||||
{t('billing.pricingCard.perMonth')}
|
||||
</chakra.span>
|
||||
</Heading>
|
||||
<Text fontWeight="bold">
|
||||
<Tooltip
|
||||
label={
|
||||
<FeaturesList
|
||||
features={[
|
||||
scopedT('starter.brandingRemoved'),
|
||||
scopedT('starter.fileUploadBlock'),
|
||||
scopedT('starter.createFolders'),
|
||||
t('billing.pricingCard.starter.brandingRemoved'),
|
||||
t('billing.pricingCard.starter.fileUploadBlock'),
|
||||
t('billing.pricingCard.starter.createFolders'),
|
||||
]}
|
||||
spacing="0"
|
||||
/>
|
||||
@ -105,19 +108,21 @@ export const ProPlanPricingCard = ({
|
||||
placement="top"
|
||||
>
|
||||
<chakra.span textDecoration="underline" cursor="pointer">
|
||||
{scopedT('pro.everythingFromStarter')}
|
||||
{t('billing.pricingCard.pro.everythingFromStarter')}
|
||||
</chakra.span>
|
||||
</Tooltip>
|
||||
{scopedT('plus')}
|
||||
{t('billing.pricingCard.plus')}
|
||||
</Text>
|
||||
<FeaturesList
|
||||
features={[
|
||||
scopedT('pro.includedSeats'),
|
||||
t('billing.pricingCard.pro.includedSeats'),
|
||||
<Stack key="starter-chats" spacing={1}>
|
||||
<HStack key="test">
|
||||
<Text>10,000 {scopedT('chatsPerMonth')}</Text>
|
||||
<Text>
|
||||
10,000 {t('billing.pricingCard.chatsPerMonth')}
|
||||
</Text>
|
||||
<MoreInfoTooltip>
|
||||
{scopedT('chatsTooltip')}
|
||||
{t('billing.pricingCard.chatsTooltip')}
|
||||
</MoreInfoTooltip>
|
||||
</HStack>
|
||||
<Text
|
||||
@ -130,9 +135,9 @@ export const ProPlanPricingCard = ({
|
||||
</Button>
|
||||
</Text>
|
||||
</Stack>,
|
||||
scopedT('pro.whatsAppIntegration'),
|
||||
scopedT('pro.customDomains'),
|
||||
scopedT('pro.analytics'),
|
||||
t('billing.pricingCard.pro.whatsAppIntegration'),
|
||||
t('billing.pricingCard.pro.customDomains'),
|
||||
t('billing.pricingCard.pro.analytics'),
|
||||
]}
|
||||
/>
|
||||
</Stack>
|
||||
|
@ -10,9 +10,9 @@ import {
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import { FeaturesList } from './FeaturesList'
|
||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||
import { useI18n, useScopedI18n } from '@/locales'
|
||||
import { formatPrice } from '@typebot.io/lib/billing/formatPrice'
|
||||
import { prices } from '@typebot.io/lib/billing/constants'
|
||||
import { T, useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
currentPlan: Plan
|
||||
@ -27,12 +27,12 @@ export const StarterPlanPricingCard = ({
|
||||
currency,
|
||||
onPayClick,
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const scopedT = useScopedI18n('billing.pricingCard')
|
||||
const { t } = useTranslate()
|
||||
|
||||
const getButtonLabel = () => {
|
||||
if (currentPlan === Plan.PRO) return t('downgrade')
|
||||
if (currentPlan === Plan.STARTER) return scopedT('upgradeButton.current')
|
||||
if (currentPlan === Plan.STARTER)
|
||||
return t('billing.pricingCard.upgradeButton.current')
|
||||
return t('upgrade')
|
||||
}
|
||||
|
||||
@ -51,25 +51,30 @@ export const StarterPlanPricingCard = ({
|
||||
<Stack>
|
||||
<Stack spacing="4">
|
||||
<Heading fontSize="2xl">
|
||||
{scopedT('heading', {
|
||||
plan: <chakra.span color="orange.400">Starter</chakra.span>,
|
||||
})}
|
||||
<T
|
||||
keyName="billing.pricingCard.heading"
|
||||
params={{ strong: <chakra.span color="orange.400" /> }}
|
||||
/>
|
||||
</Heading>
|
||||
<Text>{scopedT('starter.description')}</Text>
|
||||
<Text>{t('billing.pricingCard.starter.description')}</Text>
|
||||
</Stack>
|
||||
<Heading>
|
||||
{formatPrice(prices.STARTER, { currency })}
|
||||
<chakra.span fontSize="md">{scopedT('perMonth')}</chakra.span>
|
||||
<chakra.span fontSize="md">
|
||||
{t('billing.pricingCard.perMonth')}
|
||||
</chakra.span>
|
||||
</Heading>
|
||||
</Stack>
|
||||
|
||||
<FeaturesList
|
||||
features={[
|
||||
scopedT('starter.includedSeats'),
|
||||
t('billing.pricingCard.starter.includedSeats'),
|
||||
<Stack key="starter-chats" spacing={0}>
|
||||
<HStack>
|
||||
<Text>2,000 {scopedT('chatsPerMonth')}</Text>
|
||||
<MoreInfoTooltip>{scopedT('chatsTooltip')}</MoreInfoTooltip>
|
||||
<Text>2,000 {t('billing.pricingCard.chatsPerMonth')}</Text>
|
||||
<MoreInfoTooltip>
|
||||
{t('billing.pricingCard.chatsTooltip')}
|
||||
</MoreInfoTooltip>
|
||||
</HStack>
|
||||
<Text
|
||||
fontSize="sm"
|
||||
@ -78,9 +83,9 @@ export const StarterPlanPricingCard = ({
|
||||
Extra chats: $10 per 500
|
||||
</Text>
|
||||
</Stack>,
|
||||
scopedT('starter.brandingRemoved'),
|
||||
scopedT('starter.fileUploadBlock'),
|
||||
scopedT('starter.createFolders'),
|
||||
t('billing.pricingCard.starter.brandingRemoved'),
|
||||
t('billing.pricingCard.starter.fileUploadBlock'),
|
||||
t('billing.pricingCard.starter.createFolders'),
|
||||
]}
|
||||
/>
|
||||
</Stack>
|
||||
|
@ -3,7 +3,7 @@ import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import React from 'react'
|
||||
import { isNotDefined } from '@typebot.io/lib'
|
||||
import { ChangePlanModal } from './ChangePlanModal'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
limitReachedType?: string
|
||||
@ -15,7 +15,7 @@ export const UpgradeButton = ({
|
||||
excludedPlans,
|
||||
...props
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
const { workspace } = useWorkspace()
|
||||
return (
|
||||
|
@ -13,15 +13,15 @@ import { Workspace } from '@typebot.io/prisma'
|
||||
import React from 'react'
|
||||
import { parseNumberWithCommas } from '@typebot.io/lib'
|
||||
import { defaultQueryOptions, trpc } from '@/lib/trpc'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { getChatsLimit } from '@typebot.io/lib/billing/getChatsLimit'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
workspace: Workspace
|
||||
}
|
||||
|
||||
export const UsageProgressBars = ({ workspace }: Props) => {
|
||||
const scopedT = useScopedI18n('billing.usage')
|
||||
const { t } = useTranslate()
|
||||
const { data, isLoading } = trpc.billing.getUsage.useQuery(
|
||||
{
|
||||
workspaceId: workspace.id,
|
||||
@ -39,12 +39,12 @@ export const UsageProgressBars = ({ workspace }: Props) => {
|
||||
|
||||
return (
|
||||
<Stack spacing={6}>
|
||||
<Heading fontSize="3xl">{scopedT('heading')}</Heading>
|
||||
<Heading fontSize="3xl">{t('billing.usage.heading')}</Heading>
|
||||
<Stack spacing={3}>
|
||||
<Flex justifyContent="space-between">
|
||||
<HStack>
|
||||
<Heading fontSize="xl" as="h3">
|
||||
{scopedT('chats.heading')}
|
||||
{t('billing.usage.chats.heading')}
|
||||
</Heading>
|
||||
{chatsPercentage >= 80 && (
|
||||
<Tooltip
|
||||
@ -53,10 +53,10 @@ export const UsageProgressBars = ({ workspace }: Props) => {
|
||||
p="3"
|
||||
label={
|
||||
<Text>
|
||||
{scopedT('chats.alert.soonReach')}
|
||||
{t('billing.usage.chats.alert.soonReach')}
|
||||
<br />
|
||||
<br />
|
||||
{scopedT('chats.alert.updatePlan')}
|
||||
{t('billing.usage.chats.alert.updatePlan')}
|
||||
</Text>
|
||||
}
|
||||
>
|
||||
@ -81,7 +81,7 @@ export const UsageProgressBars = ({ workspace }: Props) => {
|
||||
<Text>
|
||||
/{' '}
|
||||
{workspaceChatsLimit === 'inf'
|
||||
? scopedT('unlimited')
|
||||
? t('billing.usage.unlimited')
|
||||
: parseNumberWithCommas(workspaceChatsLimit)}
|
||||
</Text>
|
||||
</HStack>
|
||||
|
@ -4,7 +4,7 @@ import { TextInput } from '@/components/inputs'
|
||||
import { useState } from 'react'
|
||||
import { UploadButton } from '@/components/ImageUploadContent/UploadButton'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl'
|
||||
|
||||
type Props = {
|
||||
@ -18,7 +18,7 @@ export const AudioBubbleForm = ({
|
||||
content,
|
||||
onContentChange,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.audio.settings')
|
||||
const { t } = useTranslate()
|
||||
const [currentTab, setCurrentTab] = useState<'link' | 'upload'>('link')
|
||||
|
||||
const updateUrl = (url: string) => onContentChange({ ...content, url })
|
||||
@ -34,14 +34,14 @@ export const AudioBubbleForm = ({
|
||||
onClick={() => setCurrentTab('upload')}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('upload.label')}
|
||||
{t('editor.blocks.bubbles.audio.settings.upload.label')}
|
||||
</Button>
|
||||
<Button
|
||||
variant={currentTab === 'link' ? 'solid' : 'ghost'}
|
||||
onClick={() => setCurrentTab('link')}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('embedLink.label')}
|
||||
{t('editor.blocks.bubbles.audio.settings.embedLink.label')}
|
||||
</Button>
|
||||
</HStack>
|
||||
<Stack p="2" spacing={4}>
|
||||
@ -54,25 +54,27 @@ export const AudioBubbleForm = ({
|
||||
onFileUploaded={updateUrl}
|
||||
colorScheme="blue"
|
||||
>
|
||||
{scopedT('chooseFile.label')}
|
||||
{t('editor.blocks.bubbles.audio.settings.chooseFile.label')}
|
||||
</UploadButton>
|
||||
</Flex>
|
||||
)}
|
||||
{currentTab === 'link' && (
|
||||
<>
|
||||
<TextInput
|
||||
placeholder={scopedT('worksWith.placeholder')}
|
||||
placeholder={t(
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.placeholder'
|
||||
)}
|
||||
defaultValue={content.url ?? ''}
|
||||
onChange={updateUrl}
|
||||
/>
|
||||
<Text fontSize="sm" color="gray.400" textAlign="center">
|
||||
{scopedT('worksWith.text')}
|
||||
{t('editor.blocks.bubbles.audio.settings.worksWith.text')}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
<SwitchWithLabel
|
||||
label={scopedT('autoplay.label')}
|
||||
label={t('editor.blocks.bubbles.audio.settings.autoplay.label')}
|
||||
initialValue={content.isAutoplayEnabled ?? true}
|
||||
onCheckChange={updateAutoPlay}
|
||||
/>
|
||||
|
@ -1,17 +1,19 @@
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { AudioBubbleContent } from '@typebot.io/schemas'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
url: AudioBubbleContent['url']
|
||||
}
|
||||
|
||||
export const AudioBubbleNode = ({ url }: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.audio.node')
|
||||
const { t } = useTranslate()
|
||||
return isDefined(url) ? (
|
||||
<audio src={url} controls />
|
||||
) : (
|
||||
<Text color={'gray.500'}>{scopedT('clickToEdit.text')}</Text>
|
||||
<Text color={'gray.500'}>
|
||||
{t('editor.blocks.bubbles.audio.node.clickToEdit.text')}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { EmbedBubbleBlock } from '@typebot.io/schemas'
|
||||
|
||||
@ -7,8 +7,12 @@ type Props = {
|
||||
}
|
||||
|
||||
export const EmbedBubbleContent = ({ block }: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.embed.node')
|
||||
const { t } = useTranslate()
|
||||
if (!block.content?.url)
|
||||
return <Text color="gray.500">{scopedT('clickToEdit.text')}</Text>
|
||||
return <Text>{scopedT('show.text')}</Text>
|
||||
return (
|
||||
<Text color="gray.500">
|
||||
{t('editor.blocks.bubbles.embed.node.clickToEdit.text')}
|
||||
</Text>
|
||||
)
|
||||
return <Text>{t('editor.blocks.bubbles.embed.node.show.text')}</Text>
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { TextInput, NumberInput } from '@/components/inputs'
|
||||
import { Stack, Text } from '@chakra-ui/react'
|
||||
import { EmbedBubbleContent } from '@typebot.io/schemas'
|
||||
import { sanitizeUrl } from '@typebot.io/lib'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
content: EmbedBubbleContent
|
||||
@ -10,7 +10,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const EmbedUploadContent = ({ content, onSubmit }: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.embed.settings')
|
||||
const { t } = useTranslate()
|
||||
const handleUrlChange = (url: string) => {
|
||||
const iframeUrl = sanitizeUrl(
|
||||
url.trim().startsWith('<iframe') ? extractUrlFromIframe(url) : url
|
||||
@ -25,12 +25,14 @@ export const EmbedUploadContent = ({ content, onSubmit }: Props) => {
|
||||
<Stack p="2" spacing={6}>
|
||||
<Stack>
|
||||
<TextInput
|
||||
placeholder={scopedT('worksWith.placeholder')}
|
||||
placeholder={t(
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.placeholder'
|
||||
)}
|
||||
defaultValue={content?.url ?? ''}
|
||||
onChange={handleUrlChange}
|
||||
/>
|
||||
<Text fontSize="sm" color="gray.400" textAlign="center">
|
||||
{scopedT('worksWith.text')}
|
||||
{t('editor.blocks.bubbles.embed.settings.worksWith.text')}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
@ -38,7 +40,7 @@ export const EmbedUploadContent = ({ content, onSubmit }: Props) => {
|
||||
label="Height:"
|
||||
defaultValue={content?.height}
|
||||
onValueChange={handleHeightChange}
|
||||
suffix={scopedT('numberInput.unit')}
|
||||
suffix={t('editor.blocks.bubbles.embed.settings.numberInput.unit')}
|
||||
width="150px"
|
||||
/>
|
||||
</Stack>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Box, Text, Image } from '@chakra-ui/react'
|
||||
import { ImageBubbleBlock } from '@typebot.io/schemas'
|
||||
|
||||
@ -7,11 +7,13 @@ type Props = {
|
||||
}
|
||||
|
||||
export const ImageBubbleContent = ({ block }: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.image.node')
|
||||
const { t } = useTranslate()
|
||||
const containsVariables =
|
||||
block.content?.url?.includes('{{') && block.content.url.includes('}}')
|
||||
return !block.content?.url ? (
|
||||
<Text color={'gray.500'}>{scopedT('clickToEdit.text')}</Text>
|
||||
<Text color={'gray.500'}>
|
||||
{t('editor.blocks.bubbles.image.node.clickToEdit.text')}
|
||||
</Text>
|
||||
) : (
|
||||
<Box w="full">
|
||||
<Image
|
||||
|
@ -2,7 +2,7 @@ import { ImageUploadContent } from '@/components/ImageUploadContent'
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { FilePathUploadProps } from '@/features/upload/api/generateUploadUrl'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Stack } from '@chakra-ui/react'
|
||||
import { isDefined, isNotEmpty } from '@typebot.io/lib'
|
||||
import { ImageBubbleBlock } from '@typebot.io/schemas'
|
||||
@ -19,9 +19,7 @@ export const ImageBubbleSettings = ({
|
||||
block,
|
||||
onContentChange,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n(
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick'
|
||||
)
|
||||
const { t } = useTranslate()
|
||||
const [showClickLinkInput, setShowClickLinkInput] = useState(
|
||||
isNotEmpty(block.content.clickLink?.url)
|
||||
)
|
||||
@ -60,7 +58,7 @@ export const ImageBubbleSettings = ({
|
||||
/>
|
||||
<Stack>
|
||||
<SwitchWithLabel
|
||||
label={scopedT('label')}
|
||||
label={t('editor.blocks.bubbles.image.switchWithLabel.onClick.label')}
|
||||
initialValue={showClickLinkInput}
|
||||
onCheckChange={toggleClickLink}
|
||||
/>
|
||||
@ -73,7 +71,9 @@ export const ImageBubbleSettings = ({
|
||||
defaultValue={block.content.clickLink?.url}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={scopedT('placeholder')}
|
||||
placeholder={t(
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder'
|
||||
)}
|
||||
onChange={updateClickLinkAltText}
|
||||
defaultValue={block.content.clickLink?.alt}
|
||||
/>
|
||||
|
@ -18,7 +18,7 @@ import { colors } from '@/lib/theme'
|
||||
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
||||
import { selectEditor, TElement } from '@udecode/plate-common'
|
||||
import { TextEditorToolBar } from './TextEditorToolBar'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type TextBubbleEditorContentProps = {
|
||||
id: string
|
||||
@ -31,7 +31,7 @@ const TextBubbleEditorContent = ({
|
||||
textEditorValue,
|
||||
onClose,
|
||||
}: TextBubbleEditorContentProps) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles')
|
||||
const { t } = useTranslate()
|
||||
const editor = usePlateEditorRef()
|
||||
const varDropdownRef = useRef<HTMLDivElement | null>(null)
|
||||
const rememberedSelection = useRef<BaseSelection | null>(null)
|
||||
@ -137,7 +137,7 @@ const TextBubbleEditorContent = ({
|
||||
})
|
||||
setIsFirstFocus(false)
|
||||
},
|
||||
'aria-label': `${scopedT('textEditor.plate.label')}`,
|
||||
'aria-label': `${t('editor.blocks.bubbles.textEditor.plate.label')}`,
|
||||
onBlur: () => {
|
||||
rememberedSelection.current = editor?.selection
|
||||
},
|
||||
@ -156,7 +156,9 @@ const TextBubbleEditorContent = ({
|
||||
<VariableSearchInput
|
||||
initialVariableId={undefined}
|
||||
onSelectVariable={handleVariableSelected}
|
||||
placeholder={scopedT('textEditor.searchVariable.placeholder')}
|
||||
placeholder={t(
|
||||
'editor.blocks.bubbles.textEditor.searchVariable.placeholder'
|
||||
)}
|
||||
autoFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Box, Text, Image } from '@chakra-ui/react'
|
||||
import { VideoBubbleBlock, VideoBubbleContentType } from '@typebot.io/schemas'
|
||||
|
||||
@ -7,9 +7,13 @@ type Props = {
|
||||
}
|
||||
|
||||
export const VideoBubbleContent = ({ block }: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.video.node')
|
||||
const { t } = useTranslate()
|
||||
if (!block.content?.url || !block.content.type)
|
||||
return <Text color="gray.500">{scopedT('clickToEdit.text')}</Text>
|
||||
return (
|
||||
<Text color="gray.500">
|
||||
{t('editor.blocks.bubbles.video.node.clickToEdit.text')}
|
||||
</Text>
|
||||
)
|
||||
const containsVariables =
|
||||
block.content?.url?.includes('{{') && block.content.url.includes('}}')
|
||||
switch (block.content.type) {
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
VideoBubbleContentType,
|
||||
} from '@typebot.io/schemas'
|
||||
import { NumberInput, TextInput } from '@/components/inputs'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { parseVideoUrl } from '@typebot.io/lib/parseVideoUrl'
|
||||
|
||||
type Props = {
|
||||
@ -14,7 +14,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const VideoUploadContent = ({ content, onSubmit }: Props) => {
|
||||
const scopedT = useScopedI18n('editor.blocks.bubbles.video.settings')
|
||||
const { t } = useTranslate()
|
||||
const updateUrl = (url: string) => {
|
||||
const info = parseVideoUrl(url)
|
||||
return onSubmit({
|
||||
@ -33,12 +33,14 @@ export const VideoUploadContent = ({ content, onSubmit }: Props) => {
|
||||
<Stack p="2" spacing={4}>
|
||||
<Stack>
|
||||
<TextInput
|
||||
placeholder={scopedT('worksWith.placeholder')}
|
||||
placeholder={t(
|
||||
'editor.blocks.bubbles.video.settings.worksWith.placeholder'
|
||||
)}
|
||||
defaultValue={content?.url ?? ''}
|
||||
onChange={updateUrl}
|
||||
/>
|
||||
<Text fontSize="sm" color="gray.400" textAlign="center">
|
||||
{scopedT('worksWith.text')}
|
||||
{t('editor.blocks.bubbles.video.settings.worksWith.text')}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
@ -47,7 +49,7 @@ export const VideoUploadContent = ({ content, onSubmit }: Props) => {
|
||||
label="Height:"
|
||||
defaultValue={content?.height ?? 400}
|
||||
onValueChange={updateHeight}
|
||||
suffix={scopedT('numberInput.unit')}
|
||||
suffix={t('editor.blocks.bubbles.video.settings.numberInput.unit')}
|
||||
width="150px"
|
||||
/>
|
||||
)}
|
||||
|
@ -3,7 +3,7 @@ import { canReadTypebots } from '@/helpers/databaseRules'
|
||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||
import { TRPCError } from '@trpc/server'
|
||||
import { Group, IntegrationBlockType, Typebot } from '@typebot.io/schemas'
|
||||
import { byId, isWebhookBlock, parseGroupTitle } from '@typebot.io/lib'
|
||||
import { byId, isWebhookBlock } from '@typebot.io/lib'
|
||||
import { z } from 'zod'
|
||||
import { Webhook } from '@typebot.io/prisma'
|
||||
|
||||
@ -70,7 +70,7 @@ export const listWebhookBlocks = authenticatedProcedure
|
||||
...blocks.map((block) => ({
|
||||
id: block.id,
|
||||
type: block.type,
|
||||
label: `${parseGroupTitle(group.title)} > ${block.id}`,
|
||||
label: `${group.title} > ${block.id}`,
|
||||
url: block.options.webhook
|
||||
? block.options.webhook.url
|
||||
: typebot?.webhooks.find(byId(block.webhookId))?.url ?? undefined,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Tag, Text } from '@chakra-ui/react'
|
||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||
import { byId, isDefined, parseGroupTitle } from '@typebot.io/lib'
|
||||
import { byId, isDefined } from '@typebot.io/lib'
|
||||
import { JumpBlock } from '@typebot.io/schemas/features/blocks/logic/jump'
|
||||
|
||||
type Props = {
|
||||
@ -15,8 +15,7 @@ export const JumpNodeBody = ({ options }: Props) => {
|
||||
if (!selectedGroup) return <Text color="gray.500">Configure...</Text>
|
||||
return (
|
||||
<Text>
|
||||
Jump to{' '}
|
||||
<Tag colorScheme="blue">{parseGroupTitle(selectedGroup.title)}</Tag>{' '}
|
||||
Jump to <Tag colorScheme="blue">{selectedGroup.title}</Tag>{' '}
|
||||
{isDefined(blockIndex) && blockIndex >= 0 ? (
|
||||
<>
|
||||
at block <Tag colorScheme="blue">{blockIndex + 1}</Tag>
|
||||
|
@ -3,7 +3,7 @@ import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||
import { Stack } from '@chakra-ui/react'
|
||||
import { JumpBlock } from '@typebot.io/schemas/features/blocks/logic/jump'
|
||||
import React from 'react'
|
||||
import { byId, parseGroupTitle } from '@typebot.io/lib'
|
||||
import { byId } from '@typebot.io/lib'
|
||||
|
||||
type Props = {
|
||||
groupId: string
|
||||
@ -32,7 +32,7 @@ export const JumpSettings = ({ groupId, options, onOptionsChange }: Props) => {
|
||||
items={typebot.groups
|
||||
.filter((group) => group.id !== currentGroupId)
|
||||
.map((group) => ({
|
||||
label: parseGroupTitle(group.title),
|
||||
label: group.title,
|
||||
value: group.id,
|
||||
}))}
|
||||
selectedItem={selectedGroup?.id}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Select } from '@/components/inputs/Select'
|
||||
import { Input } from '@chakra-ui/react'
|
||||
import { Group } from '@typebot.io/schemas'
|
||||
import { parseGroupTitle } from '@typebot.io/lib'
|
||||
|
||||
type Props = {
|
||||
groups: Group[]
|
||||
@ -23,7 +22,7 @@ export const GroupsDropdown = ({
|
||||
<Select
|
||||
selectedItem={groupId}
|
||||
items={(groups ?? []).map((group) => ({
|
||||
label: parseGroupTitle(group.title),
|
||||
label: group.title,
|
||||
value: group.id,
|
||||
}))}
|
||||
onSelect={onGroupIdSelected}
|
||||
|
@ -28,7 +28,11 @@ export const CollaborationMenuButton = ({
|
||||
</Tooltip>
|
||||
</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent shadow="lg" width="430px">
|
||||
<PopoverContent
|
||||
shadow="lg"
|
||||
width="430px"
|
||||
rootProps={{ style: { transform: 'scale(0)' } }}
|
||||
>
|
||||
<CollaborationList />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
@ -5,13 +5,13 @@ import { useUser } from '@/features/account/hooks/useUser'
|
||||
import { isNotDefined } from '@typebot.io/lib'
|
||||
import Link from 'next/link'
|
||||
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { WorkspaceDropdown } from '@/features/workspace/components/WorkspaceDropdown'
|
||||
import { WorkspaceSettingsModal } from '@/features/workspace/components/WorkspaceSettingsModal'
|
||||
|
||||
export const DashboardHeader = () => {
|
||||
const scopedT = useScopedI18n('dashboard.header')
|
||||
const { t } = useTranslate()
|
||||
const { user, logOut } = useUser()
|
||||
const { workspace, switchWorkspace, createWorkspace } = useWorkspace()
|
||||
|
||||
@ -50,7 +50,7 @@ export const DashboardHeader = () => {
|
||||
onClick={onOpen}
|
||||
isLoading={isNotDefined(workspace)}
|
||||
>
|
||||
{scopedT('settingsButton.label')}
|
||||
{t('dashboard.header.settingsButton.label')}
|
||||
</Button>
|
||||
<WorkspaceDropdown
|
||||
currentWorkspace={workspace}
|
||||
|
@ -5,7 +5,6 @@ import {
|
||||
PreCheckoutModalProps,
|
||||
} from '@/features/billing/components/PreCheckoutModal'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { Stack, VStack, Spinner, Text } from '@chakra-ui/react'
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import { useRouter } from 'next/router'
|
||||
@ -16,9 +15,10 @@ import { TypebotDndProvider } from '@/features/folders/TypebotDndProvider'
|
||||
import { ParentModalProvider } from '@/features/graph/providers/ParentModalProvider'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { guessIfUserIsEuropean } from '@typebot.io/lib/billing/guessIfUserIsEuropean'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const DashboardPage = () => {
|
||||
const scopedT = useScopedI18n('dashboard')
|
||||
const { t } = useTranslate()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const router = useRouter()
|
||||
const { user } = useUser()
|
||||
@ -58,7 +58,7 @@ export const DashboardPage = () => {
|
||||
|
||||
return (
|
||||
<Stack minH="100vh">
|
||||
<Seo title={workspace?.name ?? scopedT('title')} />
|
||||
<Seo title={workspace?.name ?? t('dashboard.title')} />
|
||||
<DashboardHeader />
|
||||
{!workspace?.stripeId && (
|
||||
<ParentModalProvider>
|
||||
@ -73,7 +73,7 @@ export const DashboardPage = () => {
|
||||
<TypebotDndProvider>
|
||||
{isLoading ? (
|
||||
<VStack w="full" justifyContent="center" pt="10" spacing={6}>
|
||||
<Text>{scopedT('redirectionMessage')}</Text>
|
||||
<Text>{t('dashboard.redirectionMessage')}</Text>
|
||||
<Spinner />
|
||||
</VStack>
|
||||
) : (
|
||||
|
@ -14,7 +14,7 @@ import { Plan } from '@typebot.io/prisma'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { BlockLabel } from './BlockLabel'
|
||||
import { LockTag } from '@/features/billing/components/LockTag'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
type: DraggableBlockType
|
||||
@ -27,7 +27,7 @@ type Props = {
|
||||
export const BlockCard = (
|
||||
props: Pick<Props, 'type' | 'onMouseDown'>
|
||||
): JSX.Element => {
|
||||
const scopedT = useScopedI18n('editor.blockCard')
|
||||
const { t } = useTranslate()
|
||||
const { workspace } = useWorkspace()
|
||||
|
||||
switch (props.type) {
|
||||
@ -35,7 +35,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('bubbleBlock.tooltip.label')}
|
||||
tooltip={t('blocks.bubbles.embed.blockCard.tooltip')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<BlockLabel type={props.type} />
|
||||
@ -45,7 +45,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('inputBlock.tooltip.files.label')}
|
||||
tooltip={t('blocks.inputs.fileUpload.blockCard.tooltip')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<HStack>
|
||||
@ -58,7 +58,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('logicBlock.tooltip.code.label')}
|
||||
tooltip={t('editor.blockCard.logicBlock.tooltip.code.label')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<BlockLabel type={props.type} />
|
||||
@ -68,7 +68,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('logicBlock.tooltip.typebotLink.label')}
|
||||
tooltip={t('editor.blockCard.logicBlock.tooltip.typebotLink.label')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<BlockLabel type={props.type} />
|
||||
@ -78,7 +78,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('logicBlock.tooltip.jump.label')}
|
||||
tooltip={t('editor.blockCard.logicBlock.tooltip.jump.label')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<BlockLabel type={props.type} />
|
||||
@ -88,7 +88,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('integrationBlock.tooltip.googleSheets.label')}
|
||||
tooltip={t('blocks.integrations.googleSheets.blockCard.tooltip')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<BlockLabel type={props.type} />
|
||||
@ -98,7 +98,7 @@ export const BlockCard = (
|
||||
return (
|
||||
<BlockCardLayout
|
||||
{...props}
|
||||
tooltip={scopedT('integrationBlock.tooltip.googleAnalytics.label')}
|
||||
tooltip={t('blocks.integrations.googleAnalytics.blockCard.tooltip')}
|
||||
>
|
||||
<BlockIcon type={props.type} />
|
||||
<BlockLabel type={props.type} />
|
||||
|
@ -7,84 +7,98 @@ import {
|
||||
BlockType,
|
||||
} from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = { type: BlockType }
|
||||
|
||||
export const BlockLabel = ({ type }: Props): JSX.Element => {
|
||||
const scopedT = useScopedI18n('editor.sidebarBlock')
|
||||
const { t } = useTranslate()
|
||||
|
||||
switch (type) {
|
||||
case 'start':
|
||||
return <Text fontSize="sm">{scopedT('start.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.start.label')}</Text>
|
||||
case BubbleBlockType.TEXT:
|
||||
case InputBlockType.TEXT:
|
||||
return <Text fontSize="sm">{scopedT('text.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.text.label')}</Text>
|
||||
case BubbleBlockType.IMAGE:
|
||||
return <Text fontSize="sm">{scopedT('image.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.image.label')}</Text>
|
||||
case BubbleBlockType.VIDEO:
|
||||
return <Text fontSize="sm">{scopedT('video.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.video.label')}</Text>
|
||||
case BubbleBlockType.EMBED:
|
||||
return <Text fontSize="sm">{scopedT('embed.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.embed.label')}</Text>
|
||||
case BubbleBlockType.AUDIO:
|
||||
return <Text fontSize="sm">{scopedT('audio.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.audio.label')}</Text>
|
||||
case InputBlockType.NUMBER:
|
||||
return <Text fontSize="sm">{scopedT('number.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.number.label')}</Text>
|
||||
case InputBlockType.EMAIL:
|
||||
return <Text fontSize="sm">{scopedT('email.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.email.label')}</Text>
|
||||
case InputBlockType.URL:
|
||||
return <Text fontSize="sm">{scopedT('website.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.website.label')}</Text>
|
||||
case InputBlockType.DATE:
|
||||
return <Text fontSize="sm">{scopedT('date.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.date.label')}</Text>
|
||||
case InputBlockType.PHONE:
|
||||
return <Text fontSize="sm">{scopedT('phone.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.phone.label')}</Text>
|
||||
case InputBlockType.CHOICE:
|
||||
return <Text fontSize="sm">{scopedT('button.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.button.label')}</Text>
|
||||
case InputBlockType.PICTURE_CHOICE:
|
||||
return <Text fontSize="sm">{scopedT('picChoice.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.picChoice.label')}</Text>
|
||||
)
|
||||
case InputBlockType.PAYMENT:
|
||||
return <Text fontSize="sm">{scopedT('payment.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.payment.label')}</Text>
|
||||
case InputBlockType.RATING:
|
||||
return <Text fontSize="sm">{scopedT('rating.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.rating.label')}</Text>
|
||||
case InputBlockType.FILE:
|
||||
return <Text fontSize="sm">{scopedT('file.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.file.label')}</Text>
|
||||
case LogicBlockType.SET_VARIABLE:
|
||||
return <Text fontSize="sm">{scopedT('setVariable.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.setVariable.label')}</Text>
|
||||
)
|
||||
case LogicBlockType.CONDITION:
|
||||
return <Text fontSize="sm">{scopedT('condition.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.condition.label')}</Text>
|
||||
)
|
||||
case LogicBlockType.REDIRECT:
|
||||
return <Text fontSize="sm">{scopedT('redirect.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.redirect.label')}</Text>
|
||||
)
|
||||
case LogicBlockType.SCRIPT:
|
||||
return <Text fontSize="sm">{scopedT('script.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.script.label')}</Text>
|
||||
case LogicBlockType.TYPEBOT_LINK:
|
||||
return <Text fontSize="sm">{scopedT('typebot.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.typebot.label')}</Text>
|
||||
case LogicBlockType.WAIT:
|
||||
return <Text fontSize="sm">{scopedT('wait.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.wait.label')}</Text>
|
||||
case LogicBlockType.JUMP:
|
||||
return <Text fontSize="sm">{scopedT('jump.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.jump.label')}</Text>
|
||||
case LogicBlockType.AB_TEST:
|
||||
return <Text fontSize="sm">{scopedT('abTest.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.abTest.label')}</Text>
|
||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||
return <Text fontSize="sm">{scopedT('sheets.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.sheets.label')}</Text>
|
||||
case IntegrationBlockType.GOOGLE_ANALYTICS:
|
||||
return <Text fontSize="sm">{scopedT('analytics.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.analytics.label')}</Text>
|
||||
)
|
||||
case IntegrationBlockType.WEBHOOK:
|
||||
return <Text fontSize="sm">{scopedT('webhook.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.webhook.label')}</Text>
|
||||
case IntegrationBlockType.ZAPIER:
|
||||
return <Text fontSize="sm">{scopedT('zapier.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.zapier.label')}</Text>
|
||||
case IntegrationBlockType.MAKE_COM:
|
||||
return <Text fontSize="sm">{scopedT('makecom.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.makecom.label')}</Text>
|
||||
case IntegrationBlockType.PABBLY_CONNECT:
|
||||
return <Text fontSize="sm">{scopedT('pabbly.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.pabbly.label')}</Text>
|
||||
case IntegrationBlockType.EMAIL:
|
||||
return <Text fontSize="sm">{scopedT('email.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.email.label')}</Text>
|
||||
case IntegrationBlockType.CHATWOOT:
|
||||
return <Text fontSize="sm">{scopedT('chatwoot.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.chatwoot.label')}</Text>
|
||||
)
|
||||
case IntegrationBlockType.OPEN_AI:
|
||||
return <Text fontSize="sm">{scopedT('openai.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.openai.label')}</Text>
|
||||
case IntegrationBlockType.PIXEL:
|
||||
return <Text fontSize="sm">{scopedT('pixel.label')}</Text>
|
||||
return <Text fontSize="sm">{t('editor.sidebarBlock.pixel.label')}</Text>
|
||||
case IntegrationBlockType.ZEMANTIC_AI:
|
||||
return <Text fontSize="sm">{scopedT('zemanticAi.label')}</Text>
|
||||
return (
|
||||
<Text fontSize="sm">{t('editor.sidebarBlock.zemanticAi.label')}</Text>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -23,10 +23,10 @@ import { BlockCard } from './BlockCard'
|
||||
import { LockedIcon, UnlockedIcon } from '@/components/icons'
|
||||
import { BlockCardOverlay } from './BlockCardOverlay'
|
||||
import { headerHeight } from '../constants'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const BlocksSideBar = () => {
|
||||
const scopedT = useScopedI18n('editor.sidebarBlocks')
|
||||
const { t } = useTranslate()
|
||||
const { setDraggedBlockType, draggedBlockType } = useBlockDnd()
|
||||
const [position, setPosition] = useState({
|
||||
x: 0,
|
||||
@ -107,16 +107,16 @@ export const BlocksSideBar = () => {
|
||||
<Tooltip
|
||||
label={
|
||||
isLocked
|
||||
? scopedT('sidebar.unlock.label')
|
||||
: scopedT('sidebar.lock.label')
|
||||
? t('editor.sidebarBlocks.sidebar.unlock.label')
|
||||
: t('editor.sidebarBlocks.sidebar.lock.label')
|
||||
}
|
||||
>
|
||||
<IconButton
|
||||
icon={isLocked ? <LockedIcon /> : <UnlockedIcon />}
|
||||
aria-label={
|
||||
isLocked
|
||||
? scopedT('sidebar.icon.unlock.label')
|
||||
: scopedT('sidebar.icon.lock.label')
|
||||
? t('editor.sidebarBlocks.sidebar.icon.unlock.label')
|
||||
: t('editor.sidebarBlocks.sidebar.icon.lock.label')
|
||||
}
|
||||
size="sm"
|
||||
onClick={handleLockClick}
|
||||
@ -126,7 +126,7 @@ export const BlocksSideBar = () => {
|
||||
|
||||
<Stack>
|
||||
<Text fontSize="sm" fontWeight="semibold">
|
||||
{scopedT('blockType.bubbles.heading')}
|
||||
{t('editor.sidebarBlocks.blockType.bubbles.heading')}
|
||||
</Text>
|
||||
<SimpleGrid columns={2} spacing="3">
|
||||
{Object.values(BubbleBlockType).map((type) => (
|
||||
@ -137,7 +137,7 @@ export const BlocksSideBar = () => {
|
||||
|
||||
<Stack>
|
||||
<Text fontSize="sm" fontWeight="semibold">
|
||||
{scopedT('blockType.inputs.heading')}
|
||||
{t('editor.sidebarBlocks.blockType.inputs.heading')}
|
||||
</Text>
|
||||
<SimpleGrid columns={2} spacing="3">
|
||||
{Object.values(InputBlockType).map((type) => (
|
||||
@ -148,7 +148,7 @@ export const BlocksSideBar = () => {
|
||||
|
||||
<Stack>
|
||||
<Text fontSize="sm" fontWeight="semibold">
|
||||
{scopedT('blockType.logic.heading')}
|
||||
{t('editor.sidebarBlocks.blockType.logic.heading')}
|
||||
</Text>
|
||||
<SimpleGrid columns={2} spacing="3">
|
||||
{Object.values(LogicBlockType).map((type) => (
|
||||
@ -159,7 +159,7 @@ export const BlocksSideBar = () => {
|
||||
|
||||
<Stack>
|
||||
<Text fontSize="sm" fontWeight="semibold">
|
||||
{scopedT('blockType.integrations.heading')}
|
||||
{t('editor.sidebarBlocks.blockType.integrations.heading')}
|
||||
</Text>
|
||||
<SimpleGrid columns={2} spacing="3">
|
||||
{Object.values(IntegrationBlockType).map((type) => (
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react'
|
||||
import React, { useState } from 'react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type EditableProps = {
|
||||
defaultName: string
|
||||
@ -16,7 +16,7 @@ export const EditableTypebotName = ({
|
||||
defaultName,
|
||||
onNewName,
|
||||
}: EditableProps) => {
|
||||
const scopedT = useScopedI18n('editor.editableTypebotName')
|
||||
const { t } = useTranslate()
|
||||
const emptyNameBg = useColorModeValue('gray.100', 'gray.700')
|
||||
const [currentName, setCurrentName] = useState(defaultName)
|
||||
|
||||
@ -27,7 +27,7 @@ export const EditableTypebotName = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip label={scopedT('tooltip.rename.label')}>
|
||||
<Tooltip label={t('editor.editableTypebotName.tooltip.rename.label')}>
|
||||
<Editable
|
||||
value={currentName}
|
||||
onChange={setCurrentName}
|
||||
|
@ -21,10 +21,10 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const GettingStartedModal = () => {
|
||||
const scopedT = useScopedI18n('editor.gettingStartedModal')
|
||||
const { t } = useTranslate()
|
||||
const { query } = useRouter()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
|
||||
@ -40,7 +40,9 @@ export const GettingStartedModal = () => {
|
||||
<ModalCloseButton />
|
||||
<ModalBody as={Stack} spacing="8" py="10">
|
||||
<Stack spacing={4}>
|
||||
<Heading fontSize="xl">{scopedT('editorBasics.heading')}</Heading>
|
||||
<Heading fontSize="xl">
|
||||
{t('editor.gettingStartedModal.editorBasics.heading')}
|
||||
</Heading>
|
||||
<List spacing={4}>
|
||||
<HStack as={ListItem}>
|
||||
<Flex
|
||||
@ -56,7 +58,9 @@ export const GettingStartedModal = () => {
|
||||
>
|
||||
1
|
||||
</Flex>
|
||||
<Text>{scopedT('editorBasics.list.one.label')}</Text>
|
||||
<Text>
|
||||
{t('editor.gettingStartedModal.editorBasics.list.one.label')}
|
||||
</Text>
|
||||
</HStack>
|
||||
<HStack as={ListItem}>
|
||||
<Flex
|
||||
@ -72,7 +76,9 @@ export const GettingStartedModal = () => {
|
||||
>
|
||||
2
|
||||
</Flex>
|
||||
<Text>{scopedT('editorBasics.list.two.label')}</Text>
|
||||
<Text>
|
||||
{t('editor.gettingStartedModal.editorBasics.list.two.label')}
|
||||
</Text>
|
||||
</HStack>
|
||||
<HStack as={ListItem}>
|
||||
<Flex
|
||||
@ -88,7 +94,11 @@ export const GettingStartedModal = () => {
|
||||
>
|
||||
3
|
||||
</Flex>
|
||||
<Text>{scopedT('editorBasics.list.three.label')}</Text>
|
||||
<Text>
|
||||
{t(
|
||||
'editor.gettingStartedModal.editorBasics.list.three.label'
|
||||
)}
|
||||
</Text>
|
||||
</HStack>
|
||||
<HStack as={ListItem}>
|
||||
<Flex
|
||||
@ -104,15 +114,18 @@ export const GettingStartedModal = () => {
|
||||
>
|
||||
4
|
||||
</Flex>
|
||||
<Text>{scopedT('editorBasics.list.four.label')}</Text>
|
||||
<Text>
|
||||
{t('editor.gettingStartedModal.editorBasics.list.four.label')}
|
||||
</Text>
|
||||
</HStack>
|
||||
</List>
|
||||
</Stack>
|
||||
|
||||
<Text>{scopedT('editorBasics.list.label')}</Text>
|
||||
<Text>{t('editor.gettingStartedModal.editorBasics.list.label')}</Text>
|
||||
<Stack spacing={4}>
|
||||
<Heading fontSize="xl">
|
||||
{scopedT('seeAction.label')} ({`<`} {scopedT('seeAction.time')})
|
||||
{t('editor.gettingStartedModal.seeAction.label')} ({`<`}{' '}
|
||||
{t('editor.gettingStartedModal.seeAction.time')})
|
||||
</Heading>
|
||||
<iframe
|
||||
width="100%"
|
||||
@ -127,7 +140,7 @@ export const GettingStartedModal = () => {
|
||||
<AccordionItem>
|
||||
<AccordionButton>
|
||||
<Box flex="1" textAlign="left">
|
||||
{scopedT('seeAction.item.label')}
|
||||
{t('editor.gettingStartedModal.seeAction.item.label')}
|
||||
</Box>
|
||||
<AccordionIcon />
|
||||
</AccordionButton>
|
||||
|
@ -30,10 +30,10 @@ import { RightPanel, useEditor } from '../providers/EditorProvider'
|
||||
import { useTypebot } from '../providers/TypebotProvider'
|
||||
import { SupportBubble } from '@/components/SupportBubble'
|
||||
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const TypebotHeader = () => {
|
||||
const scopedT = useScopedI18n('editor.headers')
|
||||
const { t } = useTranslate()
|
||||
const router = useRouter()
|
||||
const {
|
||||
typebot,
|
||||
@ -105,7 +105,7 @@ export const TypebotHeader = () => {
|
||||
variant={router.pathname.includes('/edit') ? 'outline' : 'ghost'}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('flowButton.label')}
|
||||
{t('editor.headers.flowButton.label')}
|
||||
</Button>
|
||||
<Button
|
||||
as={Link}
|
||||
@ -114,7 +114,7 @@ export const TypebotHeader = () => {
|
||||
variant={router.pathname.endsWith('theme') ? 'outline' : 'ghost'}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('themeButton.label')}
|
||||
{t('editor.headers.themeButton.label')}
|
||||
</Button>
|
||||
<Button
|
||||
as={Link}
|
||||
@ -123,7 +123,7 @@ export const TypebotHeader = () => {
|
||||
variant={router.pathname.endsWith('settings') ? 'outline' : 'ghost'}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('settingsButton.label')}
|
||||
{t('editor.headers.settingsButton.label')}
|
||||
</Button>
|
||||
<Button
|
||||
as={Link}
|
||||
@ -132,7 +132,7 @@ export const TypebotHeader = () => {
|
||||
variant={router.pathname.endsWith('share') ? 'outline' : 'ghost'}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('shareButton.label')}
|
||||
{t('editor.headers.shareButton.label')}
|
||||
</Button>
|
||||
{isDefined(publishedTypebot) && (
|
||||
<Button
|
||||
@ -142,7 +142,7 @@ export const TypebotHeader = () => {
|
||||
variant={router.pathname.includes('results') ? 'outline' : 'ghost'}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('resultsButton.label')}
|
||||
{t('editor.headers.resultsButton.label')}
|
||||
</Button>
|
||||
)}
|
||||
</HStack>
|
||||
@ -225,21 +225,23 @@ export const TypebotHeader = () => {
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
<Button leftIcon={<BuoyIcon />} onClick={handleHelpClick} size="sm">
|
||||
{scopedT('helpButton.label')}
|
||||
{t('editor.headers.helpButton.label')}
|
||||
</Button>
|
||||
</HStack>
|
||||
{isSavingLoading && (
|
||||
<HStack>
|
||||
<Spinner speed="0.7s" size="sm" color="gray.400" />
|
||||
<Text fontSize="sm" color="gray.400">
|
||||
{scopedT('savingSpinner.label')}
|
||||
{t('editor.headers.savingSpinner.label')}
|
||||
</Text>
|
||||
</HStack>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<HStack right="40px" pos="absolute" display={['none', 'flex']}>
|
||||
<CollaborationMenuButton isLoading={isNotDefined(typebot)} />
|
||||
<Flex pos="relative">
|
||||
<CollaborationMenuButton isLoading={isNotDefined(typebot)} />
|
||||
</Flex>
|
||||
{router.pathname.includes('/edit') && isNotDefined(rightPanel) && (
|
||||
<Button
|
||||
colorScheme="gray"
|
||||
@ -247,7 +249,7 @@ export const TypebotHeader = () => {
|
||||
isLoading={isNotDefined(typebot)}
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('previewButton.label')}
|
||||
{t('editor.headers.previewButton.label')}
|
||||
</Button>
|
||||
)}
|
||||
<PublishButton size="sm" />
|
||||
|
@ -23,7 +23,6 @@ import { areTypebotsEqual } from '@/features/publish/helpers/areTypebotsEqual'
|
||||
import { isPublished as isPublishedHelper } from '@/features/publish/helpers/isPublished'
|
||||
import { convertPublicTypebotToTypebot } from '@/features/publish/helpers/convertPublicTypebotToTypebot'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
|
||||
const autoSaveTimeout = 10000
|
||||
|
||||
@ -80,7 +79,6 @@ export const TypebotProvider = ({
|
||||
children: ReactNode
|
||||
typebotId?: string
|
||||
}) => {
|
||||
const scopedT = useScopedI18n('editor.provider')
|
||||
const { push } = useRouter()
|
||||
const { showToast } = useToast()
|
||||
|
||||
@ -96,15 +94,11 @@ export const TypebotProvider = ({
|
||||
if (error.data?.httpStatus === 404) {
|
||||
showToast({
|
||||
status: 'info',
|
||||
description: scopedT('messages.getTypebotError.description'),
|
||||
description: "Couldn't find typebot.",
|
||||
})
|
||||
push('/typebots')
|
||||
return
|
||||
}
|
||||
showToast({
|
||||
title: scopedT('messages.getTypebotError.title'),
|
||||
description: error.message,
|
||||
})
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -114,13 +108,6 @@ export const TypebotProvider = ({
|
||||
{ typebotId: typebotId as string },
|
||||
{
|
||||
enabled: isDefined(typebotId),
|
||||
onError: (error) => {
|
||||
if (error.data?.httpStatus === 404) return
|
||||
showToast({
|
||||
title: scopedT('messages.publishedTypebotError.title'),
|
||||
description: error.message,
|
||||
})
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@ -128,7 +115,7 @@ export const TypebotProvider = ({
|
||||
trpc.typebot.updateTypebot.useMutation({
|
||||
onError: (error) =>
|
||||
showToast({
|
||||
title: scopedT('messages.updateTypebotError.title'),
|
||||
title: 'Error while updating typebot',
|
||||
description: error.message,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
@ -264,10 +251,7 @@ export const TypebotProvider = ({
|
||||
isPublished,
|
||||
updateTypebot: updateLocalTypebot,
|
||||
restorePublishedTypebot,
|
||||
...groupsActions(
|
||||
setLocalTypebot as SetTypebot,
|
||||
scopedT('groups.copy.title')
|
||||
),
|
||||
...groupsActions(setLocalTypebot as SetTypebot),
|
||||
...blocksAction(setLocalTypebot as SetTypebot),
|
||||
...variablesAction(setLocalTypebot as SetTypebot),
|
||||
...edgesAction(setLocalTypebot as SetTypebot),
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
createBlockDraft,
|
||||
duplicateBlockDraft,
|
||||
} from './blocks'
|
||||
import { isEmpty, parseGroupTitle } from '@typebot.io/lib'
|
||||
import { isEmpty } from '@typebot.io/lib'
|
||||
import { Coordinates } from '@/features/graph/types'
|
||||
|
||||
export type GroupsActions = {
|
||||
@ -28,10 +28,7 @@ export type GroupsActions = {
|
||||
deleteGroup: (groupIndex: number) => void
|
||||
}
|
||||
|
||||
const groupsActions = (
|
||||
setTypebot: SetTypebot,
|
||||
groupCopyLabel: string
|
||||
): GroupsActions => ({
|
||||
const groupsActions = (setTypebot: SetTypebot): GroupsActions => ({
|
||||
createGroup: ({
|
||||
id,
|
||||
block,
|
||||
@ -67,11 +64,19 @@ const groupsActions = (
|
||||
const group = typebot.groups[groupIndex]
|
||||
const id = createId()
|
||||
|
||||
const totalGroupsWithSameTitle = typebot.groups.filter(
|
||||
(group) => group.title === group.title
|
||||
).length
|
||||
|
||||
const newGroup: Group = {
|
||||
...group,
|
||||
title: isEmpty(group.title)
|
||||
? ''
|
||||
: `${parseGroupTitle(group.title)} ${groupCopyLabel}`,
|
||||
: `${group.title}${
|
||||
totalGroupsWithSameTitle > 0
|
||||
? ` (${totalGroupsWithSameTitle})`
|
||||
: ''
|
||||
}}`,
|
||||
id,
|
||||
blocks: group.blocks.map((block) => duplicateBlockDraft(id)(block)),
|
||||
graphCoordinates: {
|
||||
|
@ -3,10 +3,10 @@ import { ChevronLeftIcon } from '@/components/icons'
|
||||
import { useTypebotDnd } from '../TypebotDndProvider'
|
||||
import Link from 'next/link'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const BackButton = ({ id }: { id: string | null }) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
||||
useTypebotDnd()
|
||||
|
||||
|
@ -3,14 +3,14 @@ import { PlusIcon } from '@/components/icons'
|
||||
import { useRouter } from 'next/router'
|
||||
import { stringify } from 'qs'
|
||||
import React from 'react'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const CreateBotButton = ({
|
||||
folderId,
|
||||
isFirstBot,
|
||||
...props
|
||||
}: { folderId?: string; isFirstBot: boolean } & ButtonProps) => {
|
||||
const scopedT = useScopedI18n('folders.createTypebotButton')
|
||||
const { t } = useTranslate()
|
||||
const router = useRouter()
|
||||
|
||||
const handleClick = () =>
|
||||
@ -39,7 +39,7 @@ export const CreateBotButton = ({
|
||||
textAlign="center"
|
||||
mt="6"
|
||||
>
|
||||
{scopedT('label')}
|
||||
{t('folders.createTypebotButton.label')}
|
||||
</Text>
|
||||
</VStack>
|
||||
</Button>
|
||||
|
@ -3,16 +3,15 @@ import { FolderPlusIcon } from '@/components/icons'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import React from 'react'
|
||||
import { useI18n, useScopedI18n } from '@/locales'
|
||||
import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||
import { LockTag } from '@/features/billing/components/LockTag'
|
||||
import { isFreePlan } from '@/features/billing/helpers/isFreePlan'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = { isLoading: boolean; onClick: () => void }
|
||||
|
||||
export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
||||
const t = useI18n()
|
||||
const scopedT = useScopedI18n('folders.createFolderButton')
|
||||
const { t } = useTranslate()
|
||||
const { workspace } = useWorkspace()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
|
||||
@ -27,7 +26,7 @@ export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
|
||||
isLoading={isLoading}
|
||||
>
|
||||
<HStack>
|
||||
<Text>{scopedT('label')}</Text>
|
||||
<Text>{t('folders.createFolderButton.label')}</Text>
|
||||
{isFreePlan(workspace) && <LockTag plan={Plan.STARTER} />}
|
||||
</HStack>
|
||||
<ChangePlanModal
|
||||
|
@ -24,8 +24,8 @@ import { useRouter } from 'next/router'
|
||||
import React, { useMemo } from 'react'
|
||||
import { deleteFolderQuery } from '../queries/deleteFolderQuery'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { useI18n, useScopedI18n } from '@/locales'
|
||||
import { updateFolderQuery } from '../queries/updateFolderQuery'
|
||||
import { T, useTranslate } from '@tolgee/react'
|
||||
|
||||
export const FolderButton = ({
|
||||
folder,
|
||||
@ -36,8 +36,7 @@ export const FolderButton = ({
|
||||
onFolderDeleted: () => void
|
||||
onFolderRenamed: (newName: string) => void
|
||||
}) => {
|
||||
const t = useI18n()
|
||||
const scopedT = useScopedI18n('folders.folderButton')
|
||||
const { t } = useTranslate()
|
||||
const router = useRouter()
|
||||
const { draggedTypebot, setMouseOverFolderId, mouseOverFolderId } =
|
||||
useTypebotDnd()
|
||||
@ -140,9 +139,12 @@ export const FolderButton = ({
|
||||
confirmButtonLabel={'Delete'}
|
||||
message={
|
||||
<Text>
|
||||
{scopedT('deleteConfirmationMessage', {
|
||||
folderName: <strong>{folder.name}</strong>,
|
||||
})}
|
||||
<T
|
||||
keyName="folders.folderButton.deleteConfirmationMessage"
|
||||
params={{
|
||||
strong: <strong>{folder.name}</strong>,
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
}
|
||||
title={`Delete ${folder.name}?`}
|
||||
|
@ -21,7 +21,7 @@ import { CreateFolderButton } from './CreateFolderButton'
|
||||
import { ButtonSkeleton, FolderButton } from './FolderButton'
|
||||
import { TypebotButton } from './TypebotButton'
|
||||
import { TypebotCardOverlay } from './TypebotButtonOverlay'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { useTypebots } from '@/features/dashboard/hooks/useTypebots'
|
||||
import { TypebotInDashboard } from '@/features/dashboard/types'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
@ -31,7 +31,7 @@ type Props = { folder: DashboardFolder | null }
|
||||
const dragDistanceTolerance = 20
|
||||
|
||||
export const FolderContent = ({ folder }: Props) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { workspace, currentRole } = useWorkspace()
|
||||
const [isCreatingFolder, setIsCreatingFolder] = useState(false)
|
||||
const {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Seo } from '@/components/Seo'
|
||||
import { DashboardHeader } from '@/features/dashboard/components/DashboardHeader'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { Stack, Flex, Spinner } from '@chakra-ui/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useFolder } from '../hooks/useFolder'
|
||||
@ -9,7 +9,7 @@ import { TypebotDndProvider } from '../TypebotDndProvider'
|
||||
import { FolderContent } from './FolderContent'
|
||||
|
||||
export const FolderPage = () => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const router = useRouter()
|
||||
|
||||
const { showToast } = useToast()
|
||||
|
@ -21,7 +21,7 @@ import { useDebounce } from 'use-debounce'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { MoreButton } from './MoreButton'
|
||||
import { EmojiOrImageIcon } from '@/components/EmojiOrImageIcon'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { T, useTranslate } from '@tolgee/react'
|
||||
import { TypebotInDashboard } from '@/features/dashboard/types'
|
||||
import { isMobile } from '@/helpers/isMobile'
|
||||
import { trpc, trpcVanilla } from '@/lib/trpc'
|
||||
@ -40,7 +40,7 @@ export const TypebotButton = ({
|
||||
onTypebotUpdated,
|
||||
onMouseDown,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('folders.typebotButton')
|
||||
const { t } = useTranslate()
|
||||
const router = useRouter()
|
||||
const { draggedTypebot } = useTypebotDnd()
|
||||
const [draggedTypebotDebounced] = useDebounce(draggedTypebot, 200)
|
||||
@ -149,7 +149,7 @@ export const TypebotButton = ({
|
||||
top="27px"
|
||||
size="sm"
|
||||
>
|
||||
{scopedT('live')}
|
||||
{t('folders.typebotButton.live')}
|
||||
</Tag>
|
||||
)}
|
||||
{!isReadOnly && (
|
||||
@ -169,18 +169,18 @@ export const TypebotButton = ({
|
||||
pos="absolute"
|
||||
top="20px"
|
||||
right="20px"
|
||||
aria-label={scopedT('showMoreOptions')}
|
||||
aria-label={t('folders.typebotButton.showMoreOptions')}
|
||||
>
|
||||
{typebot.publishedTypebotId && (
|
||||
<MenuItem onClick={handleUnpublishClick}>
|
||||
{scopedT('unpublish')}
|
||||
{t('folders.typebotButton.unpublish')}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={handleDuplicateClick}>
|
||||
{scopedT('duplicate')}
|
||||
{t('folders.typebotButton.duplicate')}
|
||||
</MenuItem>
|
||||
<MenuItem color="red.400" onClick={handleDeleteClick}>
|
||||
{scopedT('delete')}
|
||||
{t('folders.typebotButton.delete')}
|
||||
</MenuItem>
|
||||
</MoreButton>
|
||||
</>
|
||||
@ -203,13 +203,16 @@ export const TypebotButton = ({
|
||||
message={
|
||||
<Stack spacing="4">
|
||||
<Text>
|
||||
{scopedT('deleteConfirmationMessage', {
|
||||
typebotName: <strong>{typebot.name}</strong>,
|
||||
})}
|
||||
<T
|
||||
keyName="folders.typebotButton.deleteConfirmationMessage"
|
||||
params={{
|
||||
strong: <strong>{typebot.name}</strong>,
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
<Alert status="warning">
|
||||
<AlertIcon />
|
||||
{scopedT('deleteConfirmationMessageWarning')}
|
||||
{t('folders.typebotButton.deleteConfirmationMessageWarning')}
|
||||
</Alert>
|
||||
</Stack>
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ import { ChatwootNodeBody } from '@/features/blocks/integrations/chatwoot/compon
|
||||
import { AbTestNodeBody } from '@/features/blocks/logic/abTest/components/AbTestNodeBody'
|
||||
import { PictureChoiceNode } from '@/features/blocks/inputs/pictureChoice/components/PictureChoiceNode'
|
||||
import { PixelNodeBody } from '@/features/blocks/integrations/pixel/components/PixelNodeBody'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { ZemanticAiNodeBody } from '@/features/blocks/integrations/zemanticAi/ZemanticAiNodeBody'
|
||||
|
||||
type Props = {
|
||||
@ -50,7 +50,7 @@ type Props = {
|
||||
indices: BlockIndices
|
||||
}
|
||||
export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
|
||||
const scopedT = useScopedI18n('editor.blocks.start')
|
||||
const { t } = useTranslate()
|
||||
switch (block.type) {
|
||||
case BubbleBlockType.TEXT: {
|
||||
return <TextBubbleContent block={block} />
|
||||
@ -201,7 +201,7 @@ export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
|
||||
return <ZemanticAiNodeBody options={block.options} />
|
||||
}
|
||||
case 'start': {
|
||||
return <Text>{scopedT('text')}</Text>
|
||||
return <Text>{t('editor.blocks.start.text')}</Text>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import { isNotDefined } from '@typebot.io/lib'
|
||||
import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||
import { isFreePlan } from '@/features/billing/helpers/isFreePlan'
|
||||
import { parseTimeSince } from '@/helpers/parseTimeSince'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { parseDefaultPublicId } from '../helpers/parseDefaultPublicId'
|
||||
@ -39,7 +39,7 @@ export const PublishButton = ({
|
||||
isMoreMenuDisabled = false,
|
||||
...props
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const warningTextColor = useColorModeValue('red.300', 'red.600')
|
||||
const { workspace } = useWorkspace()
|
||||
const { push, query, pathname } = useRouter()
|
||||
|
@ -24,12 +24,12 @@ import { hasProPerks } from '@/features/billing/helpers/hasProPerks'
|
||||
import { CustomDomainsDropdown } from '@/features/customDomains/components/CustomDomainsDropdown'
|
||||
import { TypebotHeader } from '@/features/editor/components/TypebotHeader'
|
||||
import { parseDefaultPublicId } from '../helpers/parseDefaultPublicId'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import { env } from '@typebot.io/env'
|
||||
import DomainStatusIcon from '@/features/customDomains/components/DomainStatusIcon'
|
||||
|
||||
export const SharePage = () => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { workspace } = useWorkspace()
|
||||
const { typebot, updateTypebot, publishedTypebot } = useTypebot()
|
||||
const { showToast } = useToast()
|
||||
|
@ -16,10 +16,10 @@ import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { useUser } from '@/features/account/hooks/useUser'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const CreateNewTypebotButtons = () => {
|
||||
const scopedT = useScopedI18n('templates.buttons')
|
||||
const { t } = useTranslate()
|
||||
const { workspace } = useWorkspace()
|
||||
const { user } = useUser()
|
||||
const router = useRouter()
|
||||
@ -72,7 +72,7 @@ export const CreateNewTypebotButtons = () => {
|
||||
|
||||
return (
|
||||
<VStack maxW="600px" w="full" flex="1" pt="20" spacing={10}>
|
||||
<Heading>{scopedT('heading')}</Heading>
|
||||
<Heading>{t('templates.buttons.heading')}</Heading>
|
||||
<Stack w="full" spacing={6}>
|
||||
<Button
|
||||
variant="outline"
|
||||
@ -89,7 +89,7 @@ export const CreateNewTypebotButtons = () => {
|
||||
onClick={() => handleCreateSubmit()}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{scopedT('fromScratchButton.label')}
|
||||
{t('templates.buttons.fromScratchButton.label')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
@ -106,7 +106,7 @@ export const CreateNewTypebotButtons = () => {
|
||||
onClick={onOpen}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{scopedT('fromTemplateButton.label')}
|
||||
{t('templates.buttons.fromTemplateButton.label')}
|
||||
</Button>
|
||||
<ImportTypebotFromFileButton
|
||||
variant="outline"
|
||||
@ -123,7 +123,7 @@ export const CreateNewTypebotButtons = () => {
|
||||
isLoading={isLoading}
|
||||
onNewTypebot={handleCreateSubmit}
|
||||
>
|
||||
{scopedT('importFileButton.label')}
|
||||
{t('templates.buttons.importFileButton.label')}
|
||||
</ImportTypebotFromFileButton>
|
||||
</Stack>
|
||||
<TemplatesModal
|
||||
|
@ -4,7 +4,7 @@ import { Typebot, typebotCreateSchema } from '@typebot.io/schemas'
|
||||
import { preprocessTypebot } from '@typebot.io/schemas/features/typebot/helpers/preprocessTypebot'
|
||||
import React, { ChangeEvent } from 'react'
|
||||
import { z } from 'zod'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
onNewTypebot: (typebot: Typebot) => void
|
||||
@ -14,7 +14,7 @@ export const ImportTypebotFromFileButton = ({
|
||||
onNewTypebot,
|
||||
...props
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('templates.importFromFileButon')
|
||||
const { t } = useTranslate()
|
||||
const { showToast } = useToast()
|
||||
|
||||
const handleInputChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||
@ -29,7 +29,7 @@ export const ImportTypebotFromFileButton = ({
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showToast({
|
||||
description: scopedT('toastError.description'),
|
||||
description: t('templates.importFromFileButon.toastError.description'),
|
||||
details: {
|
||||
content: JSON.stringify(err, null, 2),
|
||||
lang: 'json',
|
||||
|
@ -19,7 +19,7 @@ import { templates } from '../data'
|
||||
import { TemplateProps } from '../types'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { sendRequest } from '@typebot.io/lib'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean
|
||||
@ -28,7 +28,7 @@ type Props = {
|
||||
}
|
||||
|
||||
export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
const scopedT = useScopedI18n('templates.modal')
|
||||
const { t } = useTranslate()
|
||||
const templateCardBackgroundColor = useColorModeValue('white', 'gray.800')
|
||||
const [typebot, setTypebot] = useState<Typebot>()
|
||||
const [selectedTemplate, setSelectedTemplate] = useState<TemplateProps>(
|
||||
@ -90,7 +90,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
pl="1"
|
||||
color="gray.500"
|
||||
>
|
||||
{scopedT('menuHeading.marketing')}
|
||||
{t('templates.modal.menuHeading.marketing')}
|
||||
</Text>
|
||||
{templates
|
||||
.filter((template) => template.category === 'marketing')
|
||||
@ -112,7 +112,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
<Text>{template.name}</Text>
|
||||
{template.isNew && (
|
||||
<Tag colorScheme="orange" size="sm" flexShrink={0}>
|
||||
{scopedT('menuHeading.new.tag')}
|
||||
{t('templates.modal.menuHeading.new.tag')}
|
||||
</Tag>
|
||||
)}
|
||||
</HStack>
|
||||
@ -126,7 +126,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
pl="1"
|
||||
color="gray.500"
|
||||
>
|
||||
{scopedT('menuHeading.product')}
|
||||
{t('templates.modal.menuHeading.product')}
|
||||
</Text>
|
||||
{templates
|
||||
.filter((template) => template.category === 'product')
|
||||
@ -148,7 +148,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
<Text>{template.name}</Text>
|
||||
{template.isNew && (
|
||||
<Tag colorScheme="orange" size="sm" flexShrink={0}>
|
||||
{scopedT('menuHeading.new.tag')}
|
||||
{t('templates.modal.menuHeading.new.tag')}
|
||||
</Tag>
|
||||
)}
|
||||
</HStack>
|
||||
@ -162,7 +162,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
pl="1"
|
||||
color="gray.500"
|
||||
>
|
||||
{scopedT('menuHeading.other')}
|
||||
{t('templates.modal.menuHeading.other')}
|
||||
</Text>
|
||||
{templates
|
||||
.filter((template) => template.category === undefined)
|
||||
@ -184,7 +184,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
<Text>{template.name}</Text>
|
||||
{template.isNew && (
|
||||
<Tag colorScheme="orange" size="sm" flexShrink={0}>
|
||||
{scopedT('menuHeading.new.tag')}
|
||||
{t('templates.modal.menuHeading.new.tag')}
|
||||
</Tag>
|
||||
)}
|
||||
</HStack>
|
||||
@ -231,7 +231,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
|
||||
onClick={onUseThisTemplateClick}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
{scopedT('useTemplateButton.label')}
|
||||
{t('templates.modal.useTemplateButton.label')}
|
||||
</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
|
@ -8,7 +8,7 @@ import { Plan } from '@typebot.io/prisma'
|
||||
import { isFreePlan } from '@/features/billing/helpers/isFreePlan'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { ChangePlanModal } from '@/features/billing/components/ChangePlanModal'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
isBrandingEnabled: boolean
|
||||
@ -23,7 +23,7 @@ export const GeneralSettings = ({
|
||||
onGeneralThemeChange,
|
||||
onBrandingChange,
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
const { workspace } = useWorkspace()
|
||||
const isWorkspaceFreePlan = isFreePlan(workspace)
|
||||
|
@ -13,7 +13,7 @@ import { WorkspaceInvitation, WorkspaceRole } from '@typebot.io/prisma'
|
||||
import { FormEvent, useState } from 'react'
|
||||
import { Member } from '../types'
|
||||
import { sendInvitationQuery } from '../queries/sendInvitationQuery'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
workspaceId: string
|
||||
@ -29,7 +29,7 @@ export const AddMemberForm = ({
|
||||
isLoading,
|
||||
isLocked,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('workspace.membersList')
|
||||
const { t } = useTranslate()
|
||||
const [invitationEmail, setInvitationEmail] = useState('')
|
||||
const [invitationRole, setInvitationRole] = useState<WorkspaceRole>(
|
||||
WorkspaceRole.MEMBER
|
||||
@ -54,7 +54,7 @@ export const AddMemberForm = ({
|
||||
return (
|
||||
<HStack as="form" onSubmit={handleInvitationSubmit}>
|
||||
<Input
|
||||
placeholder={scopedT('inviteInput.placeholder')}
|
||||
placeholder={t('workspace.membersList.inviteInput.placeholder')}
|
||||
name="inviteEmail"
|
||||
value={invitationEmail}
|
||||
onChange={(e) => setInvitationEmail(e.target.value)}
|
||||
@ -75,7 +75,7 @@ export const AddMemberForm = ({
|
||||
type="submit"
|
||||
isDisabled={isLoading || isLocked || invitationEmail === ''}
|
||||
>
|
||||
{scopedT('inviteButton.label')}
|
||||
{t('workspace.membersList.inviteButton.label')}
|
||||
</Button>
|
||||
</HStack>
|
||||
)
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
import { WorkspaceRole } from '@typebot.io/prisma'
|
||||
import React from 'react'
|
||||
import { convertWorkspaceRoleToReadable } from './AddMemberForm'
|
||||
import { useI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
image?: string
|
||||
@ -38,7 +38,7 @@ export const MemberItem = ({
|
||||
onDeleteClick,
|
||||
onSelectNewRole,
|
||||
}: Props) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
const handleAdminClick = () => onSelectNewRole(WorkspaceRole.ADMIN)
|
||||
const handleMemberClick = () => onSelectNewRole(WorkspaceRole.MEMBER)
|
||||
|
||||
@ -88,7 +88,7 @@ export const MemberIdentityContent = ({
|
||||
isGuest?: boolean
|
||||
email: string
|
||||
}) => {
|
||||
const t = useI18n()
|
||||
const { t } = useTranslate()
|
||||
|
||||
return (
|
||||
<HStack justifyContent="space-between" maxW="full" p="2">
|
||||
|
@ -19,11 +19,11 @@ import { updateInvitationQuery } from '../queries/updateInvitationQuery'
|
||||
import { updateMemberQuery } from '../queries/updateMemberQuery'
|
||||
import { Member } from '../types'
|
||||
import { useWorkspace } from '../WorkspaceProvider'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { getSeatsLimit } from '@typebot.io/lib/billing/getSeatsLimit'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const MembersList = () => {
|
||||
const scopedT = useScopedI18n('workspace.membersList')
|
||||
const { t } = useTranslate()
|
||||
const { user } = useUser()
|
||||
const { workspace, currentRole } = useWorkspace()
|
||||
const { members, invitations, isLoading, mutate } = useMembers({
|
||||
@ -103,12 +103,12 @@ export const MembersList = () => {
|
||||
<Stack w="full" spacing={3}>
|
||||
{!canInviteNewMember && (
|
||||
<UnlockPlanAlertInfo>
|
||||
{scopedT('unlockBanner.label')}
|
||||
{t('workspace.membersList.unlockBanner.label')}
|
||||
</UnlockPlanAlertInfo>
|
||||
)}
|
||||
{isDefined(seatsLimit) && (
|
||||
<Heading fontSize="2xl">
|
||||
{scopedT('title')}{' '}
|
||||
{t('workspace.membersList.title')}{' '}
|
||||
{seatsLimit === -1 ? '' : `(${currentMembersCount}/${seatsLimit})`}
|
||||
</Heading>
|
||||
)}
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
} from '@/components/icons'
|
||||
import { PlanTag } from '@/features/billing/components/PlanTag'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
import {
|
||||
Menu,
|
||||
MenuButton,
|
||||
@ -32,7 +32,7 @@ export const WorkspaceDropdown = ({
|
||||
onLogoutClick,
|
||||
onCreateNewWorkspaceClick,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('workspace.dropdown')
|
||||
const { t } = useTranslate()
|
||||
const { data } = trpc.workspace.listWorkspaces.useQuery()
|
||||
|
||||
const workspaces = data?.workspaces ?? []
|
||||
@ -72,14 +72,14 @@ export const WorkspaceDropdown = ({
|
||||
</MenuItem>
|
||||
))}
|
||||
<MenuItem onClick={onCreateNewWorkspaceClick} icon={<PlusIcon />}>
|
||||
{scopedT('newButton.label')}
|
||||
{t('workspace.dropdown.newButton.label')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={onLogoutClick}
|
||||
icon={<LogOutIcon />}
|
||||
color="orange.500"
|
||||
>
|
||||
{scopedT('logoutButton.label')}
|
||||
{t('workspace.dropdown.logoutButton.label')}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
|
@ -12,10 +12,10 @@ import React from 'react'
|
||||
import { EditableEmojiOrImageIcon } from '@/components/EditableEmojiOrImageIcon'
|
||||
import { useWorkspace } from '../WorkspaceProvider'
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
export const WorkspaceSettingsForm = ({ onClose }: { onClose: () => void }) => {
|
||||
const scopedT = useScopedI18n('workspace.settings')
|
||||
const { t } = useTranslate()
|
||||
const { workspace, workspaces, updateWorkspace, deleteCurrentWorkspace } =
|
||||
useWorkspace()
|
||||
|
||||
@ -34,7 +34,7 @@ export const WorkspaceSettingsForm = ({ onClose }: { onClose: () => void }) => {
|
||||
return (
|
||||
<Stack spacing="6" w="full">
|
||||
<FormControl>
|
||||
<FormLabel>{scopedT('icon.title')}</FormLabel>
|
||||
<FormLabel>{t('workspace.settings.icon.title')}</FormLabel>
|
||||
<Flex>
|
||||
{workspace && (
|
||||
<EditableEmojiOrImageIcon
|
||||
@ -51,7 +51,7 @@ export const WorkspaceSettingsForm = ({ onClose }: { onClose: () => void }) => {
|
||||
</FormControl>
|
||||
{workspace && (
|
||||
<TextInput
|
||||
label={scopedT('name.label')}
|
||||
label={t('workspace.settings.name.label')}
|
||||
withVariableButton={false}
|
||||
defaultValue={workspace?.name}
|
||||
onChange={handleNameChange}
|
||||
@ -74,12 +74,12 @@ const DeleteWorkspaceButton = ({
|
||||
workspaceName: string
|
||||
onConfirm: () => Promise<void>
|
||||
}) => {
|
||||
const scopedT = useScopedI18n('workspace.settings')
|
||||
const { t } = useTranslate()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
return (
|
||||
<>
|
||||
<Button colorScheme="red" variant="outline" onClick={onOpen}>
|
||||
{scopedT('deleteButton.label')}
|
||||
{t('workspace.settings.deleteButton.label')}
|
||||
</Button>
|
||||
<ConfirmModal
|
||||
isOpen={isOpen}
|
||||
@ -87,7 +87,7 @@ const DeleteWorkspaceButton = ({
|
||||
onClose={onClose}
|
||||
message={
|
||||
<Text>
|
||||
{scopedT('deleteButton.confirmMessage', {
|
||||
{t('workspace.settings.deleteButton.confirmMessage', {
|
||||
workspaceName,
|
||||
})}
|
||||
</Text>
|
||||
|
@ -24,7 +24,7 @@ import packageJson from '../../../../../../package.json'
|
||||
import { UserPreferencesForm } from '@/features/account/components/UserPreferencesForm'
|
||||
import { MyAccountForm } from '@/features/account/components/MyAccountForm'
|
||||
import { BillingSettingsLayout } from '@/features/billing/components/BillingSettingsLayout'
|
||||
import { useScopedI18n } from '@/locales'
|
||||
import { useTranslate } from '@tolgee/react'
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean
|
||||
@ -46,7 +46,7 @@ export const WorkspaceSettingsModal = ({
|
||||
workspace,
|
||||
onClose,
|
||||
}: Props) => {
|
||||
const scopedT = useScopedI18n('workspace.settings.modal')
|
||||
const { t } = useTranslate()
|
||||
const { currentRole } = useWorkspace()
|
||||
const [selectedTab, setSelectedTab] = useState<SettingsTab>('my-account')
|
||||
|
||||
@ -82,7 +82,7 @@ export const WorkspaceSettingsModal = ({
|
||||
justifyContent="flex-start"
|
||||
pl="4"
|
||||
>
|
||||
{scopedT('menu.myAccount.label')}
|
||||
{t('workspace.settings.modal.menu.myAccount.label')}
|
||||
</Button>
|
||||
<Button
|
||||
variant={selectedTab === 'user-settings' ? 'solid' : 'ghost'}
|
||||
@ -92,12 +92,12 @@ export const WorkspaceSettingsModal = ({
|
||||
justifyContent="flex-start"
|
||||
pl="4"
|
||||
>
|
||||
{scopedT('menu.preferences.label')}
|
||||
{t('workspace.settings.modal.menu.preferences.label')}
|
||||
</Button>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Text pl="4" color="gray.500">
|
||||
{scopedT('menu.workspace.label')}
|
||||
{t('workspace.settings.modal.menu.workspace.label')}
|
||||
</Text>
|
||||
{canEditWorkspace && (
|
||||
<Button
|
||||
@ -116,7 +116,7 @@ export const WorkspaceSettingsModal = ({
|
||||
justifyContent="flex-start"
|
||||
pl="4"
|
||||
>
|
||||
{scopedT('menu.settings.label')}
|
||||
{t('workspace.settings.modal.menu.settings.label')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
@ -127,7 +127,7 @@ export const WorkspaceSettingsModal = ({
|
||||
justifyContent="flex-start"
|
||||
pl="4"
|
||||
>
|
||||
{scopedT('menu.members.label')}
|
||||
{t('workspace.settings.modal.menu.members.label')}
|
||||
</Button>
|
||||
{canEditWorkspace && (
|
||||
<Button
|
||||
@ -140,7 +140,7 @@ export const WorkspaceSettingsModal = ({
|
||||
overflow="scroll"
|
||||
className="hide-scrollbar"
|
||||
>
|
||||
{scopedT('menu.billingAndUsage.label')}
|
||||
{t('workspace.settings.modal.menu.billingAndUsage.label')}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
@ -148,7 +148,9 @@ export const WorkspaceSettingsModal = ({
|
||||
|
||||
<Flex justify="center" pt="10">
|
||||
<Text color="gray.500" fontSize="xs">
|
||||
{scopedT('menu.version.label', { version: packageJson.version })}
|
||||
{t('workspace.settings.modal.menu.version.label', {
|
||||
version: packageJson.version,
|
||||
})}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Stack>
|
||||
|
25
apps/builder/src/lib/tolgee.tsx
Normal file
25
apps/builder/src/lib/tolgee.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { DevTools, Tolgee } from '@tolgee/react'
|
||||
import { FormatIcu } from '@tolgee/format-icu'
|
||||
import en from '../../public/locales/en.json'
|
||||
import fr from '../../public/locales/fr.json'
|
||||
import de from '../../public/locales/de.json'
|
||||
import pt from '../../public/locales/pt.json'
|
||||
import ptBR from '../../public/locales/pt-BR.json'
|
||||
|
||||
export const tolgee = Tolgee()
|
||||
.use(DevTools())
|
||||
.use(FormatIcu())
|
||||
.init({
|
||||
apiKey: process.env.NEXT_PUBLIC_TOLGEE_API_KEY,
|
||||
apiUrl: process.env.NEXT_PUBLIC_TOLGEE_API_URL,
|
||||
defaultLanguage: 'en',
|
||||
availableLanguages: ['en', 'fr', 'de', 'pt', 'pt-BR'],
|
||||
fallbackLanguage: 'en',
|
||||
staticData: {
|
||||
en,
|
||||
fr,
|
||||
de,
|
||||
pt,
|
||||
'pt-BR': ptBR,
|
||||
},
|
||||
})
|
@ -1,329 +0,0 @@
|
||||
export default {
|
||||
back: 'Zurück',
|
||||
'confirmModal.defaultTitle': 'Bist du sicher?',
|
||||
'dashboard.header.settingsButton.label': 'Einstellungen & Mitglieder',
|
||||
'dashboard.redirectionMessage': 'Du wirst weitergeleitet...',
|
||||
'dashboard.title': 'Meine Typebots',
|
||||
delete: 'Löschen',
|
||||
errorMessage: 'Ein Fehler ist aufgetreten',
|
||||
cancel: 'Abbrechen',
|
||||
update: 'Aktualisieren',
|
||||
upgrade: 'Upgrade',
|
||||
downgrade: 'Downgrade',
|
||||
remove: 'Entfernen',
|
||||
pending: 'Ausstehend',
|
||||
skip: 'Überspringen',
|
||||
'folders.createFolderButton.label': 'Ordner erstellen',
|
||||
'folders.createTypebotButton.label': 'Typebot erstellen',
|
||||
'folders.folderButton.deleteConfirmationMessage':
|
||||
'Möchtest du den Ordner {folderName} wirklich löschen? (Alles im Inneren wird in dein Dashboard verschoben)',
|
||||
'folders.typebotButton.live': 'Live',
|
||||
'folders.typebotButton.showMoreOptions': 'Mehr Optionen anzeigen',
|
||||
'folders.typebotButton.unpublish': 'Veröffentlichung aufheben',
|
||||
'folders.typebotButton.duplicate': 'Duplizieren',
|
||||
'folders.typebotButton.delete': 'Löschen',
|
||||
'folders.typebotButton.deleteConfirmationMessage':
|
||||
'Möchtest du deinen Typebot {typebotName} wirklich löschen?',
|
||||
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||
'Alle zugehörigen Daten werden gelöscht und können nicht wiederhergestellt werden.',
|
||||
'account.apiTokens.heading': 'API-Token',
|
||||
'account.apiTokens.description':
|
||||
'Diese Token ermöglichen es anderen Apps, dein gesamtes Konto und Typebots zu steuern. Sei vorsichtig!',
|
||||
'account.apiTokens.createButton.label': 'Erstellen',
|
||||
'account.apiTokens.deleteButton.label': 'Löschen',
|
||||
'account.apiTokens.table.nameHeader': 'Name',
|
||||
'account.apiTokens.table.createdHeader': 'Erstellt',
|
||||
'account.apiTokens.deleteConfirmationMessage':
|
||||
'Der Token {tokenName} wird dauerhaft widerrufen, bist du sicher, dass du fortfahren möchtest?',
|
||||
'account.apiTokens.createModal.createHeading': 'Token erstellen',
|
||||
'account.apiTokens.createModal.createdHeading': 'Token erstellt',
|
||||
'account.apiTokens.createModal.nameInput.label':
|
||||
'Gib einen eindeutigen Namen für deinen Token ein, um ihn von anderen Token zu unterscheiden.',
|
||||
'account.apiTokens.createModal.nameInput.placeholder':
|
||||
'Z.B. Zapier, Github, Make.com',
|
||||
'account.apiTokens.createModal.createButton.label': 'Token erstellen',
|
||||
'account.apiTokens.createModal.doneButton.label': 'Fertig',
|
||||
'account.apiTokens.createModal.copyInstruction':
|
||||
'Bitte kopiere deinen Token und bewahre ihn an einem sicheren Ort auf.',
|
||||
'account.apiTokens.createModal.securityWarning':
|
||||
'Aus Sicherheitsgründen können wir ihn nicht erneut anzeigen.',
|
||||
'account.preferences.language.heading': 'Sprache',
|
||||
'account.preferences.language.tooltip':
|
||||
'Die Übersetzungen sind noch nicht vollständig. Es ist eine laufende Arbeit. 🤓',
|
||||
'account.preferences.graphNavigation.heading': 'Editor-Navigation',
|
||||
'account.preferences.graphNavigation.mouse.label': 'Maus',
|
||||
'account.preferences.graphNavigation.mouse.description':
|
||||
'Bewege dich, indem du das Board ziehst und zoome rein/raus mit dem Mausrad',
|
||||
'account.preferences.graphNavigation.trackpad.label': 'Trackpad',
|
||||
'account.preferences.graphNavigation.trackpad.description':
|
||||
'Bewege das Board mit 2 Fingern und zoome rein/raus, indem du kneifst',
|
||||
'account.preferences.appearance.heading': 'Erscheinungsbild',
|
||||
'account.preferences.appearance.systemLabel': 'System',
|
||||
'account.preferences.appearance.lightLabel': 'Hell',
|
||||
'account.preferences.appearance.darkLabel': 'Dunkel',
|
||||
'account.myAccount.changePhotoButton.label': 'Foto ändern',
|
||||
'account.myAccount.changePhotoButton.specification':
|
||||
'.jpg oder .png, max 1MB',
|
||||
'account.myAccount.emailInput.disabledTooltip':
|
||||
'Das Aktualisieren der E-Mail-Adresse ist nicht verfügbar. Kontaktiere den Support, wenn du sie ändern möchtest.',
|
||||
'account.myAccount.emailInput.label': 'E-Mail-Adresse:',
|
||||
'account.myAccount.nameInput.label': 'Name:',
|
||||
'analytics.viewsLabel': 'Ansichten',
|
||||
'analytics.startsLabel': 'Starts',
|
||||
'analytics.notAvailableLabel': 'Nicht verfügbar',
|
||||
'analytics.completionRateLabel': 'Abschlussrate',
|
||||
'auth.signin.heading': 'Anmelden',
|
||||
'auth.signin.noAccountLabel.preLink': 'Noch kein Konto?',
|
||||
'auth.signin.noAccountLabel.link': 'Kostenlos anmelden',
|
||||
'auth.register.heading': 'Konto erstellen',
|
||||
'auth.register.alreadyHaveAccountLabel.preLink':
|
||||
'Bereits ein Konto vorhanden?',
|
||||
'auth.register.alreadyHaveAccountLabel.link': 'Anmelden',
|
||||
'auth.register.aggreeToTerms':
|
||||
'Durch die Registrierung stimmst du unseren {termsOfService} und {privacyPolicy} zu.',
|
||||
'auth.register.termsOfService': 'Nutzungsbedingungen',
|
||||
'auth.register.privacyPolicy': 'Datenschutzrichtlinie',
|
||||
'auth.error.default': 'Versuche, dich mit einem anderen Konto anzumelden.',
|
||||
'auth.error.email':
|
||||
'E-Mail nicht gefunden. Versuche, dich mit einem anderen Anbieter anzumelden.',
|
||||
'auth.error.oauthNotLinked':
|
||||
'Um deine Identität zu bestätigen, melde dich mit demselben Konto an, das du ursprünglich verwendet hast.',
|
||||
'auth.error.unknown': 'Ein Fehler ist aufgetreten. Bitte versuche es erneut.',
|
||||
'auth.signinErrorToast.title': 'Nicht autorisiert',
|
||||
'auth.signinErrorToast.description': 'Anmeldungen sind deaktiviert.',
|
||||
'auth.signinErrorToast.tooManyRequests':
|
||||
'Zu viele Anfragen. Versuche es später erneut.',
|
||||
'auth.noProvider.preLink': 'Du musst',
|
||||
'auth.noProvider.link':
|
||||
'mindestens einen Authentifizierungsanbieter konfigurieren (E-Mail, Google, GitHub, Facebook oder Azure AD).',
|
||||
'auth.orEmailLabel': 'Oder mit deiner E-Mail',
|
||||
'auth.emailSubmitButton.label': 'Absenden',
|
||||
'auth.magicLink.title': 'Eine E-Mail mit magischem Link wurde gesendet. 🪄',
|
||||
'auth.magicLink.description':
|
||||
'Vergiss nicht, deinen Spam-Ordner zu überprüfen.',
|
||||
'auth.socialLogin.githubButton.label': 'Mit GitHub fortfahren',
|
||||
'auth.socialLogin.googleButton.label': 'Mit Google fortfahren',
|
||||
'auth.socialLogin.facebookButton.label': 'Mit Facebook fortfahren',
|
||||
'auth.socialLogin.azureButton.label': 'Mit {azureProviderName} fortfahren',
|
||||
'auth.socialLogin.gitlabButton.label': 'Mit {gitlabProviderName} fortfahren',
|
||||
'auth.socialLogin.customButton.label': 'Mit {customProviderName} fortfahren',
|
||||
'billing.billingPortalButton.label': 'Abrechnungsportal',
|
||||
'billing.contribution.preLink':
|
||||
'Typebot trägt 1% deines Abonnements dazu bei, CO₂ aus der Atmosphäre zu entfernen.',
|
||||
'billing.contribution.link': 'Erfahre mehr.',
|
||||
'billing.updateSuccessToast.description':
|
||||
'Workspace {plan} Plan erfolgreich aktualisiert 🎉',
|
||||
'billing.customLimit.preLink':
|
||||
'Brauchst du individuelle Limits? Spezielle Funktionen?',
|
||||
'billing.customLimit.link': 'Lass uns darüber sprechen!',
|
||||
'billing.upgradeLimitLabel':
|
||||
'Um {type} hinzuzufügen, musst du deinen Tarif aktualisieren',
|
||||
'billing.currentSubscription.heading': 'Abonnement',
|
||||
'billing.currentSubscription.subheading': 'Aktuelles Workspace-Abonnement:',
|
||||
'billing.currentSubscription.cancelDate': 'Wird storniert am',
|
||||
'billing.currentSubscription.pastDueAlert':
|
||||
'Die letzte Zahlung ist fehlgeschlagen. Gehen Sie zum Abrechnungsportal, um fortzufahren und eine Kündigung Ihres Abonnements zu vermeiden.',
|
||||
'billing.invoices.heading': 'Rechnungen',
|
||||
'billing.invoices.empty': 'Keine Rechnungen für diesen Workspace gefunden.',
|
||||
'billing.invoices.paidAt': 'Bezahlt am',
|
||||
'billing.invoices.subtotal': 'Zwischensumme',
|
||||
'billing.preCheckoutModal.companyInput.label': 'Firmenname:',
|
||||
'billing.preCheckoutModal.emailInput.label': 'E-Mail:',
|
||||
'billing.preCheckoutModal.taxId.label': 'Steuernummer:',
|
||||
'billing.preCheckoutModal.taxId.placeholder': 'ID-Typ',
|
||||
'billing.preCheckoutModal.submitButton.label': 'Zur Kasse gehen',
|
||||
'billing.pricingCard.heading': 'Upgrade auf {plan}',
|
||||
'billing.pricingCard.perMonth': '/ Monat',
|
||||
'billing.pricingCard.plus': ', plus:',
|
||||
'billing.pricingCard.upgradeButton.current': 'Dein aktueller Tarif',
|
||||
'billing.pricingCard.chatsPerMonth': 'Chats/Monat',
|
||||
'billing.pricingCard.chatsTooltip':
|
||||
'Ein Chat wird gezählt, wenn ein Benutzer eine Diskussion startet. Es ist unabhängig von der Anzahl der gesendeten und empfangenen Nachrichten.',
|
||||
'billing.pricingCard.storageLimit': 'GB Speicherplatz',
|
||||
'billing.pricingCard.storageLimitTooltip':
|
||||
'Du belegst Speicherplatz für jede Datei, die dein Benutzer in deinem Bot hochlädt. Wenn du das Ergebnis löschst, wird der Platz freigegeben.',
|
||||
'billing.pricingCard.starter.description':
|
||||
'Für Einzelpersonen & kleine Unternehmen.',
|
||||
'billing.pricingCard.starter.includedSeats': '2 Plätze inklusive',
|
||||
'billing.pricingCard.starter.brandingRemoved': 'Branding entfernt',
|
||||
'billing.pricingCard.starter.fileUploadBlock': 'Datei-Upload Eingabefeld',
|
||||
'billing.pricingCard.starter.createFolders': 'Ordner erstellen',
|
||||
'billing.pricingCard.pro.mostPopularLabel': 'Am beliebtesten',
|
||||
'billing.pricingCard.pro.description': 'Für Agenturen & wachsende Start-ups.',
|
||||
'billing.pricingCard.pro.everythingFromStarter': 'Alles in Starter',
|
||||
'billing.pricingCard.pro.includedSeats': '5 Plätze inklusive',
|
||||
'billing.pricingCard.pro.whatsAppIntegration': 'WhatsApp-Integration',
|
||||
'billing.pricingCard.pro.customDomains': 'Eigene Domains',
|
||||
'billing.pricingCard.pro.analytics': 'Detaillierte Analysen',
|
||||
'billing.usage.heading': 'Nutzung',
|
||||
'billing.usage.unlimited': 'Unbegrenzt',
|
||||
'billing.usage.chats.heading': 'Chats',
|
||||
'billing.usage.chats.alert.soonReach':
|
||||
'Deine Typebots sind beliebt! Du wirst bald das Chat-Limit deines Tarifs erreichen. 🚀',
|
||||
'billing.usage.chats.alert.updatePlan':
|
||||
'Vergewissere dich, dass du deinen Tarif aktualisierst, um dieses Limit zu erhöhen und weiterhin mit deinen Benutzern zu chatten.',
|
||||
'billing.usage.chats.resetInfo': '(setzt sich am 1. jeden Monats zurück)',
|
||||
'billing.usage.storage.heading': 'Speicherplatz',
|
||||
'billing.usage.storage.alert.soonReach':
|
||||
'Deine Typebots sind beliebt! Du wirst bald das Speicherlimit deines Tarifs erreichen. 🚀',
|
||||
'billing.usage.storage.alert.updatePlan':
|
||||
'Stelle sicher, dass du deinen Tarif aktualisierst, um weiterhin hochgeladene Dateien zu sammeln. Du kannst auch Dateien löschen, um Speicherplatz freizugeben.',
|
||||
'billing.limitMessage.brand': 'Branding entfernen',
|
||||
'billing.limitMessage.customDomain': 'Eigene Domains hinzufügen',
|
||||
'billing.limitMessage.analytics': 'Detaillierte Analysen freischalten',
|
||||
'billing.limitMessage.fileInput': 'Datei-Eingabefelder verwenden',
|
||||
'billing.limitMessage.folder': 'Ordner erstellen',
|
||||
'billing.upgradeAlert.buttonDefaultLabel': 'Mehr Informationen',
|
||||
'workspace.membersList.inviteInput.placeholder': 'name@unternehmen.de',
|
||||
'workspace.membersList.inviteButton.label': 'Einladen',
|
||||
'workspace.membersList.unlockBanner.label':
|
||||
'Aktualisiere deinen Plan, um mit mehr Teammitgliedern zu arbeiten und neue Limits freizuschalten 🚀',
|
||||
'workspace.membersList.title': 'Mitglieder',
|
||||
'workspace.settings.icon.title': 'Symbol',
|
||||
'workspace.settings.name.label': 'Name:',
|
||||
'workspace.settings.deleteButton.label': 'Workspace löschen',
|
||||
'workspace.settings.deleteButton.confirmMessage':
|
||||
'Sind Sie sicher, dass Sie den Workspace {workspaceName} löschen möchten? Alle seine Ordner, Typebots und Ergebnisse werden dauerhaft gelöscht.',
|
||||
'workspace.settings.modal.menu.myAccount.label': 'Mein Konto',
|
||||
'workspace.settings.modal.menu.preferences.label': 'Einstellungen',
|
||||
'workspace.settings.modal.menu.workspace.label': 'Workspace',
|
||||
'workspace.settings.modal.menu.settings.label': 'Einstellungen',
|
||||
'workspace.settings.modal.menu.members.label': 'Mitglieder',
|
||||
'workspace.settings.modal.menu.billingAndUsage.label': 'Abrechnung & Nutzung',
|
||||
'workspace.settings.modal.menu.version.label': 'Version: {version}',
|
||||
'workspace.dropdown.newButton.label': 'Neuer Workspace',
|
||||
'workspace.dropdown.logoutButton.label': 'Abmelden',
|
||||
|
||||
'templates.buttons.heading': 'Erstelle einen neuen Typebot',
|
||||
'templates.buttons.fromScratchButton.label': 'Von Grund auf starten',
|
||||
'templates.buttons.fromTemplateButton.label': 'Von einer Vorlage starten',
|
||||
'templates.buttons.importFileButton.label': 'Datei importieren',
|
||||
'templates.modal.menuHeading.marketing': 'Marketing',
|
||||
'templates.modal.menuHeading.product': 'Produkt',
|
||||
'templates.modal.menuHeading.other': 'Andere',
|
||||
'templates.modal.menuHeading.new.tag': 'Neu',
|
||||
'templates.modal.useTemplateButton.label': 'Diese Vorlage verwenden',
|
||||
'templates.importFromFileButon.toastError.description':
|
||||
'Konnte die Datei nicht verarbeiten. Bist du sicher, dass es sich um einen Typebot handelt?',
|
||||
'editor.headers.flowButton.label': 'Ablauf',
|
||||
'editor.headers.themeButton.label': 'Design',
|
||||
'editor.headers.settingsButton.label': 'Einstellungen',
|
||||
'editor.headers.shareButton.label': 'Teilen',
|
||||
'editor.headers.resultsButton.label': 'Ergebnisse',
|
||||
'editor.headers.helpButton.label': 'Hilfe',
|
||||
'editor.headers.savingSpinner.label': 'Speichern...',
|
||||
'editor.headers.previewButton.label': 'Vorschau',
|
||||
'editor.sidebarBlocks.sidebar.lock.label': 'Seitenleiste sperren',
|
||||
'editor.sidebarBlocks.sidebar.unlock.label': 'Seitenleiste entsperren',
|
||||
'editor.sidebarBlocks.sidebar.icon.lock.label': 'Sperren',
|
||||
'editor.sidebarBlocks.sidebar.icon.unlock.label': 'Entsperren',
|
||||
'editor.sidebarBlocks.blockType.bubbles.heading': 'Blasen',
|
||||
'editor.sidebarBlocks.blockType.inputs.heading': 'Eingaben',
|
||||
'editor.sidebarBlocks.blockType.logic.heading': 'Logik',
|
||||
'editor.sidebarBlocks.blockType.integrations.heading': 'Integrationen',
|
||||
'editor.sidebarBlock.start.label': 'Start',
|
||||
'editor.sidebarBlock.text.label': 'Text',
|
||||
'editor.sidebarBlock.image.label': 'Bild',
|
||||
'editor.sidebarBlock.video.label': 'Video',
|
||||
'editor.sidebarBlock.embed.label': 'Einbetten',
|
||||
'editor.sidebarBlock.audio.label': 'Audio',
|
||||
'editor.sidebarBlock.number.label': 'Nummer',
|
||||
'editor.sidebarBlock.email.label': 'E-Mail',
|
||||
'editor.sidebarBlock.website.label': 'Website',
|
||||
'editor.sidebarBlock.date.label': 'Datum',
|
||||
'editor.sidebarBlock.phone.label': 'Telefon',
|
||||
'editor.sidebarBlock.button.label': 'Buttons',
|
||||
'editor.sidebarBlock.picChoice.label': 'Bildauswahl',
|
||||
'editor.sidebarBlock.payment.label': 'Zahlung',
|
||||
'editor.sidebarBlock.rating.label': 'Bewertung',
|
||||
'editor.sidebarBlock.file.label': 'Datei',
|
||||
'editor.sidebarBlock.setVariable.label': 'Variable setzen',
|
||||
'editor.sidebarBlock.condition.label': 'Bedingung',
|
||||
'editor.sidebarBlock.redirect.label': 'Weiterleitung',
|
||||
'editor.sidebarBlock.script.label': 'Skript',
|
||||
'editor.sidebarBlock.typebot.label': 'Typebot',
|
||||
'editor.sidebarBlock.wait.label': 'Warten',
|
||||
'editor.sidebarBlock.jump.label': 'Springen',
|
||||
'editor.sidebarBlock.abTest.label': 'AB-Test',
|
||||
'editor.sidebarBlock.sheets.label': 'Tabellen',
|
||||
'editor.sidebarBlock.analytics.label': 'Analytics',
|
||||
'editor.sidebarBlock.webhook.label': 'Webhook',
|
||||
'editor.sidebarBlock.zapier.label': 'Zapier',
|
||||
'editor.sidebarBlock.makecom.label': 'Make.com',
|
||||
'editor.sidebarBlock.pabbly.label': 'Pabbly',
|
||||
'editor.sidebarBlock.chatwoot.label': 'Chatwoot',
|
||||
'editor.sidebarBlock.openai.label': 'OpenAI',
|
||||
'editor.sidebarBlock.pixel.label': 'Pixel',
|
||||
'editor.sidebarBlock.zemanticAi.label': 'Zemantic AI',
|
||||
'editor.blockCard.bubbleBlock.tooltip.label':
|
||||
'Ein PDF, ein iframe, eine Website einbetten...',
|
||||
'editor.blockCard.inputBlock.tooltip.files.label': 'Dateien hochladen',
|
||||
'editor.blockCard.logicBlock.tooltip.code.label': 'JavaScript-Code ausführen',
|
||||
'editor.blockCard.logicBlock.tooltip.typebotLink.label':
|
||||
'Verlinkung zu einem anderen Typebot',
|
||||
'editor.blockCard.logicBlock.tooltip.jump.label':
|
||||
'Ablauf zu einer anderen Gruppe beschleunigen',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleSheets.label':
|
||||
'Google Tabellen',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleAnalytics.label':
|
||||
'Google Analytics',
|
||||
'editor.editableTypebotName.tooltip.rename.label': 'Umbenennen',
|
||||
'editor.gettingStartedModal.editorBasics.heading': 'Grundlagen des Editors',
|
||||
'editor.gettingStartedModal.editorBasics.list.one.label':
|
||||
'Die Seitenleiste enthält Blöcke, die du auf das Board ziehen und ablegen kannst.',
|
||||
'editor.gettingStartedModal.editorBasics.list.two.label':
|
||||
'Du kannst Blöcke gruppieren, indem du sie unter oder über einander ablegst.',
|
||||
'editor.gettingStartedModal.editorBasics.list.three.label':
|
||||
'Verbinde die Gruppen miteinander.',
|
||||
'editor.gettingStartedModal.editorBasics.list.four.label':
|
||||
'Klicke auf die Vorschau-Schaltfläche oben rechts, um deinen Bot anzusehen.',
|
||||
'editor.gettingStartedModal.editorBasics.list.label':
|
||||
'Wenn du Fragen hast, verwende gerne die Sprechblase unten rechts, um sie mir zu stellen. Ich beantworte normalerweise innerhalb der nächsten 24 Stunden. 😃',
|
||||
'editor.gettingStartedModal.seeAction.label': 'In Aktion sehen',
|
||||
'editor.gettingStartedModal.seeAction.time': '5 Minuten',
|
||||
'editor.gettingStartedModal.seeAction.item.label': 'Weitere Videos',
|
||||
'editor.provider.messages.getTypebotError.title':
|
||||
'Fehler beim Abrufen des Typebots. Aktualisiere die Seite.',
|
||||
'editor.provider.messages.getTypebotError.description':
|
||||
'Typebot konnte nicht gefunden werden.',
|
||||
'editor.provider.messages.publishedTypebotError.title':
|
||||
'Fehler beim Abrufen des veröffentlichten Typebots',
|
||||
'editor.provider.messages.updateTypebotError.title':
|
||||
'Fehler beim Aktualisieren des Typebots',
|
||||
'editor.provider.groups.copy.title': 'kopieren',
|
||||
'editor.blocks.start.text': 'Start',
|
||||
'editor.blocks.bubbles.audio.settings.upload.label': 'Hochladen',
|
||||
'editor.blocks.bubbles.audio.settings.embedLink.label': 'Link einbetten',
|
||||
'editor.blocks.bubbles.audio.settings.chooseFile.label': 'Datei auswählen',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.text':
|
||||
'Funktioniert mit .MP3- und .WAV-Dateien',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.placeholder':
|
||||
'Füge den Audio-Dateilink ein...',
|
||||
'editor.blocks.bubbles.audio.settings.autoplay.label': 'Autoplay aktivieren',
|
||||
'editor.blocks.bubbles.audio.node.clickToEdit.text':
|
||||
'Zum Bearbeiten klicken...',
|
||||
'editor.blocks.bubbles.embed.node.clickToEdit.text':
|
||||
'Zum Bearbeiten klicken...',
|
||||
'editor.blocks.bubbles.embed.node.show.text': 'Einbetten anzeigen',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.placeholder':
|
||||
'Füge den Link oder Code ein...',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.text':
|
||||
'Funktioniert mit PDFs, iframes, Websites...',
|
||||
'editor.blocks.bubbles.embed.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.image.node.clickToEdit.text':
|
||||
'Zum Bearbeiten klicken...',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.label':
|
||||
'Beim Klicken Link',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder':
|
||||
'Link Alternativtext (Beschreibung)',
|
||||
'editor.blocks.bubbles.video.node.clickToEdit.text':
|
||||
'Zum Bearbeiten klicken...',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.text':
|
||||
'Funktioniert mit YouTube, Vimeo und anderen',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.placeholder':
|
||||
'Füge den Videolink ein...',
|
||||
'editor.blocks.bubbles.video.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.textEditor.plate.label': 'Texteditor',
|
||||
'editor.blocks.bubbles.textEditor.searchVariable.placeholder':
|
||||
'Nach einer Variable suchen',
|
||||
} as const
|
@ -1,318 +0,0 @@
|
||||
export default {
|
||||
back: 'Back',
|
||||
'confirmModal.defaultTitle': 'Are you sure?',
|
||||
'dashboard.header.settingsButton.label': 'Settings & Members',
|
||||
'dashboard.redirectionMessage': 'You are being redirected...',
|
||||
'dashboard.title': 'My typebots',
|
||||
delete: 'Delete',
|
||||
errorMessage: 'An error occured',
|
||||
cancel: 'Cancel',
|
||||
update: 'Update',
|
||||
upgrade: 'Upgrade',
|
||||
downgrade: 'Downgrade',
|
||||
remove: 'Remove',
|
||||
pending: 'Pending',
|
||||
skip: 'Skip',
|
||||
'folders.createFolderButton.label': 'Create a folder',
|
||||
'folders.createTypebotButton.label': 'Create a typebot',
|
||||
'folders.folderButton.deleteConfirmationMessage':
|
||||
'Are you sure you want to delete {folderName} folder? (Everything inside will be move to your dashboard)',
|
||||
'folders.typebotButton.live': 'Live',
|
||||
'folders.typebotButton.showMoreOptions': 'Show more options',
|
||||
'folders.typebotButton.unpublish': 'Unpublish',
|
||||
'folders.typebotButton.duplicate': 'Duplicate',
|
||||
'folders.typebotButton.delete': 'Delete',
|
||||
'folders.typebotButton.deleteConfirmationMessage':
|
||||
'Are you sure you want to delete your typebot {typebotName}?',
|
||||
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||
"All its associated data will be deleted and won't be recoverable.",
|
||||
'account.apiTokens.heading': 'API tokens',
|
||||
'account.apiTokens.description':
|
||||
'These tokens allow other apps to control your whole account and typebots. Be careful!',
|
||||
'account.apiTokens.createButton.label': 'Create',
|
||||
'account.apiTokens.deleteButton.label': 'Delete',
|
||||
'account.apiTokens.table.nameHeader': 'Name',
|
||||
'account.apiTokens.table.createdHeader': 'Created',
|
||||
'account.apiTokens.deleteConfirmationMessage':
|
||||
'The token {tokenName} will be permanently revoked, are you sure you want to continue?',
|
||||
'account.apiTokens.createModal.createHeading': 'Create Token',
|
||||
'account.apiTokens.createModal.createdHeading': 'Token Created',
|
||||
'account.apiTokens.createModal.nameInput.label':
|
||||
'Enter a unique name for your token to differentiate it from other tokens.',
|
||||
'account.apiTokens.createModal.nameInput.placeholder':
|
||||
'I.e. Zapier, Github, Make.com',
|
||||
'account.apiTokens.createModal.createButton.label': 'Create token',
|
||||
'account.apiTokens.createModal.doneButton.label': 'Done',
|
||||
'account.apiTokens.createModal.copyInstruction':
|
||||
'Please copy your token and store it in a safe place.',
|
||||
'account.apiTokens.createModal.securityWarning':
|
||||
'For security reasons we cannot show it again.',
|
||||
'account.preferences.language.heading': 'Language',
|
||||
'account.preferences.language.tooltip':
|
||||
'The translations are not complete yet. It is a work in progress. 🤓',
|
||||
'account.preferences.graphNavigation.heading': 'Editor Navigation',
|
||||
'account.preferences.graphNavigation.mouse.label': 'Mouse',
|
||||
'account.preferences.graphNavigation.mouse.description':
|
||||
'Move by dragging the board and zoom in/out using the scroll wheel',
|
||||
'account.preferences.graphNavigation.trackpad.label': 'Trackpad',
|
||||
'account.preferences.graphNavigation.trackpad.description':
|
||||
'Move the board using 2 fingers and zoom in/out by pinching',
|
||||
'account.preferences.appearance.heading': 'Appearance',
|
||||
'account.preferences.appearance.systemLabel': 'System',
|
||||
'account.preferences.appearance.lightLabel': 'Light',
|
||||
'account.preferences.appearance.darkLabel': 'Dark',
|
||||
'account.myAccount.changePhotoButton.label': 'Change photo',
|
||||
'account.myAccount.changePhotoButton.specification': '.jpg or.png, max 1MB',
|
||||
'account.myAccount.emailInput.disabledTooltip':
|
||||
'Updating email is not available. Contact the support if you want to change it.',
|
||||
'account.myAccount.emailInput.label': 'Email address:',
|
||||
'account.myAccount.nameInput.label': 'Name:',
|
||||
'analytics.viewsLabel': 'Views',
|
||||
'analytics.startsLabel': 'Starts',
|
||||
'analytics.notAvailableLabel': 'Not available',
|
||||
'analytics.completionRateLabel': 'Completion rate',
|
||||
'auth.signin.heading': 'Sign In',
|
||||
'auth.signin.noAccountLabel.preLink': "Don't have an account?",
|
||||
'auth.signin.noAccountLabel.link': 'Sign up for free',
|
||||
'auth.register.heading': 'Create an account',
|
||||
'auth.register.alreadyHaveAccountLabel.preLink': 'Already have an account?',
|
||||
'auth.register.alreadyHaveAccountLabel.link': 'Sign in',
|
||||
'auth.register.aggreeToTerms':
|
||||
'By signing up, you agree to our {termsOfService} and {privacyPolicy}.',
|
||||
'auth.register.termsOfService': 'terms of service',
|
||||
'auth.register.privacyPolicy': 'privacy policy',
|
||||
'auth.error.default': 'Try signing with a different account.',
|
||||
'auth.error.email': 'Email not found. Try signing with a different provider.',
|
||||
'auth.error.oauthNotLinked':
|
||||
'To confirm your identity, sign in with the same account you used originally.',
|
||||
'auth.error.unknown': 'An error occurred. Please try again.',
|
||||
'auth.signinErrorToast.title': 'Unauthorized',
|
||||
'auth.signinErrorToast.description': 'Sign ups are disabled.',
|
||||
'auth.signinErrorToast.tooManyRequests':
|
||||
'Too many requests. Try again later.',
|
||||
'auth.noProvider.preLink': 'You need to',
|
||||
'auth.noProvider.link':
|
||||
'configure at least one auth provider (Email, Google, GitHub, Facebook or Azure AD).',
|
||||
'auth.orEmailLabel': 'Or with your email',
|
||||
'auth.emailSubmitButton.label': 'Submit',
|
||||
'auth.magicLink.title': 'A magic link email was sent. 🪄',
|
||||
'auth.magicLink.description': 'Make sure to check your spam folder.',
|
||||
'auth.socialLogin.githubButton.label': 'Continue with GitHub',
|
||||
'auth.socialLogin.googleButton.label': 'Continue with Google',
|
||||
'auth.socialLogin.facebookButton.label': 'Continue with Facebook',
|
||||
'auth.socialLogin.azureButton.label': 'Continue with {azureProviderName}',
|
||||
'auth.socialLogin.gitlabButton.label': 'Continue with {gitlabProviderName}',
|
||||
'auth.socialLogin.customButton.label': 'Continue with {customProviderName}',
|
||||
'billing.billingPortalButton.label': 'Billing portal',
|
||||
'billing.contribution.preLink':
|
||||
'Typebot is contributing 1% of your subscription to remove CO₂ from the atmosphere.',
|
||||
'billing.contribution.link': 'Learn more.',
|
||||
'billing.updateSuccessToast.description':
|
||||
'Workspace {plan} plan successfully updated 🎉',
|
||||
'billing.customLimit.preLink': 'Need custom limits? Specific features?',
|
||||
'billing.customLimit.link': "Let's chat!",
|
||||
'billing.upgradeLimitLabel':
|
||||
'You need to upgrade your plan in order to {type}',
|
||||
'billing.currentSubscription.heading': 'Subscription',
|
||||
'billing.currentSubscription.subheading': 'Current workspace subscription:',
|
||||
'billing.currentSubscription.cancelDate': 'Will be cancelled on',
|
||||
'billing.currentSubscription.pastDueAlert':
|
||||
'The latest payment failed. Head over to the billing portal to proceed and avoid having your subscription canceled.',
|
||||
'billing.invoices.heading': 'Invoices',
|
||||
'billing.invoices.empty': 'No invoices found for this workspace.',
|
||||
'billing.invoices.paidAt': 'Paid at',
|
||||
'billing.invoices.subtotal': 'Subtotal',
|
||||
'billing.preCheckoutModal.companyInput.label': 'Company name:',
|
||||
'billing.preCheckoutModal.emailInput.label': 'Email:',
|
||||
'billing.preCheckoutModal.taxId.label': 'Tax ID:',
|
||||
'billing.preCheckoutModal.taxId.placeholder': 'ID type',
|
||||
'billing.preCheckoutModal.submitButton.label': 'Go to checkout',
|
||||
'billing.pricingCard.heading': 'Upgrade to {plan}',
|
||||
'billing.pricingCard.perMonth': '/ month',
|
||||
'billing.pricingCard.plus': ', plus:',
|
||||
'billing.pricingCard.upgradeButton.current': 'Your current plan',
|
||||
'billing.pricingCard.chatsPerMonth': 'chats/mo',
|
||||
'billing.pricingCard.chatsTooltip':
|
||||
'A chat is counted whenever a user starts a discussion. It is independant of the number of messages he sends and receives.',
|
||||
'billing.pricingCard.storageLimit': 'GB of storage',
|
||||
'billing.pricingCard.storageLimitTooltip':
|
||||
'You accumulate storage for every file that your user upload into your bot. If you delete the result, it will free up the space.',
|
||||
'billing.pricingCard.starter.description':
|
||||
'For individuals & small businesses.',
|
||||
'billing.pricingCard.starter.includedSeats': '2 seats included',
|
||||
'billing.pricingCard.starter.brandingRemoved': 'Branding removed',
|
||||
'billing.pricingCard.starter.fileUploadBlock': 'File upload input block',
|
||||
'billing.pricingCard.starter.createFolders': 'Create folders',
|
||||
'billing.pricingCard.pro.mostPopularLabel': 'Most popular',
|
||||
'billing.pricingCard.pro.description': 'For agencies & growing startups.',
|
||||
'billing.pricingCard.pro.everythingFromStarter': 'Everything in Starter',
|
||||
'billing.pricingCard.pro.includedSeats': '5 seats included',
|
||||
'billing.pricingCard.pro.whatsAppIntegration': 'WhatsApp integration',
|
||||
'billing.pricingCard.pro.customDomains': 'Custom domains',
|
||||
'billing.pricingCard.pro.analytics': 'In-depth analytics',
|
||||
'billing.usage.heading': 'Usage',
|
||||
'billing.usage.unlimited': 'Unlimited',
|
||||
'billing.usage.chats.heading': 'Chats',
|
||||
'billing.usage.chats.alert.soonReach':
|
||||
"Your typebots are popular! You will soon reach your plan's chats limit. 🚀",
|
||||
'billing.usage.chats.alert.updatePlan':
|
||||
'Make sure to update your plan to increase this limit and continue chatting with your users.',
|
||||
'billing.usage.chats.resetInfo': '(resets on 1st of every month)',
|
||||
'billing.usage.storage.heading': 'Storage',
|
||||
'billing.usage.storage.alert.soonReach':
|
||||
"Your typebots are popular! You will soon reach your plan's storage limit. 🚀",
|
||||
'billing.usage.storage.alert.updatePlan':
|
||||
'Make sure to update your plan in order to continue collecting uploaded files. You can also delete files to free up space.',
|
||||
'billing.limitMessage.brand': 'remove branding',
|
||||
'billing.limitMessage.customDomain': 'add custom domains',
|
||||
'billing.limitMessage.analytics': 'unlock in-depth analytics',
|
||||
'billing.limitMessage.fileInput': 'use file input blocks',
|
||||
'billing.limitMessage.folder': 'create folders',
|
||||
'billing.upgradeAlert.buttonDefaultLabel': 'More info',
|
||||
'workspace.membersList.inviteInput.placeholder': 'colleague@company.com',
|
||||
'workspace.membersList.inviteButton.label': 'Invite',
|
||||
'workspace.membersList.unlockBanner.label':
|
||||
'Upgrade your plan to work with more team members, and unlock awesome power features 🚀',
|
||||
'workspace.membersList.title': 'Members',
|
||||
'workspace.settings.icon.title': 'Icon',
|
||||
'workspace.settings.name.label': 'Name:',
|
||||
'workspace.settings.deleteButton.label': 'Delete workspace',
|
||||
'workspace.settings.deleteButton.confirmMessage':
|
||||
'Are you sure you want to delete {workspaceName} workspace? All its folders, typebots and results will be deleted forever.',
|
||||
'workspace.settings.modal.menu.myAccount.label': 'My account',
|
||||
'workspace.settings.modal.menu.preferences.label': 'Preferences',
|
||||
'workspace.settings.modal.menu.workspace.label': 'Workspace',
|
||||
'workspace.settings.modal.menu.settings.label': 'Settings',
|
||||
'workspace.settings.modal.menu.members.label': 'Members',
|
||||
'workspace.settings.modal.menu.billingAndUsage.label': 'Billing & Usage',
|
||||
'workspace.settings.modal.menu.version.label': 'Version: {version}',
|
||||
'workspace.dropdown.newButton.label': 'New workspace',
|
||||
'workspace.dropdown.logoutButton.label': 'Log out',
|
||||
'templates.buttons.heading': 'Create a new typebot',
|
||||
'templates.buttons.fromScratchButton.label': 'Start from scratch',
|
||||
'templates.buttons.fromTemplateButton.label': 'Start from a template',
|
||||
'templates.buttons.importFileButton.label': 'Import a file',
|
||||
'templates.modal.menuHeading.marketing': 'Marketing',
|
||||
'templates.modal.menuHeading.product': 'Product',
|
||||
'templates.modal.menuHeading.other': 'Other',
|
||||
'templates.modal.menuHeading.new.tag': 'New',
|
||||
'templates.modal.useTemplateButton.label': 'Use this template',
|
||||
'templates.importFromFileButon.toastError.description':
|
||||
"Failed to parse the file. Are you sure it's a typebot?",
|
||||
'editor.headers.flowButton.label': 'Flow',
|
||||
'editor.headers.themeButton.label': 'Theme',
|
||||
'editor.headers.settingsButton.label': 'Settings',
|
||||
'editor.headers.shareButton.label': 'Share',
|
||||
'editor.headers.resultsButton.label': 'Results',
|
||||
'editor.headers.helpButton.label': 'Help',
|
||||
'editor.headers.savingSpinner.label': 'Saving...',
|
||||
'editor.headers.previewButton.label': 'Preview',
|
||||
'editor.sidebarBlocks.sidebar.lock.label': 'Lock sidebar',
|
||||
'editor.sidebarBlocks.sidebar.unlock.label': 'Unlock sidebar',
|
||||
'editor.sidebarBlocks.sidebar.icon.lock.label': 'Lock',
|
||||
'editor.sidebarBlocks.sidebar.icon.unlock.label': 'Unlock',
|
||||
'editor.sidebarBlocks.blockType.bubbles.heading': 'Bubbles',
|
||||
'editor.sidebarBlocks.blockType.inputs.heading': 'Inputs',
|
||||
'editor.sidebarBlocks.blockType.logic.heading': 'Logic',
|
||||
'editor.sidebarBlocks.blockType.integrations.heading': 'Integrations',
|
||||
'editor.sidebarBlock.start.label': 'Start',
|
||||
'editor.sidebarBlock.text.label': 'Text',
|
||||
'editor.sidebarBlock.image.label': 'Image',
|
||||
'editor.sidebarBlock.video.label': 'Video',
|
||||
'editor.sidebarBlock.embed.label': 'Embed',
|
||||
'editor.sidebarBlock.audio.label': 'Audio',
|
||||
'editor.sidebarBlock.number.label': 'Number',
|
||||
'editor.sidebarBlock.email.label': 'Email',
|
||||
'editor.sidebarBlock.website.label': 'Website',
|
||||
'editor.sidebarBlock.date.label': 'Date',
|
||||
'editor.sidebarBlock.phone.label': 'Phone',
|
||||
'editor.sidebarBlock.button.label': 'Buttons',
|
||||
'editor.sidebarBlock.picChoice.label': 'Pic choice',
|
||||
'editor.sidebarBlock.payment.label': 'Payment',
|
||||
'editor.sidebarBlock.rating.label': 'Rating',
|
||||
'editor.sidebarBlock.file.label': 'File',
|
||||
'editor.sidebarBlock.setVariable.label': 'Set variable',
|
||||
'editor.sidebarBlock.condition.label': 'Condition',
|
||||
'editor.sidebarBlock.redirect.label': 'Redirect',
|
||||
'editor.sidebarBlock.script.label': 'Script',
|
||||
'editor.sidebarBlock.typebot.label': 'Typebot',
|
||||
'editor.sidebarBlock.wait.label': 'Wait',
|
||||
'editor.sidebarBlock.jump.label': 'Jump',
|
||||
'editor.sidebarBlock.abTest.label': 'AB Test',
|
||||
'editor.sidebarBlock.sheets.label': 'Sheets',
|
||||
'editor.sidebarBlock.analytics.label': 'Analytics',
|
||||
'editor.sidebarBlock.webhook.label': 'Webhook',
|
||||
'editor.sidebarBlock.zapier.label': 'Zapier',
|
||||
'editor.sidebarBlock.makecom.label': 'Make.com',
|
||||
'editor.sidebarBlock.pabbly.label': 'Pabbly',
|
||||
'editor.sidebarBlock.chatwoot.label': 'Chatwoot',
|
||||
'editor.sidebarBlock.openai.label': 'OpenAI',
|
||||
'editor.sidebarBlock.pixel.label': 'Pixel',
|
||||
'editor.sidebarBlock.zemanticAi.label': 'Zemantic AI',
|
||||
'editor.blockCard.bubbleBlock.tooltip.label':
|
||||
'Embed a pdf, an iframe, a website...',
|
||||
'editor.blockCard.inputBlock.tooltip.files.label': 'Upload Files',
|
||||
'editor.blockCard.logicBlock.tooltip.code.label': 'Execute Javascript code',
|
||||
'editor.blockCard.logicBlock.tooltip.typebotLink.label':
|
||||
'Link and jump to another typebot',
|
||||
'editor.blockCard.logicBlock.tooltip.jump.label':
|
||||
'Fast forward the flow to another group',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleSheets.label':
|
||||
'Google Sheets',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleAnalytics.label':
|
||||
'Google Analytics',
|
||||
'editor.editableTypebotName.tooltip.rename.label': 'Rename',
|
||||
'editor.gettingStartedModal.editorBasics.heading': 'Editor Basics',
|
||||
'editor.gettingStartedModal.editorBasics.list.one.label':
|
||||
'The left side bar contains blocks that you can drag and drop to the board.',
|
||||
'editor.gettingStartedModal.editorBasics.list.two.label':
|
||||
'You can group blocks together by dropping them below or above each other',
|
||||
'editor.gettingStartedModal.editorBasics.list.three.label':
|
||||
'Connect the groups together',
|
||||
'editor.gettingStartedModal.editorBasics.list.four.label':
|
||||
'Preview your bot by clicking the preview button on the top right',
|
||||
'editor.gettingStartedModal.editorBasics.list.label':
|
||||
'Feel free to use the bottom-right bubble to reach out if you have any question. I usually answer within the next 24 hours. 😃',
|
||||
'editor.gettingStartedModal.seeAction.label': 'See it in action',
|
||||
'editor.gettingStartedModal.seeAction.time': '5 minutes',
|
||||
'editor.gettingStartedModal.seeAction.item.label': 'Other videos',
|
||||
'editor.provider.messages.getTypebotError.title':
|
||||
'Error while fetching typebot. Refresh the page.',
|
||||
'editor.provider.messages.getTypebotError.description':
|
||||
"Couldn't find typebot",
|
||||
'editor.provider.messages.publishedTypebotError.title':
|
||||
'Error while fetching published typebot',
|
||||
'editor.provider.messages.updateTypebotError.title':
|
||||
'Error while updating typebot',
|
||||
'editor.provider.groups.copy.title': 'copy',
|
||||
'editor.blocks.start.text': 'Start',
|
||||
'editor.blocks.bubbles.audio.settings.upload.label': 'Upload',
|
||||
'editor.blocks.bubbles.audio.settings.embedLink.label': 'Embed link',
|
||||
'editor.blocks.bubbles.audio.settings.chooseFile.label': 'Choose a file',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.text':
|
||||
'Works with .MP3s and .WAVs',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.placeholder':
|
||||
'Paste the audio file link...',
|
||||
'editor.blocks.bubbles.audio.settings.autoplay.label': 'Enable autoplay',
|
||||
'editor.blocks.bubbles.audio.node.clickToEdit.text': 'Click to edit...',
|
||||
'editor.blocks.bubbles.embed.node.clickToEdit.text': 'Click to edit...',
|
||||
'editor.blocks.bubbles.embed.node.show.text': 'Show embed',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.placeholder':
|
||||
'Paste the link or code...',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.text':
|
||||
'Works with PDFs, iframes, websites...',
|
||||
'editor.blocks.bubbles.embed.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.image.node.clickToEdit.text': 'Click to edit...',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.label': 'On click link',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder':
|
||||
'Link alt text (description)',
|
||||
'editor.blocks.bubbles.video.node.clickToEdit.text': 'Click to edit...',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.text':
|
||||
'Works with Youtube, Vimeo and others',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.placeholder':
|
||||
'Paste the video link...',
|
||||
'editor.blocks.bubbles.video.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.textEditor.plate.label': 'Text editor',
|
||||
'editor.blocks.bubbles.textEditor.searchVariable.placeholder':
|
||||
'Search for a variable',
|
||||
} as const
|
@ -1,332 +0,0 @@
|
||||
export default {
|
||||
back: 'Retour',
|
||||
'confirmModal.defaultTitle': 'Es-tu sûr ?',
|
||||
'dashboard.header.settingsButton.label': 'Paramètres & Membres',
|
||||
'dashboard.redirectionMessage': 'Redirection en cours...',
|
||||
'dashboard.title': 'Mes typebots',
|
||||
delete: 'Supprimer',
|
||||
errorMessage: "Une erreur s'est produite",
|
||||
cancel: 'Annuler',
|
||||
update: 'Mettre à jour',
|
||||
upgrade: 'Upgrade',
|
||||
downgrade: 'Downgrade',
|
||||
remove: 'Retirer',
|
||||
pending: 'En attente',
|
||||
skip: 'Passer',
|
||||
'folders.createFolderButton.label': 'Créer un dossier',
|
||||
'folders.createTypebotButton.label': 'Créer un typebot',
|
||||
'folders.folderButton.deleteConfirmationMessage':
|
||||
"Es-tu sûr de vouloir supprimer le dossier {folderName} ? (Tout ce qui est à l'intérieur sera déplacé dans le dossier parent ou sur votre tableau de bord)",
|
||||
'folders.typebotButton.live': 'Live',
|
||||
'folders.typebotButton.showMoreOptions': "Afficher plus d'options",
|
||||
'folders.typebotButton.unpublish': 'Dépublier',
|
||||
'folders.typebotButton.duplicate': 'Dupliquer',
|
||||
'folders.typebotButton.delete': 'Supprimer',
|
||||
'folders.typebotButton.deleteConfirmationMessage':
|
||||
'Es-tu sûr de vouloir supprimer votre typebot {typebotName} ?',
|
||||
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||
'Toutes les données associées seront supprimées et ne pourront pas être récupérées.',
|
||||
'account.apiTokens.heading': 'Tokens API',
|
||||
'account.apiTokens.description':
|
||||
"Ces tokens permettent à d'autres applications de contrôler ton compte et tes typebots. Prudence !",
|
||||
'account.apiTokens.createButton.label': 'Créer',
|
||||
'account.apiTokens.deleteButton.label': 'Supprimer',
|
||||
'account.apiTokens.table.nameHeader': 'Nom',
|
||||
'account.apiTokens.table.createdHeader': 'Créé',
|
||||
'account.apiTokens.deleteConfirmationMessage':
|
||||
'Le token {tokenName} sera définitivement révoqué, es-tu sûr de vouloir continuer ?',
|
||||
'account.apiTokens.createModal.createHeading': 'Créer un token',
|
||||
'account.apiTokens.createModal.createdHeading': 'Token créé',
|
||||
'account.apiTokens.createModal.nameInput.label':
|
||||
'Tape un nom unique pour votre token afin de le différencier des autres tokens.',
|
||||
'account.apiTokens.createModal.nameInput.placeholder':
|
||||
'Ex. Zapier, Github, Make.com',
|
||||
'account.apiTokens.createModal.createButton.label': 'Créer un token',
|
||||
'account.apiTokens.createModal.doneButton.label': 'Terminé',
|
||||
'account.apiTokens.createModal.copyInstruction':
|
||||
'Copie ton token et enregistre le dans un endroit sûr.',
|
||||
'account.apiTokens.createModal.securityWarning':
|
||||
'Pour des raisons de sécurité, nous ne pourrons pas le montrer à nouveau.',
|
||||
'account.preferences.language.heading': 'Langue',
|
||||
'account.preferences.language.tooltip':
|
||||
"Les traductions ne sont pas encore complètes. C'est un travail en cours. 🤓",
|
||||
'account.preferences.graphNavigation.heading': "Navigation de l'éditeur",
|
||||
'account.preferences.graphNavigation.mouse.label': 'Souris',
|
||||
'account.preferences.graphNavigation.mouse.description':
|
||||
'Déplace le board en cliquant avec la souris et zoom utilisant la molette',
|
||||
'account.preferences.graphNavigation.trackpad.label': 'Trackpad',
|
||||
'account.preferences.graphNavigation.trackpad.description':
|
||||
'Déplace le board en déplaçant les 2 doigts et zoom pincant',
|
||||
'account.preferences.appearance.heading': 'Apparence',
|
||||
'account.preferences.appearance.systemLabel': 'Système',
|
||||
'account.preferences.appearance.lightLabel': 'Clair',
|
||||
'account.preferences.appearance.darkLabel': 'Sombre',
|
||||
'account.myAccount.changePhotoButton.label': 'Changer de photo',
|
||||
'account.myAccount.changePhotoButton.specification': '.jpg ou.png, max 1MB',
|
||||
'account.myAccount.emailInput.disabledTooltip':
|
||||
"La mise à jour de l'adresse e-mail n'est pas disponible. Contacte le service d'assistance si tu souhaites la modifier.",
|
||||
'account.myAccount.emailInput.label': 'Adresse e-mail:',
|
||||
'account.myAccount.nameInput.label': 'Nom:',
|
||||
'analytics.viewsLabel': 'Vues',
|
||||
'analytics.startsLabel': 'Démarrés',
|
||||
'analytics.notAvailableLabel': 'Non disponible',
|
||||
'analytics.completionRateLabel': 'Taux de complétion',
|
||||
'auth.signin.heading': 'Se connecter',
|
||||
'auth.signin.noAccountLabel.preLink': "Tu n'as pas de compte?",
|
||||
'auth.signin.noAccountLabel.link': 'Inscris-toi gratuitement',
|
||||
'auth.register.heading': 'Créer un compte',
|
||||
'auth.register.alreadyHaveAccountLabel.preLink': 'Tu as déjà un compte?',
|
||||
'auth.register.alreadyHaveAccountLabel.link': 'Se connecter',
|
||||
'auth.register.aggreeToTerms':
|
||||
'En vous inscrivant, vous acceptez nos {termsOfService} et {privacyPolicy}.',
|
||||
'auth.register.termsOfService': "conditions d'utilisation",
|
||||
'auth.register.privacyPolicy': 'politique de confidentialité',
|
||||
'auth.error.default': 'Essaye de te connecter avec un compte différent.',
|
||||
'auth.error.email':
|
||||
'Email non trouvé. Essaye de te connecter avec un fournisseur différent.',
|
||||
'auth.error.oauthNotLinked':
|
||||
'Pour confirmer ton identité, connecte-toi avec le même compte que tu as utilisé à lorigine.',
|
||||
'auth.error.unknown': 'Une erreur est survenue. Essaye à nouveau.',
|
||||
'auth.signinErrorToast.title': 'Non autorisé',
|
||||
'auth.signinErrorToast.description': 'Les inscriptions sont désactivées.',
|
||||
'auth.signinErrorToast.tooManyRequests': 'Trop de tentatives de connexion.',
|
||||
'auth.noProvider.preLink': 'Tu as besoin de',
|
||||
'auth.noProvider.link':
|
||||
"configurer au moins un fournisseur d'authentification (E-mail, Google, GitHub, Facebook ou Azure AD).",
|
||||
'auth.orEmailLabel': 'Ou avec votre email',
|
||||
'auth.emailSubmitButton.label': 'Se connecter',
|
||||
'auth.magicLink.title':
|
||||
"Un email avec un lien d'authentification a été envoyé. 🪄",
|
||||
'auth.magicLink.description': "N'oublie pas de vérifier ton dossier spam.",
|
||||
'auth.socialLogin.githubButton.label': 'Continuer avec GitHub',
|
||||
'auth.socialLogin.googleButton.label': 'Continuer avec Google',
|
||||
'auth.socialLogin.facebookButton.label': 'Continuer avec Facebook',
|
||||
'auth.socialLogin.azureButton.label': 'Continuer avec {azureProviderName}',
|
||||
'auth.socialLogin.gitlabButton.label': 'Continuer avec {gitlabProviderName}',
|
||||
'auth.socialLogin.customButton.label': 'Continuer avec {customProviderName}',
|
||||
'billing.billingPortalButton.label': 'Portail de facturation',
|
||||
'billing.contribution.preLink':
|
||||
"Typebot contribue à hauteur de 1% de votre abonnement pour éliminer le CO₂ de l'atmosphère.",
|
||||
'billing.contribution.link': 'En savoir plus.',
|
||||
'billing.updateSuccessToast.description':
|
||||
'Ton abonnement {plan} a été mis à jour avec succès 🎉',
|
||||
'billing.customLimit.preLink':
|
||||
'Tu as besoin de limites personnalisées ? De fonctionnalités spécifiques ?',
|
||||
'billing.customLimit.link': 'Discutons-en!',
|
||||
'billing.upgradeLimitLabel':
|
||||
'Tu dois mettre à niveau ton abonnement pour {type}',
|
||||
'billing.currentSubscription.heading': 'Abonnement',
|
||||
'billing.currentSubscription.subheading': 'Abonnement actuel du workspace :',
|
||||
'billing.currentSubscription.cancelDate': 'Sera annulé le',
|
||||
'billing.currentSubscription.pastDueAlert':
|
||||
"Le dernier paiement a échoué. Rendez-vous sur le portail de facturation pour effectuer la procédure et éviter l'annulation de votre abonnement.",
|
||||
'billing.invoices.heading': 'Factures',
|
||||
'billing.invoices.empty': 'Aucune facture trouvée pour ce workspace.',
|
||||
'billing.invoices.paidAt': 'Payé le',
|
||||
'billing.invoices.subtotal': 'Sous-total',
|
||||
'billing.preCheckoutModal.companyInput.label': "Nom de l'entreprise :",
|
||||
'billing.preCheckoutModal.emailInput.label': 'E-mail :',
|
||||
'billing.preCheckoutModal.taxId.label': 'Numéro de TVA :',
|
||||
'billing.preCheckoutModal.taxId.placeholder': 'Type',
|
||||
'billing.preCheckoutModal.submitButton.label': 'Continuer',
|
||||
'billing.pricingCard.heading': 'Passer à {plan}',
|
||||
'billing.pricingCard.perMonth': '/ mois',
|
||||
'billing.pricingCard.plus': ', plus :',
|
||||
'billing.pricingCard.upgradeButton.current': 'Abonnement actuel',
|
||||
'billing.pricingCard.chatsPerMonth': 'chats/mois',
|
||||
'billing.pricingCard.chatsTooltip':
|
||||
"Un chat est comptabilisé chaque fois qu'un utilisateur démarre une discussion. Il est indépendant du nombre de messages qu'il envoie et reçoit.",
|
||||
'billing.pricingCard.storageLimit': 'Go de stockage',
|
||||
'billing.pricingCard.storageLimitTooltip':
|
||||
"Tu accumules du stockage pour chaque fichier que ton utilisateur télécharge dans ton bot. Si tu supprimes le résultat, ça libérera de l'espace.",
|
||||
'billing.pricingCard.starter.description':
|
||||
'Pour les particuliers et les petites entreprises.',
|
||||
'billing.pricingCard.starter.includedSeats': '2 collègues inclus',
|
||||
'billing.pricingCard.starter.brandingRemoved': 'Marque enlevée',
|
||||
'billing.pricingCard.starter.fileUploadBlock': "Bloc d'upload de fichier",
|
||||
'billing.pricingCard.starter.createFolders': 'Créer des dossiers',
|
||||
'billing.pricingCard.pro.mostPopularLabel': 'Le plus populaire',
|
||||
'billing.pricingCard.pro.description':
|
||||
'Pour les agences et les startups en croissance.',
|
||||
'billing.pricingCard.pro.everythingFromStarter':
|
||||
"Tout ce qu'il y a dans Starter",
|
||||
'billing.pricingCard.pro.includedSeats': '5 collègues inclus',
|
||||
'billing.pricingCard.pro.whatsAppIntegration': 'Intégration WhatsApp',
|
||||
'billing.pricingCard.pro.customDomains': 'Domaines personnalisés',
|
||||
'billing.pricingCard.pro.analytics': 'Analyses approfondies',
|
||||
'billing.usage.heading': 'Utilisation',
|
||||
'billing.usage.unlimited': 'Illimité',
|
||||
'billing.usage.chats.heading': 'Chats',
|
||||
'billing.usage.chats.alert.soonReach':
|
||||
'Tes typebots sont populaires ! Tu atteindras bientôt la limite de chats de votre abonnement. 🚀',
|
||||
'billing.usage.chats.alert.updatePlan':
|
||||
'Assure-toi de mettre à jour votre abonnement pour augmenter cette limite et continuer à discuter avec vos utilisateurs.',
|
||||
'billing.usage.chats.resetInfo': '(réinitialisé le 1er de chaque mois)',
|
||||
'billing.usage.storage.heading': 'Stockage',
|
||||
'billing.usage.storage.alert.soonReach':
|
||||
'Tes typebots sont populaires ! Tu atteindras bientôt la limite de stockage de ton abonnement. 🚀',
|
||||
'billing.usage.storage.alert.updatePlan':
|
||||
"Assure-toi de mettre à jour votre abonnement pour continuer à collecter des fichiers téléchargés. Tu peux également supprimer des fichiers pour libérer de l'espace.",
|
||||
'billing.limitMessage.brand': 'supprimer la marque',
|
||||
'billing.limitMessage.customDomain': 'ajouter des domaines personnalisés',
|
||||
'billing.limitMessage.analytics': 'débloquer des analyses approfondies',
|
||||
'billing.limitMessage.fileInput': 'utiliser des blocs de saisie de fichiers',
|
||||
'billing.limitMessage.folder': 'créer des dossiers',
|
||||
'billing.upgradeAlert.buttonDefaultLabel': "Plus d'informations",
|
||||
'workspace.membersList.inviteInput.placeholder': 'collegue@entreprise.fr',
|
||||
'workspace.membersList.inviteButton.label': 'Inviter',
|
||||
'workspace.membersList.unlockBanner.label':
|
||||
"Upgrade ton plan pour travailler les membres de ton équipe et débloquer d'autres fonctionnalités puissantes 🚀",
|
||||
'workspace.membersList.title': 'Membres',
|
||||
'workspace.settings.icon.title': 'Icône',
|
||||
'workspace.settings.name.label': 'Nom:',
|
||||
'workspace.settings.deleteButton.label': 'Supprimer le workspace',
|
||||
'workspace.settings.deleteButton.confirmMessage':
|
||||
'Es-tu sûr(e) de vouloir supprimer le workspace {workspaceName} ? Tous ses dossiers, typebots et résultats seront supprimés pour toujours.',
|
||||
'workspace.settings.modal.menu.myAccount.label': 'Mon compte',
|
||||
'workspace.settings.modal.menu.preferences.label': 'Préférences',
|
||||
'workspace.settings.modal.menu.workspace.label': 'Workspace',
|
||||
'workspace.settings.modal.menu.settings.label': 'Paramètres',
|
||||
'workspace.settings.modal.menu.members.label': 'Membres',
|
||||
'workspace.settings.modal.menu.billingAndUsage.label':
|
||||
'Facturation et utilisation',
|
||||
'workspace.settings.modal.menu.version.label': 'Version : {version}',
|
||||
'workspace.dropdown.newButton.label': 'Nouveau workspace',
|
||||
'workspace.dropdown.logoutButton.label': 'Déconnexion',
|
||||
'templates.buttons.heading': 'Créer un nouveau typebot',
|
||||
'templates.buttons.fromScratchButton.label': 'Commencer à partir de zéro',
|
||||
'templates.buttons.fromTemplateButton.label':
|
||||
"Commencer à partir d'un modèle",
|
||||
'templates.buttons.importFileButton.label': 'Importer un fichier',
|
||||
'templates.modal.menuHeading.marketing': 'Marketing',
|
||||
'templates.modal.menuHeading.product': 'Produit',
|
||||
'templates.modal.menuHeading.other': 'Autre',
|
||||
'templates.modal.menuHeading.new.tag': 'Nouveau',
|
||||
'templates.modal.useTemplateButton.label': 'Utiliser ce modèle',
|
||||
'templates.importFromFileButon.toastError.description':
|
||||
"Échec de l'analyse du fichier. Es-tu sûr que c'est un typebot ?",
|
||||
'editor.headers.flowButton.label': 'Flow',
|
||||
'editor.headers.themeButton.label': 'Thème',
|
||||
'editor.headers.settingsButton.label': 'Paramètres',
|
||||
'editor.headers.shareButton.label': 'Partager',
|
||||
'editor.headers.resultsButton.label': 'Résultats',
|
||||
'editor.headers.helpButton.label': 'Aide',
|
||||
'editor.headers.savingSpinner.label': 'Enregistrement...',
|
||||
'editor.headers.previewButton.label': 'Tester',
|
||||
'editor.sidebarBlocks.sidebar.lock.label': 'Fermer la barre latérale',
|
||||
'editor.sidebarBlocks.sidebar.unlock.label': 'Ouvrir la barre latérale',
|
||||
'editor.sidebarBlocks.sidebar.icon.lock.label': 'Fermée',
|
||||
'editor.sidebarBlocks.sidebar.icon.unlock.label': 'Ouverte',
|
||||
'editor.sidebarBlocks.blockType.bubbles.heading': 'Bulles',
|
||||
'editor.sidebarBlocks.blockType.inputs.heading': 'Inputs',
|
||||
'editor.sidebarBlocks.blockType.logic.heading': 'Logique',
|
||||
'editor.sidebarBlocks.blockType.integrations.heading': 'Intégrations',
|
||||
'editor.sidebarBlock.start.label': 'Démarrer',
|
||||
'editor.sidebarBlock.text.label': 'Texte',
|
||||
'editor.sidebarBlock.image.label': 'Image',
|
||||
'editor.sidebarBlock.video.label': 'Vidéo',
|
||||
'editor.sidebarBlock.embed.label': 'Iframe',
|
||||
'editor.sidebarBlock.audio.label': 'Audio',
|
||||
'editor.sidebarBlock.number.label': 'Nombre',
|
||||
'editor.sidebarBlock.email.label': 'Email',
|
||||
'editor.sidebarBlock.website.label': 'Site web',
|
||||
'editor.sidebarBlock.date.label': 'Date',
|
||||
'editor.sidebarBlock.phone.label': 'Téléphone',
|
||||
'editor.sidebarBlock.button.label': 'Boutons',
|
||||
'editor.sidebarBlock.picChoice.label': 'Choix image',
|
||||
'editor.sidebarBlock.payment.label': 'Paiement',
|
||||
'editor.sidebarBlock.rating.label': 'Évaluation',
|
||||
'editor.sidebarBlock.file.label': 'Fichier',
|
||||
'editor.sidebarBlock.setVariable.label': 'Définir variable',
|
||||
'editor.sidebarBlock.condition.label': 'Condition',
|
||||
'editor.sidebarBlock.redirect.label': 'Rediriger',
|
||||
'editor.sidebarBlock.script.label': 'Script',
|
||||
'editor.sidebarBlock.typebot.label': 'Typebot',
|
||||
'editor.sidebarBlock.wait.label': 'Attendre',
|
||||
'editor.sidebarBlock.jump.label': 'Sauter',
|
||||
'editor.sidebarBlock.abTest.label': 'AB Test',
|
||||
'editor.sidebarBlock.sheets.label': 'Sheets',
|
||||
'editor.sidebarBlock.analytics.label': 'Analytics',
|
||||
'editor.sidebarBlock.webhook.label': 'Webhook',
|
||||
'editor.sidebarBlock.zapier.label': 'Zapier',
|
||||
'editor.sidebarBlock.makecom.label': 'Make.com',
|
||||
'editor.sidebarBlock.pabbly.label': 'Pabbly',
|
||||
'editor.sidebarBlock.chatwoot.label': 'Chatwoot',
|
||||
'editor.sidebarBlock.openai.label': 'OpenAI',
|
||||
'editor.sidebarBlock.pixel.label': 'Pixel',
|
||||
'editor.sidebarBlock.zemanticAi.label': 'Zemantic AI',
|
||||
'editor.blockCard.bubbleBlock.tooltip.label':
|
||||
'Intégrer un pdf, un iframe, un site web...',
|
||||
'editor.blockCard.inputBlock.tooltip.files.label': 'Télécharger des fichiers',
|
||||
'editor.blockCard.logicBlock.tooltip.code.label':
|
||||
'Exécuter du code Javascript',
|
||||
'editor.blockCard.logicBlock.tooltip.typebotLink.label':
|
||||
'Lier et exécuter un autre typebot',
|
||||
'editor.blockCard.logicBlock.tooltip.jump.label':
|
||||
'Passer rapidement au groupe suivant',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleSheets.label':
|
||||
'Google Sheets',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleAnalytics.label':
|
||||
'Google Analytics',
|
||||
'editor.editableTypebotName.tooltip.rename.label': 'Renommer',
|
||||
'editor.gettingStartedModal.editorBasics.heading':
|
||||
"Principes de base de l'éditeur",
|
||||
'editor.gettingStartedModal.editorBasics.list.one.label':
|
||||
'La barre latérale de gauche contient des blocs que vous pouvez glisser-déposer sur le graph.',
|
||||
'editor.gettingStartedModal.editorBasics.list.two.label':
|
||||
'Vous pouvez regrouper les blocs en les déposant les uns au-dessus ou en-dessous des autres.',
|
||||
'editor.gettingStartedModal.editorBasics.list.three.label':
|
||||
'Connectez les groupes ensemble.',
|
||||
'editor.gettingStartedModal.editorBasics.list.four.label':
|
||||
'Prévisualisez votre bot en cliquant sur le bouton "Tester" en haut à droite.',
|
||||
'editor.gettingStartedModal.editorBasics.list.label':
|
||||
"N'hésitez pas à utiliser la bulle en bas à droite pour me poser des questions. Je réponds généralement dans les 24 heures. 😃",
|
||||
'editor.gettingStartedModal.seeAction.label': 'Voir en action',
|
||||
'editor.gettingStartedModal.seeAction.time': '5 minutes',
|
||||
'editor.gettingStartedModal.seeAction.item.label': 'Autres vidéos',
|
||||
'editor.provider.messages.getTypebotError.title':
|
||||
'Erreur lors de la récupération du typebot. Rafraîchissez la page.',
|
||||
'editor.provider.messages.getTypebotError.description':
|
||||
'Impossible de trouver le typebot.',
|
||||
'editor.provider.messages.publishedTypebotError.title':
|
||||
'Erreur lors de la récupération du typebot publié',
|
||||
'editor.provider.messages.updateTypebotError.title':
|
||||
'Erreur lors de la mise à jour du typebot',
|
||||
'editor.provider.groups.copy.title': 'copier',
|
||||
'editor.blocks.start.text': 'Démarrer',
|
||||
'editor.blocks.bubbles.audio.settings.upload.label': 'Uploader',
|
||||
'editor.blocks.bubbles.audio.settings.embedLink.label': 'Lien intégré',
|
||||
'editor.blocks.bubbles.audio.settings.chooseFile.label': 'Choisir un fichier',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.text':
|
||||
'Fonctionne avec les fichiers .MP3 et .WAV',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.placeholder':
|
||||
'Collez le lien du fichier audio...',
|
||||
'editor.blocks.bubbles.audio.settings.autoplay.label':
|
||||
'Activer la lecture automatique',
|
||||
'editor.blocks.bubbles.audio.node.clickToEdit.text':
|
||||
'Cliquez pour modifier...',
|
||||
'editor.blocks.bubbles.embed.node.clickToEdit.text':
|
||||
'Cliquez pour modifier...',
|
||||
'editor.blocks.bubbles.embed.node.show.text': "Afficher l'intégration",
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.placeholder':
|
||||
'Collez le lien ou le code...',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.text':
|
||||
'Fonctionne avec les PDF, les iframes, les sites web...',
|
||||
'editor.blocks.bubbles.embed.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.image.node.clickToEdit.text':
|
||||
'Cliquez pour modifier...',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.label':
|
||||
'Redirection au clic',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder':
|
||||
'Texte alternatif du lien (description)',
|
||||
'editor.blocks.bubbles.video.node.clickToEdit.text':
|
||||
'Cliquez pour modifier...',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.text':
|
||||
'Fonctionne avec Youtube, Vimeo et autres',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.placeholder':
|
||||
'Collez le lien de la vidéo...',
|
||||
'editor.blocks.bubbles.video.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.textEditor.plate.label': 'Éditeur de texte',
|
||||
'editor.blocks.bubbles.textEditor.searchVariable.placeholder':
|
||||
'Rechercher une variable',
|
||||
} as const
|
@ -1,19 +0,0 @@
|
||||
import { createI18n } from 'next-international'
|
||||
|
||||
export type I18nFunction = (key: string) => string
|
||||
|
||||
export const {
|
||||
useI18n,
|
||||
useScopedI18n,
|
||||
I18nProvider,
|
||||
getLocaleProps,
|
||||
useCurrentLocale,
|
||||
useChangeLocale,
|
||||
defineLocale,
|
||||
} = createI18n({
|
||||
en: () => import('./en'),
|
||||
fr: () => import('./fr'),
|
||||
pt: () => import('./pt'),
|
||||
'pt-BR': () => import('./pt-BR'),
|
||||
de: () => import('./de'),
|
||||
})
|
@ -1,328 +0,0 @@
|
||||
export default {
|
||||
back: 'Voltar',
|
||||
'confirmModal.defaultTitle': 'Tem certeza?',
|
||||
'dashboard.header.settingsButton.label': 'Configurações & Membros',
|
||||
'dashboard.redirectionMessage': 'Você está sendo redirecionado...',
|
||||
'dashboard.title': 'Meus typebots',
|
||||
delete: 'Apagar',
|
||||
errorMessage: 'Ocorreu um erro',
|
||||
cancel: 'Cancelar',
|
||||
update: 'Atualizar',
|
||||
upgrade: 'Upgrade',
|
||||
downgrade: 'Downgrade',
|
||||
remove: 'Remover',
|
||||
pending: 'Pendente',
|
||||
skip: 'Pular',
|
||||
'folders.createFolderButton.label': 'Criar uma pasta',
|
||||
'folders.createTypebotButton.label': 'Criar um typebot',
|
||||
'folders.folderButton.deleteConfirmationMessage':
|
||||
'Tem certeza de que deseja excluir a pasta {folderName}? (Tudo o que estiver dentro será movido para o seu painel)',
|
||||
'folders.typebotButton.live': 'Live',
|
||||
'folders.typebotButton.showMoreOptions': 'Mostrar mais opções',
|
||||
'folders.typebotButton.unpublish': 'Despublicar',
|
||||
'folders.typebotButton.duplicate': 'Duplicar',
|
||||
'folders.typebotButton.delete': 'Apagar',
|
||||
'folders.typebotButton.deleteConfirmationMessage':
|
||||
'Tem certeza de que deseja excluir seu typebot {typebotName}?',
|
||||
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||
'Todos os dados associados serão excluídos e não poderão ser recuperados.',
|
||||
'account.apiTokens.heading': 'Tokens de API',
|
||||
'account.apiTokens.description':
|
||||
'Esses tokens permitem que outros aplicativos controlem toda a sua conta e typebots. Tenha cuidado!',
|
||||
'account.apiTokens.createButton.label': 'Criar',
|
||||
'account.apiTokens.deleteButton.label': 'Excluir',
|
||||
'account.apiTokens.table.nameHeader': 'Nome',
|
||||
'account.apiTokens.table.createdHeader': 'Criado',
|
||||
'account.apiTokens.deleteConfirmationMessage':
|
||||
'O token {tokenName} será revogado permanentemente. Tem certeza de que deseja continuar?',
|
||||
'account.apiTokens.createModal.createHeading': 'Criar Token',
|
||||
'account.apiTokens.createModal.createdHeading': 'Token Criado',
|
||||
'account.apiTokens.createModal.nameInput.label':
|
||||
'Insira um nome único para o seu token para diferenciá-lo de outros tokens.',
|
||||
'account.apiTokens.createModal.nameInput.placeholder':
|
||||
'Ex. Zapier, Github, Make.com',
|
||||
'account.apiTokens.createModal.createButton.label': 'Criar token',
|
||||
'account.apiTokens.createModal.doneButton.label': 'Concluído',
|
||||
'account.apiTokens.createModal.copyInstruction':
|
||||
'Por favor, copie seu token e guarde-o em um lugar seguro.',
|
||||
'account.apiTokens.createModal.securityWarning':
|
||||
'Por motivos de segurança, não podemos mostrá-lo novamente.',
|
||||
'account.preferences.language.heading': 'Idioma',
|
||||
'account.preferences.language.tooltip':
|
||||
'As traduções ainda não estão completas. É um trabalho em andamento. 🤓',
|
||||
'account.preferences.graphNavigation.heading': 'Navegação do Editor',
|
||||
'account.preferences.graphNavigation.mouse.label': 'Mouse',
|
||||
'account.preferences.graphNavigation.mouse.description':
|
||||
'Mova arrastando o quadro e amplie/reduza usando a roda de rolagem',
|
||||
'account.preferences.graphNavigation.trackpad.label': 'Trackpad',
|
||||
'account.preferences.graphNavigation.trackpad.description':
|
||||
'Mova o quadro usando 2 dedos e amplie/reduza fazendo pinça',
|
||||
'account.preferences.appearance.heading': 'Aparência',
|
||||
'account.preferences.appearance.systemLabel': 'Sistema',
|
||||
'account.preferences.appearance.lightLabel': 'Claro',
|
||||
'account.preferences.appearance.darkLabel': 'Escuro',
|
||||
'account.myAccount.changePhotoButton.label': 'Alterar foto',
|
||||
'account.myAccount.changePhotoButton.specification':
|
||||
'.jpg ou.png, máximo 1MB',
|
||||
'account.myAccount.emailInput.disabledTooltip':
|
||||
'A atualização do e-mail não está disponível. Entre em contato com o suporte se quiser alterá-lo.',
|
||||
'account.myAccount.emailInput.label': 'Endereço de e-mail:',
|
||||
'account.myAccount.nameInput.label': 'Nome:',
|
||||
'analytics.viewsLabel': 'Visualizações',
|
||||
'analytics.startsLabel': 'Inícios',
|
||||
'analytics.completionRateLabel': 'Taxa de conclusão',
|
||||
'analytics.notAvailableLabel': 'Não disponível',
|
||||
'auth.signin.heading': 'Entrar',
|
||||
'auth.signin.noAccountLabel.preLink': 'Não tem uma conta?',
|
||||
'auth.signin.noAccountLabel.link': 'Registre-se gratuitamente',
|
||||
'auth.register.heading': 'Criar uma conta',
|
||||
'auth.register.alreadyHaveAccountLabel.preLink': 'Já tem uma conta?',
|
||||
'auth.register.alreadyHaveAccountLabel.link': 'Entrar',
|
||||
'auth.register.aggreeToTerms':
|
||||
'Ao se cadastrar, você concorda com nossos {termsOfService} e {privacyPolicy}.',
|
||||
'auth.register.termsOfService': 'termos de serviço',
|
||||
'auth.register.privacyPolicy': 'política de privacidade',
|
||||
'auth.error.default': 'Tente entrar com uma conta diferente.',
|
||||
'auth.error.email':
|
||||
'E-mail não encontrado. Tente entrar com um provedor diferente.',
|
||||
'auth.error.oauthNotLinked':
|
||||
'Já existe uma conta vinculada a esse E-mail, entre com a mesma conta que você usou originalmente.',
|
||||
'auth.error.unknown': 'Ocorreu um erro. Tente novamente.',
|
||||
'auth.signinErrorToast.title': 'Não autorizado',
|
||||
'auth.signinErrorToast.description': 'As inscrições estão desativadas.',
|
||||
'auth.signinErrorToast.tooManyRequests':
|
||||
'Muitas tentativas. Tente novamente mais tarde.',
|
||||
'auth.noProvider.preLink': 'Você precisa',
|
||||
'auth.noProvider.link':
|
||||
'configurar pelo menos um provedor de autenticação (E-mail, Google, GitHub, Facebook ou Azure AD).',
|
||||
'auth.orEmailLabel': 'Ou com seu email',
|
||||
'auth.emailSubmitButton.label': 'Enviar',
|
||||
'auth.magicLink.title': 'Um email com o link mágico foi enviado. 🪄',
|
||||
'auth.magicLink.description': 'Certifique-se de verificar sua pasta de spam.',
|
||||
'auth.socialLogin.githubButton.label': 'Continuar com GitHub',
|
||||
'auth.socialLogin.googleButton.label': 'Continuar com Google',
|
||||
'auth.socialLogin.facebookButton.label': 'Continuar com Facebook',
|
||||
'auth.socialLogin.azureButton.label': 'Continuar com {azureProviderName}',
|
||||
'auth.socialLogin.gitlabButton.label': 'Continuar com {gitlabProviderName}',
|
||||
'auth.socialLogin.customButton.label': 'Continuar com {customProviderName}',
|
||||
'billing.billingPortalButton.label': 'Portal de cobrança',
|
||||
'billing.contribution.preLink':
|
||||
'A Typebot está contribuindo com 1% da sua assinatura para remover o CO₂ da atmosfera.',
|
||||
'billing.contribution.link': 'Saiba mais.',
|
||||
'billing.updateSuccessToast.description':
|
||||
'Sua assinatura {plan} foi atualizada com sucesso 🎉',
|
||||
'billing.customLimit.preLink':
|
||||
'Precisa de limites personalizados? Recursos específicos?',
|
||||
'billing.customLimit.link': 'Vamos conversar!',
|
||||
'billing.upgradeLimitLabel':
|
||||
'Você precisa atualizar sua assinatura para {type}',
|
||||
'billing.currentSubscription.heading': 'Assinatura',
|
||||
'billing.currentSubscription.subheading':
|
||||
'Assinatura atual do espaço de trabalho:',
|
||||
'billing.currentSubscription.cancelDate': 'Será cancelado em',
|
||||
'billing.currentSubscription.pastDueAlert':
|
||||
'O último pagamento falhou. Acesse o portal de faturamento para prosseguir e evitar o cancelamento da sua assinatura.',
|
||||
'billing.invoices.heading': 'Faturas',
|
||||
'billing.invoices.empty':
|
||||
'Nenhuma fatura encontrada para este espaço de trabalho.',
|
||||
'billing.invoices.paidAt': 'Pago em',
|
||||
'billing.invoices.subtotal': 'Subtotal',
|
||||
'billing.preCheckoutModal.companyInput.label': 'Nome da empresa:',
|
||||
'billing.preCheckoutModal.emailInput.label': 'E-mail:',
|
||||
'billing.preCheckoutModal.taxId.label': 'Identificação fiscal (CPF):',
|
||||
'billing.preCheckoutModal.taxId.placeholder': 'Tipo de ID',
|
||||
'billing.preCheckoutModal.submitButton.label':
|
||||
'Ir para a finalização da compra',
|
||||
'billing.pricingCard.heading': 'Mudar para {plan}',
|
||||
'billing.pricingCard.perMonth': '/ mês',
|
||||
'billing.pricingCard.plus': ', mais:',
|
||||
'billing.pricingCard.upgradeButton.current': 'Sua assinatura atual',
|
||||
'billing.pricingCard.chatsPerMonth': 'chats/mês',
|
||||
'billing.pricingCard.chatsTooltip':
|
||||
'Um chat é contado sempre que um usuário inicia uma discussão. Ele é independente do número de mensagens que ele envia e recebe.',
|
||||
'billing.pricingCard.storageLimit': 'GB de armazenamento',
|
||||
'billing.pricingCard.storageLimitTooltip':
|
||||
'Você acumula armazenamento para cada arquivo que seu usuário carrega em seu bot. Se você excluir o resultado, ele liberará espaço.',
|
||||
'billing.pricingCard.starter.description':
|
||||
'Para indivíduos e pequenas empresas.',
|
||||
'billing.pricingCard.starter.includedSeats': '2 assentos incluídos',
|
||||
'billing.pricingCard.starter.brandingRemoved': 'Marca removida',
|
||||
'billing.pricingCard.starter.fileUploadBlock': 'Bloco de envio de arquivo',
|
||||
'billing.pricingCard.starter.createFolders': 'Criar pastas',
|
||||
'billing.pricingCard.pro.mostPopularLabel': 'Mais popular',
|
||||
'billing.pricingCard.pro.description':
|
||||
'Para agências e startups em crescimento.',
|
||||
'billing.pricingCard.pro.everythingFromStarter': 'Tudo em Starter',
|
||||
'billing.pricingCard.pro.includedSeats': '5 assentos incluídos',
|
||||
'billing.pricingCard.pro.whatsAppIntegration': 'Integração do WhatsApp',
|
||||
'billing.pricingCard.pro.customDomains': 'Domínios personalizados',
|
||||
'billing.pricingCard.pro.analytics': 'Análises aprofundadas',
|
||||
'billing.usage.heading': 'Uso',
|
||||
'billing.usage.unlimited': 'Ilimitado',
|
||||
'billing.usage.chats.heading': 'Chats',
|
||||
'billing.usage.chats.alert.soonReach':
|
||||
'Seus typebots são populares! Você logo alcançará o limite de chats de seu plano. 🚀',
|
||||
'billing.usage.chats.alert.updatePlan':
|
||||
'Certifique-se de atualizar seu plano para aumentar esse limite e continuar conversando com seus usuários.',
|
||||
'billing.usage.chats.resetInfo': '(reiniciado todo dia 1)',
|
||||
'billing.usage.storage.heading': 'Armazenamento',
|
||||
'billing.usage.storage.alert.soonReach':
|
||||
'Seus typebots são populares! Você logo alcançará o limite de armazenamento de seu plano. 🚀',
|
||||
'billing.usage.storage.alert.updatePlan':
|
||||
'Certifique-se de atualizar seu plano para continuar coletando arquivos enviados. Você também pode excluir arquivos para liberar espaço.',
|
||||
'billing.limitMessage.brand': 'remover a marca',
|
||||
'billing.limitMessage.customDomain': 'adicionar domínios personalizados',
|
||||
'billing.limitMessage.analytics': 'desbloquear análises aprofundadas',
|
||||
'billing.limitMessage.fileInput': 'usar blocos de envio de arquivo',
|
||||
'billing.limitMessage.folder': 'criar pastas',
|
||||
'billing.upgradeAlert.buttonDefaultLabel': 'Mais informações',
|
||||
'workspace.membersList.inviteInput.placeholder': 'colega@empresa.com',
|
||||
'workspace.membersList.inviteButton.label': 'Convidar',
|
||||
'workspace.membersList.unlockBanner.label':
|
||||
'Atualize seu plano para trabalhar com mais membros da equipe e desbloqueie recursos incríveis 🚀',
|
||||
'workspace.membersList.title': 'Membros',
|
||||
'workspace.settings.icon.title': 'Ícone',
|
||||
'workspace.settings.name.label': 'Nome:',
|
||||
'workspace.settings.deleteButton.label': 'Excluir espaço de trabalho',
|
||||
'workspace.settings.deleteButton.confirmMessage':
|
||||
'Você tem certeza de que deseja excluir o espaço de trabalho {workspaceName}? Todas as suas pastas, typebots e resultados serão excluídos permanentemente.',
|
||||
'workspace.settings.modal.menu.myAccount.label': 'Minha conta',
|
||||
'workspace.settings.modal.menu.preferences.label': 'Preferências',
|
||||
'workspace.settings.modal.menu.workspace.label': 'Espaço de trabalho',
|
||||
'workspace.settings.modal.menu.settings.label': 'Configurações',
|
||||
'workspace.settings.modal.menu.members.label': 'Membros',
|
||||
'workspace.settings.modal.menu.billingAndUsage.label': 'Faturamento e uso',
|
||||
'workspace.settings.modal.menu.version.label': 'Versão: {version}',
|
||||
'workspace.dropdown.newButton.label': 'Novo espaço de trabalho',
|
||||
'workspace.dropdown.logoutButton.label': 'Sair',
|
||||
'templates.buttons.heading': 'Criar um novo typebot',
|
||||
'templates.buttons.fromScratchButton.label': 'Comece do zero',
|
||||
'templates.buttons.fromTemplateButton.label': 'Comece a partir de um modelo',
|
||||
'templates.buttons.importFileButton.label': 'Importar um arquivo',
|
||||
'templates.modal.menuHeading.marketing': 'Marketing',
|
||||
'templates.modal.menuHeading.product': 'Produto',
|
||||
'templates.modal.menuHeading.other': 'Outros',
|
||||
'templates.modal.menuHeading.new.tag': 'Novo',
|
||||
'templates.modal.useTemplateButton.label': 'Usar esse modelo',
|
||||
'templates.importFromFileButon.toastError.description':
|
||||
'Falha ao analisar o arquivo. Tem certeza de que é um typebot?',
|
||||
'editor.headers.flowButton.label': 'Fluxo',
|
||||
'editor.headers.themeButton.label': 'Tema',
|
||||
'editor.headers.settingsButton.label': 'Configurações',
|
||||
'editor.headers.shareButton.label': 'Compartilhar',
|
||||
'editor.headers.resultsButton.label': 'Resultados',
|
||||
'editor.headers.helpButton.label': 'Ajuda',
|
||||
'editor.headers.savingSpinner.label': 'Salvando...',
|
||||
'editor.headers.previewButton.label': 'Visualizar',
|
||||
'editor.sidebarBlocks.sidebar.lock.label': 'Bloquear barra lateral',
|
||||
'editor.sidebarBlocks.sidebar.unlock.label': 'Desbloquear barra lateral',
|
||||
'editor.sidebarBlocks.sidebar.icon.lock.label': 'Bloquear',
|
||||
'editor.sidebarBlocks.sidebar.icon.unlock.label': 'Desbloquear',
|
||||
'editor.sidebarBlocks.blockType.bubbles.heading': 'Bubbles',
|
||||
'editor.sidebarBlocks.blockType.inputs.heading': 'Inputs',
|
||||
'editor.sidebarBlocks.blockType.logic.heading': 'Condicionais',
|
||||
'editor.sidebarBlocks.blockType.integrations.heading': 'Integrações',
|
||||
'editor.sidebarBlock.start.label': 'Início',
|
||||
'editor.sidebarBlock.text.label': 'Texto',
|
||||
'editor.sidebarBlock.image.label': 'Imagem',
|
||||
'editor.sidebarBlock.video.label': 'Vídeo',
|
||||
'editor.sidebarBlock.embed.label': 'Incorporar',
|
||||
'editor.sidebarBlock.audio.label': 'Áudio',
|
||||
'editor.sidebarBlock.number.label': 'Número',
|
||||
'editor.sidebarBlock.email.label': 'Email',
|
||||
'editor.sidebarBlock.website.label': 'Website',
|
||||
'editor.sidebarBlock.date.label': 'Data',
|
||||
'editor.sidebarBlock.phone.label': 'Telefone',
|
||||
'editor.sidebarBlock.button.label': 'Botão',
|
||||
'editor.sidebarBlock.picChoice.label': 'Seleção de Imagem',
|
||||
'editor.sidebarBlock.payment.label': 'Pagamento',
|
||||
'editor.sidebarBlock.rating.label': 'Avaliação',
|
||||
'editor.sidebarBlock.file.label': 'Arquivo',
|
||||
'editor.sidebarBlock.setVariable.label': 'Variável',
|
||||
'editor.sidebarBlock.condition.label': 'Condição',
|
||||
'editor.sidebarBlock.redirect.label': 'Redirecionar',
|
||||
'editor.sidebarBlock.script.label': 'Script',
|
||||
'editor.sidebarBlock.typebot.label': 'Typebot',
|
||||
'editor.sidebarBlock.wait.label': 'Espera',
|
||||
'editor.sidebarBlock.jump.label': 'Pular',
|
||||
'editor.sidebarBlock.abTest.label': 'Teste AB',
|
||||
'editor.sidebarBlock.sheets.label': 'Sheets',
|
||||
'editor.sidebarBlock.analytics.label': 'Analytics',
|
||||
'editor.sidebarBlock.webhook.label': 'Webhook',
|
||||
'editor.sidebarBlock.zapier.label': 'Zapier',
|
||||
'editor.sidebarBlock.makecom.label': 'Make.com',
|
||||
'editor.sidebarBlock.pabbly.label': 'Pabbly',
|
||||
'editor.sidebarBlock.chatwoot.label': 'Chatwoot',
|
||||
'editor.sidebarBlock.openai.label': 'OpenAI',
|
||||
'editor.sidebarBlock.pixel.label': 'Pixel',
|
||||
'editor.sidebarBlock.zemanticAi.label': 'Zemantic AI',
|
||||
'editor.blockCard.bubbleBlock.tooltip.label':
|
||||
'Incorporar pdf, iframe, website...',
|
||||
'editor.blockCard.inputBlock.tooltip.files.label': 'Carregar Ficheiros',
|
||||
'editor.blockCard.logicBlock.tooltip.code.label':
|
||||
'Executar código Javascript',
|
||||
'editor.blockCard.logicBlock.tooltip.typebotLink.label':
|
||||
'Link e salte para outro typebot',
|
||||
'editor.blockCard.logicBlock.tooltip.jump.label':
|
||||
'Encaminhar fluxo para outro grupo',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleSheets.label':
|
||||
'Google Sheets',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleAnalytics.label':
|
||||
'Google Analytics',
|
||||
'editor.editableTypebotName.tooltip.rename.label': 'Renomear',
|
||||
'editor.gettingStartedModal.editorBasics.heading': 'Fundamentos do Editor',
|
||||
'editor.gettingStartedModal.editorBasics.list.one.label':
|
||||
'A barra lateral esquerda contém blocos que podem ser arrastados e soltos no quadro.',
|
||||
'editor.gettingStartedModal.editorBasics.list.two.label':
|
||||
'Você pode agrupar blocos juntos, colocando-os abaixo ou acima dos outros',
|
||||
'editor.gettingStartedModal.editorBasics.list.three.label':
|
||||
'Conecte os grupos entre eles',
|
||||
'editor.gettingStartedModal.editorBasics.list.four.label':
|
||||
'Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito',
|
||||
'editor.gettingStartedModal.editorBasics.list.label':
|
||||
'Sinta-se à vontade para usar o chat no canto inferior direito para entrar em contato se tiver alguma dúvida. Normalmente, respondo nas próximas 24 horas. 😃',
|
||||
'editor.gettingStartedModal.seeAction.label': 'Veja como funciona em',
|
||||
'editor.gettingStartedModal.seeAction.time': '5 minutos',
|
||||
'editor.gettingStartedModal.seeAction.item.label': 'Outros vídeos',
|
||||
'editor.provider.messages.getTypebotError.title':
|
||||
'Erro ao obter o typebot. Atualize a página.',
|
||||
'editor.provider.messages.getTypebotError.description':
|
||||
'Não foi possível encontrar o typebot',
|
||||
'editor.provider.messages.publishedTypebotError.title':
|
||||
'Erro ao obter o typebot publicado',
|
||||
'editor.provider.messages.updateTypebotError.title':
|
||||
'Erro ao atualizar o typebot',
|
||||
'editor.provider.groups.copy.title': 'Cópia',
|
||||
'editor.blocks.start.text': 'Início',
|
||||
'editor.blocks.bubbles.audio.settings.upload.label': 'Carregar',
|
||||
'editor.blocks.bubbles.audio.settings.embedLink.label': 'Incorporar link',
|
||||
'editor.blocks.bubbles.audio.settings.chooseFile.label':
|
||||
'Escolher um arquivo',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.text':
|
||||
'Compatível com .MP3s e .WAVs',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.placeholder':
|
||||
'Colar o link do arquivo de áudio...',
|
||||
'editor.blocks.bubbles.audio.settings.autoplay.label':
|
||||
'Ativar reprodução automática',
|
||||
'editor.blocks.bubbles.audio.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.embed.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.embed.node.show.text': 'Mostrar incorporação',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.placeholder':
|
||||
'Colar o link ou código...',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.text':
|
||||
'Compatível com PDFs, iframes, websites...',
|
||||
'editor.blocks.bubbles.embed.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.image.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.label': 'Link ao clicar',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder':
|
||||
'Texto alternativo do link (descrição)',
|
||||
'editor.blocks.bubbles.video.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.text':
|
||||
'Compatível com Youtube, Vimeo e outros',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.placeholder':
|
||||
'Colar o link do vídeo...',
|
||||
'editor.blocks.bubbles.video.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.textEditor.plate.label': 'Editor de texto',
|
||||
'editor.blocks.bubbles.textEditor.searchVariable.placeholder':
|
||||
'Pesquisar uma variável',
|
||||
} as const
|
@ -1,329 +0,0 @@
|
||||
export default {
|
||||
back: 'Voltar',
|
||||
'confirmModal.defaultTitle': 'Tem a certeza?',
|
||||
'dashboard.header.settingsButton.label': 'Configurações & Membros',
|
||||
'dashboard.redirectionMessage': 'Está a ser redirecionado...',
|
||||
'dashboard.title': 'Os meus typebots',
|
||||
delete: 'Apagar',
|
||||
errorMessage: 'Ocorreu um erro',
|
||||
cancel: 'Cancelar',
|
||||
update: 'Atualizar',
|
||||
upgrade: 'Upgrade',
|
||||
downgrade: 'Downgrade',
|
||||
remove: 'Remover',
|
||||
pending: 'Pendente',
|
||||
skip: 'Saltar',
|
||||
'folders.createFolderButton.label': 'Criar uma pasta',
|
||||
'folders.createTypebotButton.label': 'Criar um typebot',
|
||||
'folders.folderButton.deleteConfirmationMessage':
|
||||
'Tem a certeza de que deseja excluir a pasta {folderName}? (Tudo o que estiver dentro será movido para o seu painel)',
|
||||
'folders.typebotButton.live': 'Ao Vivo',
|
||||
'folders.typebotButton.showMoreOptions': 'Mostrar mais opções',
|
||||
'folders.typebotButton.unpublish': 'Despublicar',
|
||||
'folders.typebotButton.duplicate': 'Duplicar',
|
||||
'folders.typebotButton.delete': 'Apagar',
|
||||
'folders.typebotButton.deleteConfirmationMessage':
|
||||
'Tem a certeza de que deseja excluir o seu typebot {typebotName}?',
|
||||
'folders.typebotButton.deleteConfirmationMessageWarning':
|
||||
'Todos os dados associados serão excluídos e não poderão ser recuperados.',
|
||||
'account.apiTokens.heading': 'Tokens de API',
|
||||
'account.apiTokens.description':
|
||||
'Estes tokens permitem que outras aplicações controlem toda a sua conta e typebots. Tenha cuidado!',
|
||||
'account.apiTokens.createButton.label': 'Criar',
|
||||
'account.apiTokens.deleteButton.label': 'Excluir',
|
||||
'account.apiTokens.table.nameHeader': 'Nome',
|
||||
'account.apiTokens.table.createdHeader': 'Criado',
|
||||
'account.apiTokens.deleteConfirmationMessage':
|
||||
'O token {tokenName} será revogado permanentemente. Tem a certeza de que deseja continuar?',
|
||||
'account.apiTokens.createModal.createHeading': 'Criar Token',
|
||||
'account.apiTokens.createModal.createdHeading': 'Token Criado',
|
||||
'account.apiTokens.createModal.nameInput.label':
|
||||
'Insira um nome único para o seu token para o diferenciar de outros tokens.',
|
||||
'account.apiTokens.createModal.nameInput.placeholder':
|
||||
'Ex. Zapier, Github, Make.com',
|
||||
'account.apiTokens.createModal.createButton.label': 'Criar token',
|
||||
'account.apiTokens.createModal.doneButton.label': 'Concluído',
|
||||
'account.apiTokens.createModal.copyInstruction':
|
||||
'Por favor, copie o seu token e guarde-o num lugar seguro.',
|
||||
'account.apiTokens.createModal.securityWarning':
|
||||
'Por razões de segurança, não o podemos mostrar novamente.',
|
||||
'account.preferences.language.heading': 'Idioma',
|
||||
'account.preferences.language.tooltip':
|
||||
'As traduções ainda não estão completas. É um trabalho em curso. 🤓',
|
||||
'account.preferences.graphNavigation.heading': 'Navegação do Editor',
|
||||
'account.preferences.graphNavigation.mouse.label': 'Rato',
|
||||
'account.preferences.graphNavigation.mouse.description':
|
||||
'Mova arrastando o quadro e amplie/reduza usando a roda de deslocamento',
|
||||
'account.preferences.graphNavigation.trackpad.label': 'Trackpad',
|
||||
'account.preferences.graphNavigation.trackpad.description':
|
||||
'Mova o quadro usando 2 dedos e amplie/reduza fazendo pinça',
|
||||
'account.preferences.appearance.heading': 'Aparência',
|
||||
'account.preferences.appearance.systemLabel': 'Sistema',
|
||||
'account.preferences.appearance.lightLabel': 'Claro',
|
||||
'account.preferences.appearance.darkLabel': 'Escuro',
|
||||
'account.myAccount.changePhotoButton.label': 'Alterar foto',
|
||||
'account.myAccount.changePhotoButton.specification':
|
||||
'.jpg ou.png, máximo 1MB',
|
||||
'account.myAccount.emailInput.disabledTooltip':
|
||||
'A atualização do e-mail não está disponível. Entre em contacto com o apoio se quiser alterá-lo.',
|
||||
'account.myAccount.emailInput.label': 'Endereço de e-mail:',
|
||||
'account.myAccount.nameInput.label': 'Nome:',
|
||||
'analytics.viewsLabel': 'Visualizações',
|
||||
'analytics.startsLabel': 'Inícios',
|
||||
'analytics.notAvailableLabel': 'Não disponível',
|
||||
'analytics.completionRateLabel': 'Taxa de conclusão',
|
||||
'auth.signin.heading': 'Entrar',
|
||||
'auth.signin.noAccountLabel.preLink': 'Não tem uma conta?',
|
||||
'auth.signin.noAccountLabel.link': 'Registe-se gratuitamente',
|
||||
'auth.register.heading': 'Criar uma conta',
|
||||
'auth.register.alreadyHaveAccountLabel.preLink': 'Já tem uma conta?',
|
||||
'auth.register.alreadyHaveAccountLabel.link': 'Entrar',
|
||||
'auth.register.aggreeToTerms':
|
||||
'Ao registar-se, concorda com os nossos {termsOfService} e {privacyPolicy}.',
|
||||
'auth.register.termsOfService': 'termos de serviço',
|
||||
'auth.register.privacyPolicy': 'política de privacidade',
|
||||
'auth.error.default': 'Tente entrar com uma conta diferente.',
|
||||
'auth.error.email':
|
||||
'E-mail não encontrado. Tente entrar com um fornecedor diferente.',
|
||||
'auth.error.oauthNotLinked':
|
||||
'Para confirmar a sua identidade, entre com a mesma conta que usou originalmente.',
|
||||
'auth.error.unknown': 'Ocorreu um erro. Tente novamente.',
|
||||
'auth.signinErrorToast.title': 'Não autorizado',
|
||||
'auth.signinErrorToast.description': 'As inscrições estão desativadas.',
|
||||
'auth.signinErrorToast.tooManyRequests':
|
||||
'Muitas tentativas. Tente novamente mais tarde.',
|
||||
'auth.noProvider.preLink': 'Precisa de',
|
||||
'auth.noProvider.link':
|
||||
'configurar pelo menos um fornecedor de autenticação (E-mail, Google, GitHub, Facebook ou Azure AD).',
|
||||
'auth.orEmailLabel': 'Ou com o seu e-mail',
|
||||
'auth.emailSubmitButton.label': 'Enviar',
|
||||
'auth.magicLink.title': 'Foi enviado um e-mail com a ligação mágica. 🪄',
|
||||
'auth.magicLink.description':
|
||||
'Certifique-se de verificar a sua pasta de spam.',
|
||||
'auth.socialLogin.githubButton.label': 'Continuar com GitHub',
|
||||
'auth.socialLogin.googleButton.label': 'Continuar com Google',
|
||||
'auth.socialLogin.facebookButton.label': 'Continuar com Facebook',
|
||||
'auth.socialLogin.azureButton.label': 'Continuar com {azureProviderName}',
|
||||
'auth.socialLogin.gitlabButton.label': 'Continuar com {gitlabProviderName}',
|
||||
'auth.socialLogin.customButton.label': 'Continuar com {customProviderName}',
|
||||
'billing.billingPortalButton.label': 'Portal de facturação',
|
||||
'billing.contribution.preLink':
|
||||
'A Typebot está a contribuir com 1% da sua subscrição para remover o CO₂ da atmosfera.',
|
||||
'billing.contribution.link': 'Saiba mais.',
|
||||
'billing.updateSuccessToast.description':
|
||||
'A sua subscrição {plan} foi atualizada com sucesso 🎉',
|
||||
'billing.customLimit.preLink':
|
||||
'Precisa de limites personalizados? Funcionalidades específicas?',
|
||||
'billing.customLimit.link': 'Vamos falar!',
|
||||
'billing.upgradeLimitLabel':
|
||||
'Precisa de atualizar a sua subscrição para {type}',
|
||||
'billing.currentSubscription.heading': 'Subscrição',
|
||||
'billing.currentSubscription.subheading':
|
||||
'Subscrição actual do espaço de trabalho:',
|
||||
'billing.currentSubscription.cancelDate': 'Será cancelado em',
|
||||
'billing.currentSubscription.pastDueAlert':
|
||||
'O último pagamento falhou. Acesse o portal de faturamento para continuar e evitar o cancelamento da sua assinatura.',
|
||||
'billing.invoices.heading': 'Facturas',
|
||||
'billing.invoices.empty':
|
||||
'Nenhuma factura encontrada para este espaço de trabalho.',
|
||||
'billing.invoices.paidAt': 'Pago em',
|
||||
'billing.invoices.subtotal': 'Subtotal',
|
||||
'billing.preCheckoutModal.companyInput.label': 'Nome da empresa:',
|
||||
'billing.preCheckoutModal.emailInput.label': 'E-mail:',
|
||||
'billing.preCheckoutModal.taxId.label': 'Identificação fiscal (NIF):',
|
||||
'billing.preCheckoutModal.taxId.placeholder': 'Tipo de ID',
|
||||
'billing.preCheckoutModal.submitButton.label':
|
||||
'Ir para a finalização da compra',
|
||||
'billing.pricingCard.heading': 'Mudar para {plan}',
|
||||
'billing.pricingCard.perMonth': '/ mês',
|
||||
'billing.pricingCard.plus': ', mais:',
|
||||
'billing.pricingCard.upgradeButton.current': 'A sua subscrição atual',
|
||||
'billing.pricingCard.chatsPerMonth': 'chats/mês',
|
||||
'billing.pricingCard.chatsTooltip':
|
||||
'Um chat é contado sempre que um utilizador inicia uma discussão. Ele é independente do número de mensagens que envia e recebe.',
|
||||
'billing.pricingCard.storageLimit': 'GB de armazenamento',
|
||||
'billing.pricingCard.storageLimitTooltip':
|
||||
'Acumula armazenamento para cada ficheiro que o seu utilizador carrega no seu bot. Se excluir o resultado, ele libertará espaço.',
|
||||
'billing.pricingCard.starter.description':
|
||||
'Para indivíduos e pequenas empresas.',
|
||||
'billing.pricingCard.starter.includedSeats': '2 lugares incluídos',
|
||||
'billing.pricingCard.starter.brandingRemoved': 'Marca removida',
|
||||
'billing.pricingCard.starter.fileUploadBlock': 'Bloco de envio de ficheiro',
|
||||
'billing.pricingCard.starter.createFolders': 'Criar pastas',
|
||||
'billing.pricingCard.pro.mostPopularLabel': 'Mais popular',
|
||||
'billing.pricingCard.pro.description':
|
||||
'Para agências e startups em crescimento.',
|
||||
'billing.pricingCard.pro.everythingFromStarter': 'Tudo em Starter',
|
||||
'billing.pricingCard.pro.includedSeats': '5 lugares incluídos',
|
||||
'billing.pricingCard.pro.whatsAppIntegration': 'Integração do WhatsApp',
|
||||
'billing.pricingCard.pro.customDomains': 'Domínios personalizados',
|
||||
'billing.pricingCard.pro.analytics': 'Análises aprofundadas',
|
||||
'billing.usage.heading': 'Uso',
|
||||
'billing.usage.unlimited': 'Ilimitado',
|
||||
'billing.usage.chats.heading': 'Chats',
|
||||
'billing.usage.chats.alert.soonReach':
|
||||
'Os seus typebots são populares! Vai alcançar em breve o limite de chats do seu plano. 🚀',
|
||||
'billing.usage.chats.alert.updatePlan':
|
||||
'Certifique-se de atualizar o seu plano para aumentar esse limite e continuar a conversar com os seus utilizadores.',
|
||||
'billing.usage.chats.resetInfo': '(reiniciado a cada dia 1)',
|
||||
'billing.usage.storage.heading': 'Armazenamento',
|
||||
'billing.usage.storage.alert.soonReach':
|
||||
'Os seus typebots são populares! Vai alcançar em breve o limite de armazenamento do seu plano. 🚀',
|
||||
'billing.usage.storage.alert.updatePlan':
|
||||
'Certifique-se de atualizar o seu plano para continuar a recolher ficheiros enviados. Também pode excluir ficheiros para libertar espaço.',
|
||||
'billing.limitMessage.brand': 'remover a marca',
|
||||
'billing.limitMessage.customDomain': 'adicionar domínios personalizados',
|
||||
'billing.limitMessage.analytics': 'desbloquear análises aprofundadas',
|
||||
'billing.limitMessage.fileInput': 'usar blocos de envio de ficheiros',
|
||||
'billing.limitMessage.folder': 'criar pastas',
|
||||
'billing.upgradeAlert.buttonDefaultLabel': 'Mais informações',
|
||||
'workspace.membersList.inviteInput.placeholder': 'colega@empresa.com',
|
||||
'workspace.membersList.inviteButton.label': 'Convidar',
|
||||
'workspace.membersList.unlockBanner.label':
|
||||
'Atualize o seu plano para trabalhar com mais membros da equipa e desbloquear funcionalidades incríveis 🚀',
|
||||
'workspace.membersList.title': 'Membros',
|
||||
'workspace.settings.icon.title': 'Ícone',
|
||||
'workspace.settings.name.label': 'Nome:',
|
||||
'workspace.settings.deleteButton.label': 'Eliminar espaço de trabalho',
|
||||
'workspace.settings.deleteButton.confirmMessage':
|
||||
'Tem a certeza de que deseja eliminar o espaço de trabalho {workspaceName}? Todas as suas pastas, typebots e resultados serão excluídos permanentemente.',
|
||||
'workspace.settings.modal.menu.myAccount.label': 'A minha conta',
|
||||
'workspace.settings.modal.menu.preferences.label': 'Preferências',
|
||||
'workspace.settings.modal.menu.workspace.label': 'Espaço de trabalho',
|
||||
'workspace.settings.modal.menu.settings.label': 'Configurações',
|
||||
'workspace.settings.modal.menu.members.label': 'Membros',
|
||||
'workspace.settings.modal.menu.billingAndUsage.label': 'Faturação e uso',
|
||||
'workspace.settings.modal.menu.version.label': 'Versão: {version}',
|
||||
'workspace.dropdown.newButton.label': 'Novo espaço de trabalho',
|
||||
'workspace.dropdown.logoutButton.label': 'Sair',
|
||||
'templates.buttons.heading': 'Criar um novo typebot',
|
||||
'templates.buttons.fromScratchButton.label': 'Comece do zero',
|
||||
'templates.buttons.fromTemplateButton.label': 'Comece a partir de um modelo',
|
||||
'templates.buttons.importFileButton.label': 'Importar um ficheiro',
|
||||
'templates.modal.menuHeading.marketing': 'Marketing',
|
||||
'templates.modal.menuHeading.product': 'Produto',
|
||||
'templates.modal.menuHeading.other': 'Outros',
|
||||
'templates.modal.menuHeading.new.tag': 'Novo',
|
||||
'templates.modal.useTemplateButton.label': 'Usar este modelo',
|
||||
'templates.importFromFileButon.toastError.description':
|
||||
'Falha ao analisar o ficheiro. Tem certeza de que é um typebot?',
|
||||
'editor.headers.flowButton.label': 'Fluxo',
|
||||
'editor.headers.themeButton.label': 'Tema',
|
||||
'editor.headers.settingsButton.label': 'Configurações',
|
||||
'editor.headers.shareButton.label': 'Compartilhar',
|
||||
'editor.headers.resultsButton.label': 'Resultados',
|
||||
'editor.headers.helpButton.label': 'Ajuda',
|
||||
'editor.headers.savingSpinner.label': 'Salvando...',
|
||||
'editor.headers.previewButton.label': 'Visualizar',
|
||||
'editor.sidebarBlocks.sidebar.lock.label': 'Bloquear barra lateral',
|
||||
'editor.sidebarBlocks.sidebar.unlock.label': 'Desbloquear barra lateral',
|
||||
'editor.sidebarBlocks.sidebar.icon.lock.label': 'Bloquear',
|
||||
'editor.sidebarBlocks.sidebar.icon.unlock.label': 'Desbloquear',
|
||||
'editor.sidebarBlocks.blockType.bubbles.heading': 'Bubbles',
|
||||
'editor.sidebarBlocks.blockType.inputs.heading': 'Inputs',
|
||||
'editor.sidebarBlocks.blockType.logic.heading': 'Condicionais',
|
||||
'editor.sidebarBlocks.blockType.integrations.heading': 'Integrações',
|
||||
'editor.sidebarBlock.start.label': 'Início',
|
||||
'editor.sidebarBlock.text.label': 'Texto',
|
||||
'editor.sidebarBlock.image.label': 'Imagem',
|
||||
'editor.sidebarBlock.video.label': 'Vídeo',
|
||||
'editor.sidebarBlock.embed.label': 'Incorporar',
|
||||
'editor.sidebarBlock.audio.label': 'Áudio',
|
||||
'editor.sidebarBlock.number.label': 'Número',
|
||||
'editor.sidebarBlock.email.label': 'Email',
|
||||
'editor.sidebarBlock.website.label': 'Website',
|
||||
'editor.sidebarBlock.date.label': 'Data',
|
||||
'editor.sidebarBlock.phone.label': 'Telefone',
|
||||
'editor.sidebarBlock.button.label': 'Botão',
|
||||
'editor.sidebarBlock.picChoice.label': 'Seleção de Imagem',
|
||||
'editor.sidebarBlock.payment.label': 'Pagamento',
|
||||
'editor.sidebarBlock.rating.label': 'Classificação',
|
||||
'editor.sidebarBlock.file.label': 'Ficheiro',
|
||||
'editor.sidebarBlock.setVariable.label': 'Variável',
|
||||
'editor.sidebarBlock.condition.label': 'Condição',
|
||||
'editor.sidebarBlock.redirect.label': 'Redirecionar',
|
||||
'editor.sidebarBlock.script.label': 'Script',
|
||||
'editor.sidebarBlock.typebot.label': 'Typebot',
|
||||
'editor.sidebarBlock.wait.label': 'Espera',
|
||||
'editor.sidebarBlock.jump.label': 'Saltar',
|
||||
'editor.sidebarBlock.abTest.label': 'Teste AB',
|
||||
'editor.sidebarBlock.sheets.label': 'Sheets',
|
||||
'editor.sidebarBlock.analytics.label': 'Analytics',
|
||||
'editor.sidebarBlock.webhook.label': 'Webhook',
|
||||
'editor.sidebarBlock.zapier.label': 'Zapier',
|
||||
'editor.sidebarBlock.makecom.label': 'Make.com',
|
||||
'editor.sidebarBlock.pabbly.label': 'Pabbly',
|
||||
'editor.sidebarBlock.chatwoot.label': 'Chatwoot',
|
||||
'editor.sidebarBlock.openai.label': 'OpenAI',
|
||||
'editor.sidebarBlock.pixel.label': 'Pixel',
|
||||
'editor.sidebarBlock.zemanticAi.label': 'Zemantic AI',
|
||||
'editor.blockCard.bubbleBlock.tooltip.label':
|
||||
'Incorporar pdf, iframe, website...',
|
||||
'editor.blockCard.inputBlock.tooltip.files.label': 'Carregar Ficheiros',
|
||||
'editor.blockCard.logicBlock.tooltip.code.label':
|
||||
'Executar código Javascript',
|
||||
'editor.blockCard.logicBlock.tooltip.typebotLink.label':
|
||||
'Link e salte para outro typebot',
|
||||
'editor.blockCard.logicBlock.tooltip.jump.label':
|
||||
'Encaminhar fluxo para outro grupo',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleSheets.label':
|
||||
'Google Sheets',
|
||||
'editor.blockCard.integrationBlock.tooltip.googleAnalytics.label':
|
||||
'Google Analytics',
|
||||
'editor.editableTypebotName.tooltip.rename.label': 'Renomear',
|
||||
'editor.gettingStartedModal.editorBasics.heading': 'Noções básicas de editor',
|
||||
'editor.gettingStartedModal.editorBasics.list.one.label':
|
||||
'A barra lateral esquerda contém blocos que pode arrastar e largar no quadro.',
|
||||
'editor.gettingStartedModal.editorBasics.list.two.label':
|
||||
'Pode agrupar blocos juntos, colocando-os uns abaixo ou acima dos outros',
|
||||
'editor.gettingStartedModal.editorBasics.list.three.label':
|
||||
'Ligue os grupos entre si',
|
||||
'editor.gettingStartedModal.editorBasics.list.four.label':
|
||||
'Pré-visualize o seu bot ao clicar no botão de visualizar no canto superior direito',
|
||||
'editor.gettingStartedModal.editorBasics.list.label':
|
||||
'Sinta-se à vontade para usar o chat no canto inferior direito para entrar em contacto se tiver alguma questão. Normalmente, respondo nas próximas 24 horas. 😃',
|
||||
'editor.gettingStartedModal.seeAction.label': 'Veja o funcionamento em',
|
||||
'editor.gettingStartedModal.seeAction.time': '5 minutos',
|
||||
'editor.gettingStartedModal.seeAction.item.label': 'Outros vídeos',
|
||||
'editor.provider.messages.getTypebotError.title':
|
||||
'Erro ao obter o typebot. Atualize a página.',
|
||||
'editor.provider.messages.getTypebotError.description':
|
||||
'Não foi possível encontrar o typebot',
|
||||
'editor.provider.messages.publishedTypebotError.title':
|
||||
'Erro ao obter o typebot publicado',
|
||||
'editor.provider.messages.updateTypebotError.title':
|
||||
'Erro ao atualizar o typebot',
|
||||
'editor.provider.groups.copy.title': 'Cópia',
|
||||
'editor.blocks.start.text': 'Começar',
|
||||
'editor.blocks.bubbles.audio.settings.upload.label': 'Carregar',
|
||||
'editor.blocks.bubbles.audio.settings.embedLink.label': 'Incorporar link',
|
||||
'editor.blocks.bubbles.audio.settings.chooseFile.label':
|
||||
'Escolher um ficheiro',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.text':
|
||||
'Compatível com .MP3s e .WAVs',
|
||||
'editor.blocks.bubbles.audio.settings.worksWith.placeholder':
|
||||
'Colar o link do ficheiro de áudio...',
|
||||
'editor.blocks.bubbles.audio.settings.autoplay.label':
|
||||
'Ativar reprodução automática',
|
||||
'editor.blocks.bubbles.audio.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.embed.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.embed.node.show.text': 'Mostrar incorporação',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.placeholder':
|
||||
'Colar o link ou código...',
|
||||
'editor.blocks.bubbles.embed.settings.worksWith.text':
|
||||
'Compatível com PDFs, iframes, websites...',
|
||||
'editor.blocks.bubbles.embed.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.image.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.label': 'Link ao clicar',
|
||||
'editor.blocks.bubbles.image.switchWithLabel.onClick.placeholder':
|
||||
'Texto alternativo do link (descrição)',
|
||||
'editor.blocks.bubbles.video.node.clickToEdit.text': 'Clique para editar...',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.text':
|
||||
'Compatível com Youtube, Vimeo e outros',
|
||||
'editor.blocks.bubbles.video.settings.worksWith.placeholder':
|
||||
'Colar o link do vídeo...',
|
||||
'editor.blocks.bubbles.video.settings.numberInput.unit': 'px',
|
||||
'editor.blocks.bubbles.textEditor.plate.label': 'Editor de texto',
|
||||
'editor.blocks.bubbles.textEditor.searchVariable.placeholder':
|
||||
'Pesquisar uma variável',
|
||||
} as const
|
@ -15,20 +15,21 @@ import { toTitleCase } from '@typebot.io/lib'
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { NewVersionPopup } from '@/components/NewVersionPopup'
|
||||
import { I18nProvider } from '@/locales'
|
||||
import en from '@/locales/en'
|
||||
import { TypebotProvider } from '@/features/editor/providers/TypebotProvider'
|
||||
import { WorkspaceProvider } from '@/features/workspace/WorkspaceProvider'
|
||||
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
|
||||
|
||||
import { initPostHogIfEnabled } from '@/features/telemetry/posthog'
|
||||
import { TolgeeProvider, useTolgeeSSR } from '@tolgee/react'
|
||||
import { tolgee } from '@/lib/tolgee'
|
||||
|
||||
initPostHogIfEnabled()
|
||||
|
||||
const { ToastContainer, toast } = createStandaloneToast(customTheme)
|
||||
|
||||
const App = ({ Component, pageProps }: AppProps) => {
|
||||
useRouterProgressBar()
|
||||
const { query, pathname } = useRouter()
|
||||
const { query, pathname, locale } = useRouter()
|
||||
const ssrTolgee = useTolgeeSSR(tolgee, locale)
|
||||
|
||||
useEffect(() => {
|
||||
if (pathname.endsWith('/edit') || pathname.endsWith('/analytics')) {
|
||||
@ -56,7 +57,7 @@ const App = ({ Component, pageProps }: AppProps) => {
|
||||
return (
|
||||
<>
|
||||
<ToastContainer />
|
||||
<I18nProvider locale={pageProps.locale} fallbackLocale={en}>
|
||||
<TolgeeProvider tolgee={ssrTolgee}>
|
||||
<ChakraProvider theme={customTheme}>
|
||||
<SessionProvider session={pageProps.session}>
|
||||
<UserProvider>
|
||||
@ -72,7 +73,7 @@ const App = ({ Component, pageProps }: AppProps) => {
|
||||
</UserProvider>
|
||||
</SessionProvider>
|
||||
</ChakraProvider>
|
||||
</I18nProvider>
|
||||
</TolgeeProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { getLocaleProps } from '@/locales'
|
||||
import { GetServerSidePropsContext } from 'next'
|
||||
import { getServerSession } from 'next-auth'
|
||||
import { authOptions } from './api/auth/[...nextauth]'
|
||||
@ -7,32 +6,28 @@ export default function Page() {
|
||||
return null
|
||||
}
|
||||
|
||||
export const getServerSideProps = getLocaleProps(
|
||||
async (context: GetServerSidePropsContext) => {
|
||||
const session = await getServerSession(
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
)
|
||||
if (!session?.user) {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: false,
|
||||
destination:
|
||||
context.locale !== context.defaultLocale
|
||||
? `/${context.locale}/signin`
|
||||
: '/signin',
|
||||
},
|
||||
}
|
||||
}
|
||||
export const getServerSideProps = async (
|
||||
context: GetServerSidePropsContext
|
||||
) => {
|
||||
const session = await getServerSession(context.req, context.res, authOptions)
|
||||
if (!session?.user) {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: false,
|
||||
destination:
|
||||
context.locale !== context.defaultLocale
|
||||
? `/${context.locale}/typebots`
|
||||
: '/typebots',
|
||||
? `/${context.locale}/signin`
|
||||
: '/signin',
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
return {
|
||||
redirect: {
|
||||
permanent: false,
|
||||
destination:
|
||||
context.locale !== context.defaultLocale
|
||||
? `/${context.locale}/typebots`
|
||||
: '/typebots',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
import { DashboardPage } from '@/features/dashboard/components/DashboardPage'
|
||||
import { getLocaleProps } from '@/locales'
|
||||
import { GetServerSidePropsContext } from 'next'
|
||||
|
||||
export default function Page() {
|
||||
return <DashboardPage />
|
||||
}
|
||||
|
||||
export const getServerSideProps = getLocaleProps(
|
||||
async (context: GetServerSidePropsContext) => {
|
||||
const redirectPath = context.query.redirectPath?.toString()
|
||||
return redirectPath
|
||||
? {
|
||||
redirect: {
|
||||
permanent: false,
|
||||
destination: redirectPath,
|
||||
},
|
||||
}
|
||||
: { props: {} }
|
||||
}
|
||||
)
|
||||
export const getServerSideProps = async (
|
||||
context: GetServerSidePropsContext
|
||||
) => {
|
||||
const redirectPath = context.query.redirectPath?.toString()
|
||||
return redirectPath
|
||||
? {
|
||||
redirect: {
|
||||
permanent: false,
|
||||
destination: redirectPath,
|
||||
},
|
||||
}
|
||||
: { props: {} }
|
||||
}
|
||||
|
26
apps/builder/tolgee.d.ts
vendored
Normal file
26
apps/builder/tolgee.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
import type en from './src/locales/en.json'
|
||||
|
||||
declare module '@tolgee/core/lib/types' {
|
||||
type TranslationsType = typeof en
|
||||
|
||||
// ensures that nested keys are accessible with "."
|
||||
type DotNotationEntries<T> = T extends object
|
||||
? {
|
||||
[K in keyof T]: `${K & string}${T[K] extends undefined
|
||||
? ''
|
||||
: T[K] extends object
|
||||
? `.${DotNotationEntries<T[K]>}`
|
||||
: ''}`
|
||||
}[keyof T]
|
||||
: ''
|
||||
|
||||
// enables both intellisense and new keys without an error
|
||||
type LiteralUnion<LiteralType extends BaseType, BaseType extends Primitive> =
|
||||
| LiteralType
|
||||
| (BaseType & { _?: never })
|
||||
|
||||
export type TranslationKey = LiteralUnion<
|
||||
DotNotationEntries<TranslationsType>,
|
||||
string
|
||||
>
|
||||
}
|
@ -6,5 +6,5 @@
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
"include": ["next-env.d.ts", "tolgee.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
||||
|
Reference in New Issue
Block a user