2
0

🌐 Translate workspace (#528)

This commit is contained in:
Baptiste Arnaud
2023-05-31 07:53:30 +02:00
committed by GitHub
parent 6651c85f02
commit b2ea8fc059
18 changed files with 3029 additions and 3494 deletions

View File

@ -13,7 +13,7 @@ const nextConfig = {
],
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'pt'],
locales: ['en', 'fr', 'pt', 'de'],
},
experimental: {
outputFileTracingRoot: path.join(__dirname, '../../'),

View File

@ -37,7 +37,6 @@
"@trpc/server": "10.27.3",
"@typebot.io/emails": "workspace:*",
"@typebot.io/js": "workspace:*",
"@typebot.io/next-international": "0.3.8",
"@typebot.io/react": "workspace:*",
"@udecode/plate-basic-marks": "21.1.5",
"@udecode/plate-common": "^21.1.5",
@ -71,6 +70,7 @@
"minio": "7.1.1",
"next": "13.4.3",
"next-auth": "4.22.1",
"next-international": "^0.4.1",
"nextjs-cors": "^2.1.2",
"nodemailer": "6.9.2",
"nprogress": "0.2.0",

View File

@ -1,15 +1,36 @@
import { Stack, Heading, useColorMode } from '@chakra-ui/react'
import {
Stack,
Heading,
useColorMode,
Menu,
MenuButton,
MenuList,
MenuItem,
Button,
HStack,
} from '@chakra-ui/react'
import { GraphNavigation } from '@typebot.io/prisma'
import React, { useEffect } from 'react'
import { GraphNavigationRadioGroup } from './GraphNavigationRadioGroup'
import { AppearanceRadioGroup } from './AppearanceRadioGroup'
import { useUser } from '../hooks/useUser'
import { useScopedI18n } from '@/locales'
import { useChangeLocale, useCurrentLocale, useScopedI18n } from '@/locales'
import { ChevronDownIcon } from '@/components/icons'
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
const localeHumanReadable = {
en: 'English',
fr: 'Français',
de: 'Deutsch',
pt: 'Português',
} as const
export const UserPreferencesForm = () => {
const scopedT = useScopedI18n('account.preferences')
const { colorMode, setColorMode } = useColorMode()
const { user, updateUser } = useUser()
const changeLocale = useChangeLocale()
const currentLocale = useCurrentLocale()
useEffect(() => {
if (!user?.graphNavigation)
@ -25,8 +46,40 @@ export const UserPreferencesForm = () => {
updateUser({ preferredAppAppearance: value })
}
const updateLocale = (locale: keyof typeof localeHumanReadable) => () => {
changeLocale(locale)
document.cookie = `NEXT_LOCALE=${locale}; path=/; max-age=31536000`
}
return (
<Stack spacing={12}>
<HStack spacing={4}>
<Heading size="md">{scopedT('language.heading')}</Heading>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
{localeHumanReadable[currentLocale]}
</MenuButton>
<MenuList>
{Object.keys(localeHumanReadable).map((locale) => (
<MenuItem
key={locale}
onClick={updateLocale(
locale as keyof typeof localeHumanReadable
)}
>
{
localeHumanReadable[
locale as keyof typeof localeHumanReadable
]
}
</MenuItem>
))}
</MenuList>
</Menu>
{currentLocale !== 'en' && (
<MoreInfoTooltip>{scopedT('language.tooltip')}</MoreInfoTooltip>
)}
</HStack>
<Stack spacing={6}>
<Heading size="md">{scopedT('graphNavigation.heading')}</Heading>
<GraphNavigationRadioGroup

View File

@ -13,6 +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'
type Props = {
workspaceId: string
@ -28,6 +29,7 @@ export const AddMemberForm = ({
isLoading,
isLocked,
}: Props) => {
const scopedT = useScopedI18n('workspace.membersList')
const [invitationEmail, setInvitationEmail] = useState('')
const [invitationRole, setInvitationRole] = useState<WorkspaceRole>(
WorkspaceRole.MEMBER
@ -52,7 +54,7 @@ export const AddMemberForm = ({
return (
<HStack as="form" onSubmit={handleInvitationSubmit}>
<Input
placeholder="colleague@company.com"
placeholder={scopedT('inviteInput.placeholder')}
name="inviteEmail"
value={invitationEmail}
onChange={(e) => setInvitationEmail(e.target.value)}
@ -73,7 +75,7 @@ export const AddMemberForm = ({
type="submit"
isDisabled={isLoading || isLocked || invitationEmail === ''}
>
Invite
{scopedT('inviteButton.label')}
</Button>
</HStack>
)

View File

@ -13,6 +13,7 @@ import {
import { WorkspaceRole } from '@typebot.io/prisma'
import React from 'react'
import { convertWorkspaceRoleToReadable } from './AddMemberForm'
import { useI18n } from '@/locales'
type Props = {
image?: string
@ -37,6 +38,7 @@ export const MemberItem = ({
onDeleteClick,
onSelectNewRole,
}: Props) => {
const t = useI18n()
const handleAdminClick = () => onSelectNewRole(WorkspaceRole.ADMIN)
const handleMemberClick = () => onSelectNewRole(WorkspaceRole.MEMBER)
@ -65,7 +67,7 @@ export const MemberItem = ({
{convertWorkspaceRoleToReadable(WorkspaceRole.MEMBER)}
</MenuItem>
<MenuItem color="red.500" onClick={onDeleteClick}>
Remove
{t('remove')}
</MenuItem>
</MenuList>
)}
@ -85,32 +87,36 @@ export const MemberIdentityContent = ({
image?: string
isGuest?: boolean
email: string
}) => (
<HStack justifyContent="space-between" maxW="full" p="2">
<HStack minW={0} spacing="4">
<Avatar name={name} src={image} size="sm" />
<Stack spacing={0} minW="0">
{name && (
<Text textAlign="left" fontSize="15px">
{name}
}) => {
const t = useI18n()
return (
<HStack justifyContent="space-between" maxW="full" p="2">
<HStack minW={0} spacing="4">
<Avatar name={name} src={image} size="sm" />
<Stack spacing={0} minW="0">
{name && (
<Text textAlign="left" fontSize="15px">
{name}
</Text>
)}
<Text
color="gray.500"
fontSize={name ? '14px' : 'inherit'}
noOfLines={1}
>
{email}
</Text>
</Stack>
</HStack>
<HStack flexShrink={0}>
{isGuest && (
<Tag color="gray.400" data-testid="tag">
{t('pending')}
</Tag>
)}
<Text
color="gray.500"
fontSize={name ? '14px' : 'inherit'}
noOfLines={1}
>
{email}
</Text>
</Stack>
<Tag data-testid="tag">{tag}</Tag>
</HStack>
</HStack>
<HStack flexShrink={0}>
{isGuest && (
<Tag color="gray.400" data-testid="tag">
Pending
</Tag>
)}
<Tag data-testid="tag">{tag}</Tag>
</HStack>
</HStack>
)
)
}

View File

@ -20,8 +20,10 @@ import { updateInvitationQuery } from '../queries/updateInvitationQuery'
import { updateMemberQuery } from '../queries/updateMemberQuery'
import { Member } from '../types'
import { useWorkspace } from '../WorkspaceProvider'
import { useScopedI18n } from '@/locales'
export const MembersList = () => {
const scopedT = useScopedI18n('workspace.membersList')
const { user } = useUser()
const { workspace, currentRole } = useWorkspace()
const { members, invitations, isLoading, mutate } = useMembers({
@ -102,16 +104,11 @@ export const MembersList = () => {
return (
<Stack w="full" spacing={3}>
{!canInviteNewMember && (
<UnlockPlanAlertInfo
contentLabel={`
Upgrade your plan to work with more team members, and unlock awesome
power features 🚀
`}
/>
<UnlockPlanAlertInfo contentLabel={scopedT('unlockBanner.label')} />
)}
{isDefined(seatsLimit) && (
<Heading fontSize="2xl">
Members{' '}
{scopedT('title')}{' '}
{seatsLimit === -1 ? '' : `(${currentMembersCount}/${seatsLimit})`}
</Heading>
)}

View File

@ -7,6 +7,7 @@ import {
} from '@/components/icons'
import { PlanTag } from '@/features/billing/components/PlanTag'
import { trpc } from '@/lib/trpc'
import { useScopedI18n } from '@/locales'
import {
Menu,
MenuButton,
@ -31,6 +32,7 @@ export const WorkspaceDropdown = ({
onLogoutClick,
onCreateNewWorkspaceClick,
}: Props) => {
const scopedT = useScopedI18n('workspace.dropdown')
const { data } = trpc.workspace.listWorkspaces.useQuery()
const workspaces = data?.workspaces ?? []
@ -70,14 +72,14 @@ export const WorkspaceDropdown = ({
</MenuItem>
))}
<MenuItem onClick={onCreateNewWorkspaceClick} icon={<PlusIcon />}>
New workspace
{scopedT('newButton.label')}
</MenuItem>
<MenuItem
onClick={onLogoutClick}
icon={<LogOutIcon />}
color="orange.500"
>
Log out
{scopedT('logoutButton.label')}
</MenuItem>
</MenuList>
</Menu>

View File

@ -12,8 +12,10 @@ import React from 'react'
import { EditableEmojiOrImageIcon } from '@/components/EditableEmojiOrImageIcon'
import { useWorkspace } from '../WorkspaceProvider'
import { TextInput } from '@/components/inputs'
import { useScopedI18n } from '@/locales'
export const WorkspaceSettingsForm = ({ onClose }: { onClose: () => void }) => {
const scopedT = useScopedI18n('workspace.settings')
const { workspace, workspaces, updateWorkspace, deleteCurrentWorkspace } =
useWorkspace()
@ -34,7 +36,7 @@ export const WorkspaceSettingsForm = ({ onClose }: { onClose: () => void }) => {
return (
<Stack spacing="6" w="full">
<FormControl>
<FormLabel>Icon</FormLabel>
<FormLabel>{scopedT('icon.title')}</FormLabel>
<Flex>
{workspace && (
<EditableEmojiOrImageIcon
@ -48,7 +50,7 @@ export const WorkspaceSettingsForm = ({ onClose }: { onClose: () => void }) => {
</FormControl>
{workspace && (
<TextInput
label="Name:"
label={scopedT('name.label')}
withVariableButton={false}
defaultValue={workspace?.name}
onChange={handleNameChange}
@ -71,11 +73,12 @@ const DeleteWorkspaceButton = ({
workspaceName: string
onConfirm: () => Promise<void>
}) => {
const scopedT = useScopedI18n('workspace.settings')
const { isOpen, onOpen, onClose } = useDisclosure()
return (
<>
<Button colorScheme="red" variant="outline" onClick={onOpen}>
Delete workspace
{scopedT('deleteButton.label')}
</Button>
<ConfirmModal
isOpen={isOpen}
@ -83,8 +86,9 @@ const DeleteWorkspaceButton = ({
onClose={onClose}
message={
<Text>
Are you sure you want to delete {workspaceName} workspace? All its
folders, typebots and results will be deleted forever.
{scopedT('deleteButton.confirmMessage', {
workspaceName,
})}
</Text>
}
confirmButtonLabel="Delete"

View File

@ -24,6 +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'
type Props = {
isOpen: boolean
@ -45,6 +46,7 @@ export const WorkspaceSettingsModal = ({
workspace,
onClose,
}: Props) => {
const scopedT = useScopedI18n('workspace.settings.modal')
const { currentRole } = useWorkspace()
const [selectedTab, setSelectedTab] = useState<SettingsTab>('my-account')
@ -56,7 +58,7 @@ export const WorkspaceSettingsModal = ({
<ModalContent minH="600px" flexDir="row">
<Stack
spacing={8}
w="200px"
w="180px"
py="6"
borderRightWidth={1}
justifyContent="space-between"
@ -80,7 +82,7 @@ export const WorkspaceSettingsModal = ({
justifyContent="flex-start"
pl="4"
>
My account
{scopedT('menu.myAccount.label')}
</Button>
<Button
variant={selectedTab === 'user-settings' ? 'solid' : 'ghost'}
@ -90,12 +92,12 @@ export const WorkspaceSettingsModal = ({
justifyContent="flex-start"
pl="4"
>
Preferences
{scopedT('menu.preferences.label')}
</Button>
</Stack>
<Stack>
<Text pl="4" color="gray.500">
Workspace
{scopedT('menu.workspace.label')}
</Text>
{canEditWorkspace && (
<Button
@ -114,7 +116,7 @@ export const WorkspaceSettingsModal = ({
justifyContent="flex-start"
pl="4"
>
Settings
{scopedT('menu.settings.label')}
</Button>
)}
<Button
@ -125,7 +127,7 @@ export const WorkspaceSettingsModal = ({
justifyContent="flex-start"
pl="4"
>
Members
{scopedT('menu.members.label')}
</Button>
{canEditWorkspace && (
<Button
@ -135,8 +137,10 @@ export const WorkspaceSettingsModal = ({
size="sm"
justifyContent="flex-start"
pl="4"
overflow="scroll"
className="hide-scrollbar"
>
Billing & Usage
{scopedT('menu.billingAndUsage.label')}
</Button>
)}
</Stack>
@ -144,7 +148,7 @@ export const WorkspaceSettingsModal = ({
<Flex justify="center" pt="10">
<Text color="gray.500" fontSize="xs">
Version: {packageJson.version}
{scopedT('menu.version.label', { version: packageJson.version })}
</Text>
</Flex>
</Stack>

View File

@ -1,6 +1,4 @@
import { defineLocale } from './index'
export default defineLocale({
export default {
back: 'Zurück',
'confirmModal.defaultTitle': 'Bist du sicher?',
'dashboard.header.settingsButton.label': 'Einstellungen & Mitglieder',
@ -12,55 +10,61 @@ export default defineLocale({
update: 'Aktualisieren',
upgrade: 'Upgrade',
downgrade: 'Downgrade',
remove: 'Entfernen',
pending: 'Ausstehend',
'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)',
'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': 'Unveröffentlichen',
'folders.typebotButton.duplicate': 'Duplizieren',
'folders.typebotButton.delete': 'Löschen',
'folders.typebotButton.deleteConfirmationMessage':
'Möchtest du deinen Typebot {typebotName} wirklich löschen?',
'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.',
'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!',
'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?',
'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.',
'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',
'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.',
'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.',
'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',
'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',
'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.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.',
'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',
@ -70,22 +74,25 @@ export default defineLocale({
'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.preLink':
'Bereits ein Konto vorhanden?',
'auth.register.alreadyHaveAccountLabel.link': 'Anmelden',
'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.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.',
'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.noProvider.preLink': 'Du musst',
'auth.noProvider.link':
'mindestens einen Authentifizierungsanbieter konfigurieren (E-Mail, Google, GitHub, Facebook oder Azure AD).',
'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.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',
@ -94,64 +101,86 @@ export default defineLocale({
'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.',
'Typebot trägt 1% deines Abonnements dazu bei, CO₂ aus der Atmosphäre zu entfernen.',
'billing.contribution.link': 'Erfahre mehr.',
'billing.updateSuccessToast.description':
'Arbeitsbereich {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 Arbeitsbereich-Abonnement:',
'billing.currentSubscription.cancelLink': 'Mein Abonnement kündigen',
'billing.invoices.heading': 'Rechnungen',
'billing.invoices.empty': 'Keine Rechnungen für diesen Arbeitsbereich 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 sammelst 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.customDomains': 'Eigene Domains',
'billing.pricingCard.pro.analytics': 'Detaillierte Analysen',
'billing.usage.heading': 'Nutzung',
'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': 'Speicher',
'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',
})
'Arbeitsbereich {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 Arbeitsbereich-Abonnement:',
'billing.currentSubscription.cancelLink': 'Mein Abonnement kündigen',
'billing.invoices.heading': 'Rechnungen',
'billing.invoices.empty':
'Keine Rechnungen für diesen Arbeitsbereich 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 sammelst 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.customDomains': 'Eigene Domains',
'billing.pricingCard.pro.analytics': 'Detaillierte Analysen',
'billing.usage.heading': 'Nutzung',
'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': 'Speicher',
'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': 'kollege@unternehmen.com',
'workspace.membersList.inviteButton.label': 'Einladen',
'workspace.membersList.unlockBanner.label':
'Aktualisieren Sie Ihren Plan, um mit mehr Teammitgliedern zu arbeiten und erstaunliche Leistungsmerkmale freizuschalten 🚀',
'workspace.membersList.title': 'Mitglieder',
'workspace.settings.icon.title': 'Symbol',
'workspace.settings.name.label': 'Name:',
'workspace.settings.deleteButton.label': 'Arbeitsbereich löschen',
'workspace.settings.deleteButton.confirmMessage':
'Sind Sie sicher, dass Sie den Arbeitsbereich {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': 'Arbeitsbereich',
'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 Arbeitsbereich',
'workspace.dropdown.logoutButton.label': 'Abmelden',
} as const

View File

@ -10,6 +10,8 @@ export default {
update: 'Update',
upgrade: 'Upgrade',
downgrade: 'Downgrade',
remove: 'Remove',
pending: 'Pending',
'folders.createFolderButton.label': 'Create a folder',
'folders.createTypebotButton.label': 'Create a typebot',
'folders.folderButton.deleteConfirmationMessage':
@ -44,6 +46,9 @@ export default {
'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':
@ -152,4 +157,23 @@ export default {
'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',
} as const

View File

@ -1,10 +1,8 @@
import { defineLocale } from './index'
export default defineLocale({
export default {
back: 'Retour',
'confirmModal.defaultTitle': 'Êtes-vous sûr ?',
'confirmModal.defaultTitle': 'Es-tu sûr ?',
'dashboard.header.settingsButton.label': 'Paramètres & Membres',
'dashboard.redirectionMessage': "Vous êtes en train d'être redirigé...",
'dashboard.redirectionMessage': 'Redirection en cours...',
'dashboard.title': 'Mes typebots',
delete: 'Supprimer',
errorMessage: "Une erreur s'est produite",
@ -12,47 +10,52 @@ export default defineLocale({
update: 'Mettre à jour',
upgrade: 'Upgrade',
downgrade: 'Downgrade',
remove: 'Retirer',
pending: 'En attente',
'folders.createFolderButton.label': 'Créer un dossier',
'folders.createTypebotButton.label': 'Créer un typebot',
'folders.folderButton.deleteConfirmationMessage':
"Êtes-vous 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)",
"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':
'Êtes-vous sûr de vouloir supprimer votre typebot {typebotName} ?',
'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 votre compte et vos typebots. Soyez prudent !",
"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é, êtes-vous sûr de vouloir continuer ?',
'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':
'Entrez un nom unique pour votre token afin de le différencier des autres tokens.',
'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':
'Veuillez copier votre token et le stocker dans un endroit sûr.',
'Copie ton token et enregistre le dans un endroit sûr.',
'account.apiTokens.createModal.securityWarning':
'Pour des raisons de sécurité, nous ne pouvons pas le montrer à nouveau.',
'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éplacez en glissant et zoom en avant/arrière en utilisant la molette',
'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éplacez le board en utilisant 2 doigts et zoomer en avant/arrière en pincant',
'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',
@ -60,35 +63,34 @@ export default defineLocale({
'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. Contactez le service d'assistance si vous souhaitez la modifier.",
"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.completionRateLabel': 'Taux de complétion',
'auth.signin.heading': 'Se connecter',
'auth.signin.noAccountLabel.preLink': "Vous n'avez pas de compte?",
'auth.signin.noAccountLabel.link': 'Inscrivez-vous gratuitement',
'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': 'Vous avez déjà un compte?',
'auth.register.alreadyHaveAccountLabel.preLink': 'Tu as déjà un compte?',
'auth.register.alreadyHaveAccountLabel.link': 'Se connecter',
'auth.error.default': 'Essayez de vous connecter avec un compte différent.',
'auth.error.default': 'Essaye de te connecter avec un compte différent.',
'auth.error.email':
'Email non trouvé. Essayez de vous connecter avec un fournisseur différent.',
'Email non trouvé. Essaye de te connecter avec un fournisseur différent.',
'auth.error.oauthNotLinked':
'Pour confirmer votre identité, connectez-vous avec le même compte que vous avez utilisé à lorigine.',
'auth.error.unknown': 'Une erreur est survenue. Veuillez réessayer.',
'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.noProvider.preLink': 'Vous avez besoin de',
'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':
'Assurez-vous de vérifier votre dossier de spam.',
'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',
@ -100,12 +102,12 @@ export default defineLocale({
"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':
'Votre abonnement {plan} a été mis à jour avec succès 🎉',
'Ton abonnement {plan} a été mis à jour avec succès 🎉',
'billing.customLimit.preLink':
'Vous avez besoin de limites personnalisées ? De fonctionnalités spécifiques ?',
'Tu as besoin de limites personnalisées ? De fonctionnalités spécifiques ?',
'billing.customLimit.link': 'Discutons-en!',
'billing.upgradeLimitLabel':
'Vous devez mettre à niveau votre abonnement pour {type}',
'Tu dois mettre à niveau ton abonnement pour {type}',
'billing.currentSubscription.heading': 'Abonnement',
'billing.currentSubscription.subheading': 'Abonnement actuel du workspace :',
'billing.currentSubscription.cancelLink': "Annuler l'abonnement",
@ -127,7 +129,7 @@ export default defineLocale({
"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':
"Vous accumulez du stockage pour chaque fichier que votre utilisateur télécharge dans votre bot. Si vous supprimez le résultat, cela libérera de l'espace.",
"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',
@ -145,19 +147,39 @@ export default defineLocale({
'billing.usage.heading': 'Utilisation',
'billing.usage.chats.heading': 'Chats',
'billing.usage.chats.alert.soonReach':
'Vos typebots sont populaires ! Vous atteindrez bientôt la limite de chats de votre abonnement. 🚀',
'Tes typebots sont populaires ! Tu atteindras bientôt la limite de chats de votre abonnement. 🚀',
'billing.usage.chats.alert.updatePlan':
'Assurez-vous de mettre à jour votre abonnement pour augmenter cette limite et continuer à discuter avec vos utilisateurs.',
'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':
'Vos typebots sont populaires ! Vous atteindrez bientôt la limite de stockage de votre abonnement. 🚀',
'Tes typebots sont populaires ! Tu atteindras bientôt la limite de stockage de ton abonnement. 🚀',
'billing.usage.storage.alert.updatePlan':
"Assurez-vous de mettre à jour votre abonnement pour continuer à collecter des fichiers téléchargés. Vous pouvez également supprimer des fichiers pour libérer de l'espace.",
"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',
} as const

View File

@ -1,13 +1,13 @@
import { createI18n } from '@typebot.io/next-international'
import type Locale from './en'
import { createI18n } from 'next-international'
export const {
defineLocale,
useI18n,
useScopedI18n,
I18nProvider,
getLocaleProps,
} = createI18n<typeof Locale>({
useCurrentLocale,
useChangeLocale,
} = createI18n({
en: () => import('./en'),
fr: () => import('./fr'),
pt: () => import('./pt'),

View File

@ -1,6 +1,4 @@
import { defineLocale } from './index'
export default defineLocale({
export default {
back: 'Voltar',
'confirmModal.defaultTitle': 'Tem certeza?',
'dashboard.header.settingsButton.label': 'Configurações & Membros',
@ -12,6 +10,8 @@ export default defineLocale({
update: 'Atualizar',
upgrade: 'Upgrade',
downgrade: 'Downgrade',
remove: 'Remover',
pending: 'Pendente',
'folders.createFolderButton.label': 'Criar uma pasta',
'folders.createTypebotButton.label': 'Criar um typebot',
'folders.folderButton.deleteConfirmationMessage':
@ -46,6 +46,9 @@ export default defineLocale({
'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':
@ -161,4 +164,23 @@ export default defineLocale({
'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',
} as const

View File

@ -19,6 +19,7 @@ import { I18nProvider } from '@/locales'
import { TypebotProvider } from '@/features/editor/providers/TypebotProvider'
import { WorkspaceProvider } from '@/features/workspace/WorkspaceProvider'
import { isCloudProdInstance } from '@/helpers/isCloudProdInstance'
import en from '@/locales/en'
const { ToastContainer, toast } = createStandaloneToast(customTheme)

View File

@ -2601,6 +2601,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -2928,6 +2931,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -3093,6 +3099,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -3182,6 +3191,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [

View File

@ -2214,6 +2214,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -2541,6 +2544,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -2706,6 +2712,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -2795,6 +2804,9 @@
},
"isCustomBody": {
"type": "boolean"
},
"isExecutedOnClient": {
"type": "boolean"
}
},
"required": [
@ -4322,92 +4334,171 @@
{
"anyOf": [
{
"type": "object",
"properties": {
"scriptToExecute": {
"anyOf": [
{
"type": "object",
"properties": {
"content": {
"type": "string"
},
"args": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"anyOf": [
{
"scriptToExecute": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"args": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"anyOf": [
{
"anyOf": [
{
"type": "string"
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
{
"type": "number"
"type": "boolean"
}
]
},
{
"type": "boolean"
"type": "array",
"items": {
"type": "string",
"nullable": true
}
}
]
},
{
"type": "array",
"items": {
"type": "string",
"nullable": true
}
],
"nullable": true
}
},
"required": [
"id"
],
"nullable": true
"additionalProperties": false
}
},
"required": [
"id"
],
"additionalProperties": false
}
}
},
"required": [
"content",
"args"
],
"additionalProperties": false
}
},
"required": [
"content",
"args"
"scriptToExecute"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"redirect": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"isNewTab": {
"type": "boolean"
}
},
"required": [
"isNewTab"
],
"additionalProperties": false
}
},
"required": [
"redirect"
],
"additionalProperties": false
}
},
"required": [
"scriptToExecute"
],
"additionalProperties": false
]
},
{
"type": "object",
"properties": {
"redirect": {
"chatwoot": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"isNewTab": {
"type": "boolean"
"scriptToExecute": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"args": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"anyOf": [
{
"anyOf": [
{
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
{
"type": "boolean"
}
]
},
{
"type": "array",
"items": {
"type": "string",
"nullable": true
}
}
],
"nullable": true
}
},
"required": [
"id"
],
"additionalProperties": false
}
}
},
"required": [
"content",
"args"
],
"additionalProperties": false
}
},
"required": [
"isNewTab"
"scriptToExecute"
],
"additionalProperties": false
}
},
"required": [
"redirect"
"chatwoot"
],
"additionalProperties": false
}
@ -4416,75 +4507,38 @@
{
"type": "object",
"properties": {
"chatwoot": {
"googleAnalytics": {
"type": "object",
"properties": {
"scriptToExecute": {
"type": "object",
"properties": {
"content": {
"type": "string"
"trackingId": {
"type": "string"
},
"category": {
"type": "string"
},
"action": {
"type": "string"
},
"label": {
"type": "string"
},
"value": {
"anyOf": [
{
"type": "number"
},
"args": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"anyOf": [
{
"anyOf": [
{
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
{
"type": "boolean"
}
]
},
{
"type": "array",
"items": {
"type": "string",
"nullable": true
}
}
],
"nullable": true
}
},
"required": [
"id"
],
"additionalProperties": false
}
}
},
"required": [
"content",
"args"
],
"additionalProperties": false
{}
]
},
"sendTo": {
"type": "string"
}
},
"required": [
"scriptToExecute"
],
"additionalProperties": false
}
},
"required": [
"chatwoot"
"googleAnalytics"
],
"additionalProperties": false
}
@ -4493,38 +4547,21 @@
{
"type": "object",
"properties": {
"googleAnalytics": {
"wait": {
"type": "object",
"properties": {
"trackingId": {
"type": "string"
},
"category": {
"type": "string"
},
"action": {
"type": "string"
},
"label": {
"type": "string"
},
"value": {
"anyOf": [
{
"type": "number"
},
{}
]
},
"sendTo": {
"type": "string"
"secondsToWaitFor": {
"type": "number"
}
},
"required": [
"secondsToWaitFor"
],
"additionalProperties": false
}
},
"required": [
"googleAnalytics"
"wait"
],
"additionalProperties": false
}
@ -4533,21 +4570,75 @@
{
"type": "object",
"properties": {
"wait": {
"setVariable": {
"type": "object",
"properties": {
"secondsToWaitFor": {
"type": "number"
"scriptToExecute": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"args": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"anyOf": [
{
"anyOf": [
{
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
{
"type": "boolean"
}
]
},
{
"type": "array",
"items": {
"type": "string",
"nullable": true
}
}
],
"nullable": true
}
},
"required": [
"id"
],
"additionalProperties": false
}
}
},
"required": [
"content",
"args"
],
"additionalProperties": false
}
},
"required": [
"secondsToWaitFor"
"scriptToExecute"
],
"additionalProperties": false
}
},
"required": [
"wait"
"setVariable"
],
"additionalProperties": false
}
@ -4556,75 +4647,38 @@
{
"type": "object",
"properties": {
"setVariable": {
"streamOpenAiChatCompletion": {
"type": "object",
"properties": {
"scriptToExecute": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"args": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"anyOf": [
{
"anyOf": [
{
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
},
{
"type": "boolean"
}
]
},
{
"type": "array",
"items": {
"type": "string",
"nullable": true
}
}
],
"nullable": true
}
},
"required": [
"id"
],
"additionalProperties": false
"messages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string",
"enum": [
"system",
"user",
"assistant"
]
}
}
},
"required": [
"content",
"args"
],
"additionalProperties": false
},
"additionalProperties": false
}
}
},
"required": [
"scriptToExecute"
"messages"
],
"additionalProperties": false
}
},
"required": [
"setVariable"
"streamOpenAiChatCompletion"
],
"additionalProperties": false
}
@ -4633,38 +4687,42 @@
{
"type": "object",
"properties": {
"streamOpenAiChatCompletion": {
"webhookToExecute": {
"type": "object",
"properties": {
"messages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string",
"enum": [
"system",
"user",
"assistant"
]
}
},
"additionalProperties": false
"url": {
"type": "string"
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"body": {},
"method": {
"type": "string",
"enum": [
"POST",
"GET",
"PUT",
"DELETE",
"PATCH",
"HEAD",
"CONNECT",
"OPTIONS",
"TRACE"
]
}
},
"required": [
"messages"
"url"
],
"additionalProperties": false
}
},
"required": [
"streamOpenAiChatCompletion"
"webhookToExecute"
],
"additionalProperties": false
}

5497
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff