🧑‍💻 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:
Baptiste Arnaud
2023-10-27 09:23:50 +02:00
committed by GitHub
parent 31b3fc311e
commit bed8b42a2e
101 changed files with 2141 additions and 2210 deletions

View File

@@ -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>
)

View File

@@ -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">

View File

@@ -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>
)}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>