🌐 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,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>