diff --git a/api/src/i18n/services/translation.service.spec.ts b/api/src/i18n/services/translation.service.spec.ts index 12ad3de0..0db4de37 100644 --- a/api/src/i18n/services/translation.service.spec.ts +++ b/api/src/i18n/services/translation.service.spec.ts @@ -4,7 +4,6 @@ * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). - * 3. SaaS Restriction: This software, or any derivative of it, may not be used to offer a competing product or service (SaaS) without prior written consent from Hexastack. Offering the software as a service or using it in a commercial cloud environment without express permission is strictly prohibited. */ import { EventEmitter2 } from '@nestjs/event-emitter'; diff --git a/frontend/src/app-components/attachment/AttachmentDialog.tsx b/frontend/src/app-components/attachment/AttachmentDialog.tsx index 139b7629..0ddc30ec 100644 --- a/frontend/src/app-components/attachment/AttachmentDialog.tsx +++ b/frontend/src/app-components/attachment/AttachmentDialog.tsx @@ -9,11 +9,11 @@ import { Button, Dialog, DialogActions, DialogContent } from "@mui/material"; import { GridEventListener } from "@mui/x-data-grid"; import { FC, useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; import { MediaLibrary } from "@/components/media-library"; import { DialogControlProps } from "@/hooks/useDialog"; +import { useTranslate } from "@/hooks/useTranslate"; import { IAttachment } from "@/types/attachment.types"; export type AttachmentDialogProps = DialogControlProps< @@ -28,7 +28,7 @@ export const AttachmentDialog: FC = ({ accept, ...rest }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const [selected, setSelected] = useState(null); const handleSelection: GridEventListener<"rowClick"> = (data) => { setSelected(data.row); diff --git a/frontend/src/app-components/attachment/AttachmentInput.tsx b/frontend/src/app-components/attachment/AttachmentInput.tsx index e718e1ee..82f3938b 100644 --- a/frontend/src/app-components/attachment/AttachmentInput.tsx +++ b/frontend/src/app-components/attachment/AttachmentInput.tsx @@ -8,7 +8,6 @@ import { Box, FormHelperText, FormLabel } from "@mui/material"; import { forwardRef } from "react"; -import { useTranslation } from "react-i18next"; import { useGet } from "@/hooks/crud/useGet"; import { useHasPermission } from "@/hooks/useHasPermission"; @@ -47,7 +46,6 @@ const AttachmentInput = forwardRef( ref, ) => { const hasPermission = useHasPermission(); - const { t } = useTranslation(); const handleChange = (attachment: IAttachment | null) => { onChange && onChange(attachment?.id || null, attachment?.type || null); }; @@ -84,9 +82,7 @@ const AttachmentInput = forwardRef( enableMediaLibrary={enableMediaLibrary} onChange={handleChange} /> - ) : ( - t("message.no_attachment") - )} + ) : null} {helperText ? ( {helperText} ) : null} diff --git a/frontend/src/app-components/attachment/AttachmentThumbnail.tsx b/frontend/src/app-components/attachment/AttachmentThumbnail.tsx index c211d080..6075b67c 100644 --- a/frontend/src/app-components/attachment/AttachmentThumbnail.tsx +++ b/frontend/src/app-components/attachment/AttachmentThumbnail.tsx @@ -20,7 +20,6 @@ import { Typography, } from "@mui/material"; import { FC } from "react"; -import { useTranslation } from "react-i18next"; import { useDelete } from "@/hooks/crud/useDelete"; import { useGet } from "@/hooks/crud/useGet"; @@ -28,6 +27,7 @@ import { useDialog } from "@/hooks/useDialog"; import useFormattedFileSize from "@/hooks/useFormattedFileSize"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; import { IAttachment } from "@/types/attachment.types"; import { PermissionAction } from "@/types/permission.types"; @@ -84,7 +84,7 @@ const AttachmentThumbnail: FC = ({ entity: EntityType.ATTACHMENT, }); const { toast } = useToast(); - const { t } = useTranslation(); + const { t } = useTranslate(); const deleteDialogCtl = useDialog(false); const { mutateAsync: deleteAttachment } = useDelete(EntityType.ATTACHMENT, { onError: () => { diff --git a/frontend/src/app-components/attachment/AttachmentUploader.tsx b/frontend/src/app-components/attachment/AttachmentUploader.tsx index 498474a1..915ff657 100644 --- a/frontend/src/app-components/attachment/AttachmentUploader.tsx +++ b/frontend/src/app-components/attachment/AttachmentUploader.tsx @@ -10,11 +10,11 @@ import CloudUploadIcon from "@mui/icons-material/CloudUpload"; import FolderCopyIcon from "@mui/icons-material/FolderCopy"; import { Box, Button, Divider, Grid, styled, Typography } from "@mui/material"; import { ChangeEvent, DragEvent, FC, useState } from "react"; -import { useTranslation } from "react-i18next"; import { useUpload } from "@/hooks/crud/useUpload"; import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; import { IAttachment } from "@/types/attachment.types"; @@ -76,7 +76,7 @@ const AttachmentUploader: FC = ({ const [attachment, setAttachment] = useState( undefined, ); - const { t } = useTranslation(); + const { t } = useTranslate(); const [isDragOver, setIsDragOver] = useState(false); const { toast } = useToast(); const { mutateAsync: uploadAttachment } = useUpload(EntityType.ATTACHMENT, { diff --git a/frontend/src/app-components/auth/Login.tsx b/frontend/src/app-components/auth/Login.tsx index 8c22aca6..1fbdba3e 100755 --- a/frontend/src/app-components/auth/Login.tsx +++ b/frontend/src/app-components/auth/Login.tsx @@ -14,11 +14,11 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import { useConfirmAccount, useLogin } from "@/hooks/entities/auth-hooks"; import { useAuth } from "@/hooks/useAuth"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { useValidationRules } from "@/hooks/useValidationRules"; import { ILoginAttributes } from "@/types/auth/login.types"; @@ -33,7 +33,7 @@ const DEFAULT_VALUES: ILoginAttributes = { }; export const Login = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const router = useRouter(); const { authenticate } = useAuth(); @@ -91,59 +91,57 @@ export const Login = () => { return ( -
- - - {t("title.login")} - - , - }} - helperText={ - errors.identifier ? errors.identifier.message : null - } - {...register("identifier", validationRules.email)} - /> + + + + {t("title.login")} + + , + }} + helperText={errors.identifier ? errors.identifier.message : null} + {...register("identifier", validationRules.email)} + /> - , - }} - helperText={errors.password ? errors.password.message : null} - {...register("password", validationRules.password)} - /> - - - - - - - - - + - - -
+ + + +
+ + + ); }; diff --git a/frontend/src/app-components/auth/Register.tsx b/frontend/src/app-components/auth/Register.tsx index e8eadb10..deedd7e8 100644 --- a/frontend/src/app-components/auth/Register.tsx +++ b/frontend/src/app-components/auth/Register.tsx @@ -22,10 +22,10 @@ import { import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import { useAcceptInvite } from "@/hooks/entities/auth-hooks"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { useValidationRules } from "@/hooks/useValidationRules"; import { IRegisterAttributes } from "@/types/auth/register.types"; import { JWT } from "@/utils/Jwt"; @@ -49,7 +49,7 @@ const DEFAULT_VALUES: IRegisterAttributes = { type TRegisterExtendedPayload = IRegisterAttributes & { password2: string }; export const Register = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const router = useRouter(); const { toast } = useToast(); const { mutateAsync: acceptInvite, isLoading } = useAcceptInvite({ diff --git a/frontend/src/app-components/auth/ResetPassword.tsx b/frontend/src/app-components/auth/ResetPassword.tsx index 2eb284be..f68a4466 100644 --- a/frontend/src/app-components/auth/ResetPassword.tsx +++ b/frontend/src/app-components/auth/ResetPassword.tsx @@ -11,10 +11,10 @@ import { Button, Grid, Paper, Typography } from "@mui/material"; import Link from "next/link"; import { useRouter } from "next/router"; import { useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import { useResetPassword } from "@/hooks/entities/reset-hooks"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { useValidationRules } from "@/hooks/useValidationRules"; import { ContentContainer } from "../dialogs"; @@ -22,7 +22,7 @@ import { Adornment } from "../inputs/Adornment"; import { PasswordInput } from "../inputs/PasswordInput"; export const ResetPassword = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const rules = useValidationRules(); const validationRules = { diff --git a/frontend/src/app-components/auth/resetPasswordRequest.tsx b/frontend/src/app-components/auth/resetPasswordRequest.tsx index 704b9b20..a5d13135 100644 --- a/frontend/src/app-components/auth/resetPasswordRequest.tsx +++ b/frontend/src/app-components/auth/resetPasswordRequest.tsx @@ -9,16 +9,16 @@ import { Button, Grid, Paper, Typography } from "@mui/material"; import Link from "next/link"; import { useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import { useRequestResetPassword } from "@/hooks/entities/reset-hooks"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { ContentContainer } from "../dialogs"; import { Input } from "../inputs/Input"; export const ResetPasswordRequest = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const { register, diff --git a/frontend/src/app-components/buttons/DialogButtons.tsx b/frontend/src/app-components/buttons/DialogButtons.tsx index 2ff94a61..36fbe909 100644 --- a/frontend/src/app-components/buttons/DialogButtons.tsx +++ b/frontend/src/app-components/buttons/DialogButtons.tsx @@ -9,7 +9,8 @@ import CheckIcon from "@mui/icons-material/Check"; import CloseIcon from "@mui/icons-material/Close"; import { Button } from "@mui/material"; -import { useTranslation } from "react-i18next"; + +import { useTranslate } from "@/hooks/useTranslate"; interface DialogButtonsProps { closeDialog?: () => void; @@ -20,7 +21,7 @@ const DialogButtons: React.FC = ({ closeDialog, handleSubmit, }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); return ( <> diff --git a/frontend/src/app-components/dialogs/DeleteDialog.tsx b/frontend/src/app-components/dialogs/DeleteDialog.tsx index 6fc9dcd1..f9114992 100644 --- a/frontend/src/app-components/dialogs/DeleteDialog.tsx +++ b/frontend/src/app-components/dialogs/DeleteDialog.tsx @@ -16,10 +16,10 @@ import { Button, } from "@mui/material"; import { FC } from "react"; -import { useTranslation } from "react-i18next"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; import { DialogControl } from "@/hooks/useDialog"; +import { useTranslate } from "@/hooks/useTranslate"; export type DeleteDialogProps = DialogControl; export const DeleteDialog: FC = ({ @@ -27,7 +27,7 @@ export const DeleteDialog: FC = ({ callback, closeDialog: closeFunction, }: DeleteDialogProps) => { - const { t } = useTranslation(); + const { t } = useTranslate(); return ( diff --git a/frontend/src/app-components/inputs/FilterTextfield.tsx b/frontend/src/app-components/inputs/FilterTextfield.tsx index ef77e43d..cd58df06 100644 --- a/frontend/src/app-components/inputs/FilterTextfield.tsx +++ b/frontend/src/app-components/inputs/FilterTextfield.tsx @@ -8,13 +8,14 @@ import SearchIcon from "@mui/icons-material/Search"; import { TextFieldProps } from "@mui/material"; -import { useTranslation } from "react-i18next"; + +import { useTranslate } from "@/hooks/useTranslate"; import { Adornment } from "./Adornment"; import { Input } from "./Input"; export const FilterTextfield = (props: TextFieldProps) => { - const { t } = useTranslation(); + const { t } = useTranslate(); //TODO: replace the native delete text button by a styled custom button return ( diff --git a/frontend/src/app-components/inputs/MultipleInput.tsx b/frontend/src/app-components/inputs/MultipleInput.tsx index 62751e72..17c73a38 100644 --- a/frontend/src/app-components/inputs/MultipleInput.tsx +++ b/frontend/src/app-components/inputs/MultipleInput.tsx @@ -24,7 +24,8 @@ import { useEffect, useState, } from "react"; -import { useTranslation } from "react-i18next"; + +import { useTranslate } from "@/hooks/useTranslate"; import { Input } from "./Input"; @@ -54,7 +55,7 @@ const MultipleInput = forwardRef( }, ref, ) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const [inputs, setInputs] = useState>( value ? value.length >= minInput diff --git a/frontend/src/app-components/menus/Sidebar.tsx b/frontend/src/app-components/menus/Sidebar.tsx index 59c77730..ca621817 100644 --- a/frontend/src/app-components/menus/Sidebar.tsx +++ b/frontend/src/app-components/menus/Sidebar.tsx @@ -26,8 +26,9 @@ import { import { OverridableComponent } from "@mui/material/OverridableComponent"; import Link from "next/link"; import { useState, useEffect } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslate } from "@/hooks/useTranslate"; +import { TTranslationKeys } from "@/i18n/i18n.types"; import { theme } from "@/layout/themes/theme"; import { SXStyleOptions } from "@/utils/SXStyleOptions"; @@ -160,7 +161,7 @@ const VerticalMenuItem = ({ isNested?: boolean; isToggled?: boolean; }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const linkProps = { href, onClick, @@ -173,7 +174,11 @@ const VerticalMenuItem = ({ : theme.palette.text.secondary; return ( - + @@ -221,7 +226,7 @@ export const Sidebar = ({ isToggled, toggleFunction, }: TSidebarProps) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const [openItems, setOpenItems] = useState([]); const toggleCollapse = (menuItem: string) => () => { if (isToggled || !openItems.includes(menuItem)) @@ -301,7 +306,9 @@ export const Sidebar = ({ return ( {isToggled && text ? ( - {t(text)} + + {String(t(text as TTranslationKeys))} + ) : null} ); diff --git a/frontend/src/app-components/tables/NoDataOverlay.tsx b/frontend/src/app-components/tables/NoDataOverlay.tsx index 5d0b7b0f..78b15dbc 100644 --- a/frontend/src/app-components/tables/NoDataOverlay.tsx +++ b/frontend/src/app-components/tables/NoDataOverlay.tsx @@ -7,12 +7,13 @@ */ import { Grid, Typography } from "@mui/material"; -import { useTranslation } from "react-i18next"; + +import { useTranslate } from "@/hooks/useTranslate"; import NoDataIcon from "../svg/NoDataIcon"; export const NoDataOverlay = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); return ( = { + [ActionColumnLabel.Edit]: "button.edit", + [ActionColumnLabel.Delete]: "button.delete", + [ActionColumnLabel.Values]: "button.values", + [ActionColumnLabel.Manage_Roles]: "button.manage_roles", + [ActionColumnLabel.Permissions]: "button.permissions", + [ActionColumnLabel.Content]: "button.content", + [ActionColumnLabel.Fields]: "button.fields", + [ActionColumnLabel.Manage_Labels]: "title.manage_labels", + [ActionColumnLabel.Toggle]: "button.toggle", +} as const; + export interface ActionColumn { label: ActionColumnLabel; action?: (row: T) => void; @@ -99,7 +112,7 @@ function StackComponent({ actions: ActionColumn[]; params: GridRenderCellParams; }) { - const { t } = useTranslation(); + const { t } = useTranslate(); return ( @@ -116,9 +129,13 @@ function StackComponent({ key={label} className="actionButton" icon={ - {getIcon(label)} + + {getIcon(label)} + } - label={helperText || t(label)} + label={helperText || t(ACTION_COLUMN_LABEL_MAP[label])} showInMenu={false} sx={{ color: diff --git a/frontend/src/components/Menu/MenuAccordion.tsx b/frontend/src/components/Menu/MenuAccordion.tsx index 962e380b..46d3b6ac 100644 --- a/frontend/src/components/Menu/MenuAccordion.tsx +++ b/frontend/src/components/Menu/MenuAccordion.tsx @@ -25,13 +25,13 @@ import { styled, } from "@mui/material"; import React, { FC, useState } from "react"; -import { useTranslation } from "react-i18next"; import { AnimatedChevron } from "@/app-components/icons/AnimatedChevron"; import { UnifiedIcon } from "@/app-components/icons/UnifiedIcon"; import { TMenuItem } from "@/app-components/menus/Sidebar"; import { useGetFromCache } from "@/hooks/crud/useGet"; import { useHasPermission } from "@/hooks/useHasPermission"; +import { useTranslate } from "@/hooks/useTranslate"; import { theme } from "@/layout/themes/theme"; import { EntityType } from "@/services/types"; import { IMenuNode } from "@/types/menu-tree.types"; @@ -103,7 +103,7 @@ const MenuItem: FC = ({ onUpdate, onDelete, }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const hasPermission = useHasPermission(); return ( diff --git a/frontend/src/components/Menu/MenuDialog.tsx b/frontend/src/components/Menu/MenuDialog.tsx index 0483c0a1..1a417d68 100644 --- a/frontend/src/components/Menu/MenuDialog.tsx +++ b/frontend/src/components/Menu/MenuDialog.tsx @@ -15,7 +15,6 @@ import { } from "@mui/material"; import { useEffect, FC } from "react"; import { useForm, Controller } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import DialogButtons from "@/app-components/buttons/DialogButtons"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; @@ -23,6 +22,8 @@ import { ContentContainer } from "@/app-components/dialogs/layouts/ContentContai import { ContentItem } from "@/app-components/dialogs/layouts/ContentItem"; import { Input } from "@/app-components/inputs/Input"; import { ToggleableInput } from "@/app-components/inputs/ToggleableInput"; +import { useTranslate } from "@/hooks/useTranslate"; +import { TNestedTranslation } from "@/i18n/i18n.types"; import { IMenuItem, IMenuItemAttributes, MenuType } from "@/types/menu.types"; import { isAbsoluteUrl } from "@/utils/URL"; @@ -45,7 +46,7 @@ export const MenuDialog: FC = ({ parentId, ...rest }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { reset, resetField, @@ -123,9 +124,11 @@ export const MenuDialog: FC = ({ helperText={errors.type ? errors.type.message : null} {...rest} > - {Object.keys(MenuType).map((value, key) => ( + {( + Object.keys(MenuType) as TNestedTranslation<"label">[] + ).map((value, key) => ( - {t(`label.${value}`)} + {t("label", value)} ))} diff --git a/frontend/src/components/Menu/index.tsx b/frontend/src/components/Menu/index.tsx index ead52812..bab6d447 100644 --- a/frontend/src/components/Menu/index.tsx +++ b/frontend/src/components/Menu/index.tsx @@ -10,7 +10,6 @@ import { faBars } from "@fortawesome/free-solid-svg-icons"; import AddIcon from "@mui/icons-material/Add"; import { Grid, Paper, Button, Box, debounce } from "@mui/material"; import React, { useRef, useState } from "react"; -import { useTranslation } from "react-i18next"; import { DeleteDialog } from "@/app-components/dialogs/DeleteDialog"; import { NoDataOverlay } from "@/app-components/tables/NoDataOverlay"; @@ -19,6 +18,7 @@ import { useDelete } from "@/hooks/crud/useDelete"; import { useFind } from "@/hooks/crud/useFind"; import { useUpdate } from "@/hooks/crud/useUpdate"; import { useHasPermission } from "@/hooks/useHasPermission"; +import { useTranslate } from "@/hooks/useTranslate"; import { PageHeader } from "@/layout/content/PageHeader"; import { EntityType } from "@/services/types"; import { IMenuItem } from "@/types/menu.types"; @@ -28,7 +28,7 @@ import MenuAccordion from "./MenuAccordion"; import { MenuDialog } from "./MenuDialog"; export const Menu = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const [addDialogOpened, setAddDialogOpened] = useState(false); const [editDialogOpened, setEditDialogOpened] = useState(false); const [selectedMenuId, setSelectedMenuId] = useState( diff --git a/frontend/src/components/categories/CategoryDialog.tsx b/frontend/src/components/categories/CategoryDialog.tsx index af27e349..f6baa5e9 100644 --- a/frontend/src/components/categories/CategoryDialog.tsx +++ b/frontend/src/components/categories/CategoryDialog.tsx @@ -9,7 +9,6 @@ import { Dialog, DialogActions, DialogContent } from "@mui/material"; import { FC, useEffect } from "react"; import { useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import DialogButtons from "@/app-components/buttons/DialogButtons"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; @@ -20,6 +19,7 @@ import { useCreate } from "@/hooks/crud/useCreate"; import { useUpdate } from "@/hooks/crud/useUpdate"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; import { ICategory, ICategoryAttributes } from "@/types/category.types"; @@ -31,7 +31,7 @@ export const CategoryDialog: FC = ({ closeDialog, ...rest }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const { mutateAsync: createCategory } = useCreate(EntityType.CATEGORY, { onError: () => { diff --git a/frontend/src/components/categories/index.tsx b/frontend/src/components/categories/index.tsx index b3c152f1..93b5d5af 100644 --- a/frontend/src/components/categories/index.tsx +++ b/frontend/src/components/categories/index.tsx @@ -10,7 +10,6 @@ import AddIcon from "@mui/icons-material/Add"; import FolderIcon from "@mui/icons-material/Folder"; import { Button, Grid, Paper } from "@mui/material"; import { GridColDef } from "@mui/x-data-grid"; -import { useTranslation } from "react-i18next"; import { DeleteDialog } from "@/app-components/dialogs/DeleteDialog"; import { FilterTextfield } from "@/app-components/inputs/FilterTextfield"; @@ -26,6 +25,7 @@ import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useSearch } from "@/hooks/useSearch"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { PageHeader } from "@/layout/content/PageHeader"; import { EntityType } from "@/services/types"; import { PermissionAction } from "@/types/permission.types"; @@ -35,7 +35,7 @@ import { CategoryDialog } from "./CategoryDialog"; import { ICategory } from "../../types/category.types"; export const Categories = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const addDialogCtl = useDialog(false); const editDialogCtl = useDialog(false); diff --git a/frontend/src/components/content-types/ContentTypeDialog.tsx b/frontend/src/components/content-types/ContentTypeDialog.tsx index a278662e..f1e5ec08 100644 --- a/frontend/src/components/content-types/ContentTypeDialog.tsx +++ b/frontend/src/components/content-types/ContentTypeDialog.tsx @@ -9,7 +9,6 @@ import { Dialog, DialogActions, DialogContent } from "@mui/material"; import { FC, useEffect } from "react"; import { useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import DialogButtons from "@/app-components/buttons/DialogButtons"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; @@ -20,6 +19,7 @@ import { useCreate } from "@/hooks/crud/useCreate"; import { useUpdate } from "@/hooks/crud/useUpdate"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; import { IContentType, @@ -33,7 +33,7 @@ export const ContentTypeDialog: FC = ({ closeDialog, }) => { const { toast } = useToast(); - const { t } = useTranslation(); + const { t } = useTranslate(); const { handleSubmit, register, diff --git a/frontend/src/components/content-types/EditContentTypeFieldsDialog.tsx b/frontend/src/components/content-types/EditContentTypeFieldsDialog.tsx index af9186aa..95ba915f 100644 --- a/frontend/src/components/content-types/EditContentTypeFieldsDialog.tsx +++ b/frontend/src/components/content-types/EditContentTypeFieldsDialog.tsx @@ -17,7 +17,6 @@ import { } from "@mui/material"; import { useEffect } from "react"; import { useFieldArray, useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import DialogButtons from "@/app-components/buttons/DialogButtons"; import { @@ -30,6 +29,7 @@ import { useGet } from "@/hooks/crud/useGet"; import { useUpdate } from "@/hooks/crud/useUpdate"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; import { ContentFieldType, IContentType } from "@/types/content-type.types"; @@ -43,7 +43,7 @@ export const EditContentTypeFieldsDialog = ({ closeDialog, open, }: EditContentTypeDialogFieldsProps) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { isLoading, data, refetch } = useGet(contentType?.id || "", { entity: EntityType.CONTENT_TYPE, }); diff --git a/frontend/src/components/content-types/components/FieldInput.tsx b/frontend/src/components/content-types/components/FieldInput.tsx index c8c1c1c3..5d5d5b3c 100644 --- a/frontend/src/components/content-types/components/FieldInput.tsx +++ b/frontend/src/components/content-types/components/FieldInput.tsx @@ -16,10 +16,10 @@ import { UseFormSetValue, useWatch, } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import { IconButton } from "@/app-components/buttons/IconButton"; import { Input } from "@/app-components/inputs/Input"; +import { useTranslate } from "@/hooks/useTranslate"; import { ContentFieldType, IContentType } from "@/types/content-type.types"; import { slugify } from "@/utils/string"; @@ -34,7 +34,7 @@ export const FieldInput = ({ control: Control>; setValue: UseFormSetValue>; }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const label = useWatch({ control: props.control, name: `fields.${index}.label`, diff --git a/frontend/src/components/content-types/index.tsx b/frontend/src/components/content-types/index.tsx index 79f0a9e7..23e8e9fb 100644 --- a/frontend/src/components/content-types/index.tsx +++ b/frontend/src/components/content-types/index.tsx @@ -10,7 +10,6 @@ import { faAlignLeft } from "@fortawesome/free-solid-svg-icons"; import AddIcon from "@mui/icons-material/Add"; import { Button, Grid, Paper } from "@mui/material"; import { useRouter } from "next/router"; -import { useTranslation } from "react-i18next"; import { DeleteDialog } from "@/app-components/dialogs"; import { FilterTextfield } from "@/app-components/inputs/FilterTextfield"; @@ -26,6 +25,7 @@ import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useSearch } from "@/hooks/useSearch"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { PageHeader } from "@/layout/content/PageHeader"; import { EntityType } from "@/services/types"; import { IContentType } from "@/types/content-type.types"; @@ -36,7 +36,7 @@ import { ContentTypeDialog } from "./ContentTypeDialog"; import { EditContentTypeFieldsDialog } from "./EditContentTypeFieldsDialog"; export const ContentTypes = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const router = useRouter(); // Dialog Controls diff --git a/frontend/src/components/contents/ContentDialog.tsx b/frontend/src/components/contents/ContentDialog.tsx index 1c845762..4d1b27d1 100644 --- a/frontend/src/components/contents/ContentDialog.tsx +++ b/frontend/src/components/contents/ContentDialog.tsx @@ -23,7 +23,6 @@ import { FieldErrors, useForm, } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import AttachmentInput from "@/app-components/attachment/AttachmentInput"; import DialogButtons from "@/app-components/buttons/DialogButtons"; @@ -36,6 +35,8 @@ import { useCreate } from "@/hooks/crud/useCreate"; import { useUpdate } from "@/hooks/crud/useUpdate"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; +import { TNestedTranslation } from "@/i18n/i18n.types"; import { EntityType } from "@/services/types"; import { ContentField, @@ -60,7 +61,7 @@ const ContentFieldInput: React.FC = ({ field, errors, }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); switch (contentField.type) { case ContentFieldType.TEXT: @@ -70,7 +71,7 @@ const ContentFieldInput: React.FC = ({ , { defaultValue: contentField.label, })} InputProps={ @@ -92,7 +93,7 @@ const ContentFieldInput: React.FC = ({ case ContentFieldType.CHECKBOX: return ( , { defaultValue: contentField.label, })} {...field} @@ -102,7 +103,7 @@ const ContentFieldInput: React.FC = ({ case ContentFieldType.FILE: return ( , { defaultValue: contentField.label, })} {...field} @@ -133,7 +134,7 @@ export const ContentDialog: FC = ({ content: undefined, contentType: undefined, }; - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const { reset, diff --git a/frontend/src/components/contents/index.tsx b/frontend/src/components/contents/index.tsx index 0634b5a1..c2c104bc 100644 --- a/frontend/src/components/contents/index.tsx +++ b/frontend/src/components/contents/index.tsx @@ -12,7 +12,6 @@ import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { Button, Chip, Grid, Paper, Switch, Typography } from "@mui/material"; import Link from "next/link"; import { useRouter } from "next/router"; -import { useTranslation } from "react-i18next"; import { DeleteDialog } from "@/app-components/dialogs"; import { FilterTextfield } from "@/app-components/inputs/FilterTextfield"; @@ -30,6 +29,7 @@ import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useSearch } from "@/hooks/useSearch"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { PageHeader } from "@/layout/content/PageHeader"; import { EntityType, Format } from "@/services/types"; import { IContentType } from "@/types/content-type.types"; @@ -40,7 +40,7 @@ import { getDateTimeFormatter } from "@/utils/date"; import { ContentDialog } from "./ContentDialog"; export const Contents = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const { query } = useRouter(); // Dialog Controls diff --git a/frontend/src/components/context-vars/ContextVarDialog.tsx b/frontend/src/components/context-vars/ContextVarDialog.tsx index e19c8903..05f5e0f3 100644 --- a/frontend/src/components/context-vars/ContextVarDialog.tsx +++ b/frontend/src/components/context-vars/ContextVarDialog.tsx @@ -16,7 +16,6 @@ import { } from "@mui/material"; import { FC, useEffect } from "react"; import { Controller, useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import DialogButtons from "@/app-components/buttons/DialogButtons"; import { DialogTitle } from "@/app-components/dialogs/DialogTitle"; @@ -27,6 +26,7 @@ import { useCreate } from "@/hooks/crud/useCreate"; import { useUpdate } from "@/hooks/crud/useUpdate"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; import { IContextVar, IContextVarAttributes } from "@/types/context-var.types"; import { slugify } from "@/utils/string"; @@ -38,7 +38,7 @@ export const ContextVarDialog: FC = ({ closeDialog, ...rest }) => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const { mutateAsync: createContextVar } = useCreate(EntityType.CONTEXT_VAR, { onError: () => { diff --git a/frontend/src/components/context-vars/index.tsx b/frontend/src/components/context-vars/index.tsx index 8037c466..3cb5e1c5 100644 --- a/frontend/src/components/context-vars/index.tsx +++ b/frontend/src/components/context-vars/index.tsx @@ -11,7 +11,6 @@ import AddIcon from "@mui/icons-material/Add"; import { Button, Grid, Paper, Switch } from "@mui/material"; import { GridColDef } from "@mui/x-data-grid"; import React from "react"; -import { useTranslation } from "react-i18next"; import { DeleteDialog } from "@/app-components/dialogs/DeleteDialog"; import { FilterTextfield } from "@/app-components/inputs/FilterTextfield"; @@ -28,6 +27,7 @@ import { getDisplayDialogs, useDialog } from "@/hooks/useDialog"; import { useHasPermission } from "@/hooks/useHasPermission"; import { useSearch } from "@/hooks/useSearch"; import { useToast } from "@/hooks/useToast"; +import { useTranslate } from "@/hooks/useTranslate"; import { PageHeader } from "@/layout/content/PageHeader"; import { EntityType } from "@/services/types"; import { IContextVar } from "@/types/context-var.types"; @@ -37,7 +37,7 @@ import { getDateTimeFormatter } from "@/utils/date"; import { ContextVarDialog } from "./ContextVarDialog"; export const ContextVars = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { toast } = useToast(); const addDialogCtl = useDialog(false); const editDialogCtl = useDialog(false); diff --git a/frontend/src/components/dashboard/AudienceChart.tsx b/frontend/src/components/dashboard/AudienceChart.tsx index 67042ed2..589f2c41 100644 --- a/frontend/src/components/dashboard/AudienceChart.tsx +++ b/frontend/src/components/dashboard/AudienceChart.tsx @@ -8,17 +8,17 @@ import { Card, CardContent, Divider } from "@mui/material"; import { MultiLineChart, ResponsiveChartContainer } from "eazychart-react"; -import { useTranslation } from "react-i18next"; import { StyledCardHeader } from "@/app-components/card/StyledCardHeader"; import { useFindStats } from "@/hooks/entities/bot-stat-hooks"; +import { useTranslate } from "@/hooks/useTranslate"; import { LineChartStats } from "@/types/bot-stat.types"; import { buildMultiLineChartConfig, transformToLine } from "@/utils/chart"; import { NoDataChart } from "./NoDataChart"; const AudienceChart = () => { - const { t, i18n } = useTranslation(); + const { t, i18n } = useTranslate(); const { data: stats } = useFindStats("audiance"); const { data, domainKeys } = transformToLine(stats); diff --git a/frontend/src/components/dashboard/ConversationChart.tsx b/frontend/src/components/dashboard/ConversationChart.tsx index 8a7940b4..5c6b7bf9 100644 --- a/frontend/src/components/dashboard/ConversationChart.tsx +++ b/frontend/src/components/dashboard/ConversationChart.tsx @@ -8,17 +8,17 @@ import { Card, CardContent, Divider } from "@mui/material"; import { MultiLineChart, ResponsiveChartContainer } from "eazychart-react"; -import { useTranslation } from "react-i18next"; import { StyledCardHeader } from "@/app-components/card/StyledCardHeader"; import { useFindStats } from "@/hooks/entities/bot-stat-hooks"; +import { useTranslate } from "@/hooks/useTranslate"; import { LineChartStats } from "@/types/bot-stat.types"; import { buildMultiLineChartConfig, transformToLine } from "@/utils/chart"; import { NoDataChart } from "./NoDataChart"; const ConversationChart = () => { - const { t, i18n } = useTranslation(); + const { t, i18n } = useTranslate(); const { data: conversations } = useFindStats("conversation"); const { data: conversationData, domainKeys: conversationDomains } = transformToLine(conversations); diff --git a/frontend/src/components/dashboard/MessageChart.tsx b/frontend/src/components/dashboard/MessageChart.tsx index fc70cde0..53a27944 100644 --- a/frontend/src/components/dashboard/MessageChart.tsx +++ b/frontend/src/components/dashboard/MessageChart.tsx @@ -8,17 +8,17 @@ import { Card, CardContent, Divider } from "@mui/material"; import { MultiLineChart, ResponsiveChartContainer } from "eazychart-react"; -import { useTranslation } from "react-i18next"; import { StyledCardHeader } from "@/app-components/card/StyledCardHeader"; import { useFindStats } from "@/hooks/entities/bot-stat-hooks"; +import { useTranslate } from "@/hooks/useTranslate"; import { LineChartStats } from "@/types/bot-stat.types"; import { buildMultiLineChartConfig, transformToLine } from "@/utils/chart"; import { NoDataChart } from "./NoDataChart"; const MessageChart = () => { - const { t, i18n } = useTranslation(); + const { t, i18n } = useTranslate(); const { data: stats } = useFindStats("messages"); const { data, domainKeys: domains } = transformToLine(stats); diff --git a/frontend/src/components/dashboard/NoDataChart.tsx b/frontend/src/components/dashboard/NoDataChart.tsx index 28dba0a3..e4728709 100644 --- a/frontend/src/components/dashboard/NoDataChart.tsx +++ b/frontend/src/components/dashboard/NoDataChart.tsx @@ -9,8 +9,8 @@ import { faChartLine } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { styled, Typography } from "@mui/material"; -import { useTranslation } from "react-i18next"; +import { useTranslate } from "@/hooks/useTranslate"; import { SXStyleOptions } from "@/utils/SXStyleOptions"; export const StyledMessage = styled(Typography)( @@ -24,7 +24,7 @@ export const StyledMessage = styled(Typography)( ); export const NoDataChart = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); return ( diff --git a/frontend/src/components/dashboard/PopularChart.tsx b/frontend/src/components/dashboard/PopularChart.tsx index c3568cc1..b8aa141d 100644 --- a/frontend/src/components/dashboard/PopularChart.tsx +++ b/frontend/src/components/dashboard/PopularChart.tsx @@ -8,17 +8,17 @@ import { Card, CardContent, Divider } from "@mui/material"; import { ColumnChart, ResponsiveChartContainer } from "eazychart-react"; -import { useTranslation } from "react-i18next"; import { StyledCardHeader } from "@/app-components/card/StyledCardHeader"; import { useFindStats } from "@/hooks/entities/bot-stat-hooks"; +import { useTranslate } from "@/hooks/useTranslate"; import { ColumnChartStats } from "@/types/bot-stat.types"; import { buildColumnChartConfig } from "@/utils/chart"; import { NoDataChart } from "./NoDataChart"; const PopularChart = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); const { data } = useFindStats("popularBlocks"); return ( diff --git a/frontend/src/components/dashboard/index.tsx b/frontend/src/components/dashboard/index.tsx index 7cc6fd10..bd69b8fc 100644 --- a/frontend/src/components/dashboard/index.tsx +++ b/frontend/src/components/dashboard/index.tsx @@ -9,8 +9,8 @@ import Home from "@mui/icons-material/Home"; import { Grid, GridProps } from "@mui/material"; import { PropsWithChildren } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslate } from "@/hooks/useTranslate"; import { PageHeader } from "@/layout/content/PageHeader"; import AudienceChart from "./AudienceChart"; @@ -23,7 +23,7 @@ const DashboardContent = (props: PropsWithChildren) => ( ); export const Dashboard = () => { - const { t } = useTranslation(); + const { t } = useTranslate(); return ( diff --git a/frontend/src/components/inbox/components/AttachmentViewer.tsx b/frontend/src/components/inbox/components/AttachmentViewer.tsx index 76da28a4..59a4e18a 100644 --- a/frontend/src/components/inbox/components/AttachmentViewer.tsx +++ b/frontend/src/components/inbox/components/AttachmentViewer.tsx @@ -9,10 +9,10 @@ import DownloadIcon from "@mui/icons-material/Download"; import { Button, Dialog, DialogContent } from "@mui/material"; import { FC } from "react"; -import { useTranslation } from "react-i18next"; import { DialogTitle } from "@/app-components/dialogs"; import { useDialog } from "@/hooks/useDialog"; +import { useTranslate } from "@/hooks/useTranslate"; import { AttachmentAttrs, FileType, @@ -68,7 +68,7 @@ const componentMap: { [key in FileType]: FC } = { return