diff --git a/src/workspaces/components/Dialogs/ConfirmDialog/ConfirmDialog.tsx b/src/workspaces/components/Dialogs/ConfirmDialog/ConfirmDialog.tsx index ca48202c..561346e0 100644 --- a/src/workspaces/components/Dialogs/ConfirmDialog/ConfirmDialog.tsx +++ b/src/workspaces/components/Dialogs/ConfirmDialog/ConfirmDialog.tsx @@ -1,6 +1,7 @@ import { useState } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; +import { useTranslation } from '@/components/locales'; type ConfirmDialogProps = { open: boolean; @@ -16,8 +17,9 @@ type ConfirmDialogProps = { export const ConfirmDialog = (props: ConfirmDialogProps) => { const [confirming, setConfirming] = useState(false); + const { t } = useTranslation(); const { open, disabled = false, title, description, children } = props; - const { onConfirm, onCancel, confirmLabel = 'Confirm', confirmVariant = 'default' } = props; + const { onConfirm, onCancel, confirmLabel, confirmVariant = 'default' } = props; const handleConfirm = async () => { setConfirming(true); @@ -37,16 +39,16 @@ export const ConfirmDialog = (props: ConfirmDialogProps) => {
diff --git a/src/workspaces/components/Dialogs/PaperDialog/PaperDialog.tsx b/src/workspaces/components/Dialogs/PaperDialog/PaperDialog.tsx index 0da54be2..4e28328f 100644 --- a/src/workspaces/components/Dialogs/PaperDialog/PaperDialog.tsx +++ b/src/workspaces/components/Dialogs/PaperDialog/PaperDialog.tsx @@ -2,6 +2,7 @@ import type { ReactNode } from 'react'; import { Dialog, DialogOverlay, DialogPortal } from '@/components/ui/dialog'; import * as DialogPrimitive from '@radix-ui/react-dialog'; import { cardStyle } from '@/components/Card'; +import { useTranslation } from '@/components/locales'; type PaperDialogProps = { open: boolean; @@ -11,6 +12,8 @@ type PaperDialogProps = { }; export const PaperDialog = ({ open, onOpenChange, onOpenAutoFocus, children }: PaperDialogProps) => { + const { t } = useTranslation(); + const handleOpenAutoFocus = (ev: Event) => { ev.preventDefault(); onOpenAutoFocus?.(ev); @@ -25,9 +28,9 @@ export const PaperDialog = ({ open, onOpenChange, onOpenAutoFocus, children }: P className="fixed left-[50%] top-[50%] z-[600] grid w-full max-w-md translate-x-[-50%] translate-y-[-50%] gap-4 border-2 border-duck-dark/30 text-duck-dark p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg" style={cardStyle()} > - + ✕ - Close + {t('button.close')} {children} diff --git a/src/workspaces/components/ErrorDialogs/CustomError.tsx b/src/workspaces/components/ErrorDialogs/CustomError.tsx index 91773736..dcaa444b 100644 --- a/src/workspaces/components/ErrorDialogs/CustomError.tsx +++ b/src/workspaces/components/ErrorDialogs/CustomError.tsx @@ -2,9 +2,11 @@ import { Dialog, DialogContent, DialogDescription } from '@/components/ui/dialog import { DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Ban } from 'lucide-react'; +import { useTranslation } from '@/components/locales'; import type { ErrorDialogsProps } from './index'; export const CustomErrorDialog = ({ apiError, setApiError }: ErrorDialogsProps) => { + const { t } = useTranslation(); const onOpenChange = (value: boolean) => { if (!value) { setApiError(null); @@ -16,14 +18,15 @@ export const CustomErrorDialog = ({ apiError, setApiError }: ErrorDialogsProps) - Server Error + {t('error.server.title')} {apiError?.uuid} + {/* The server's own message, shown verbatim — it is a response, not UI copy (see D1). */}

{apiError?.message}

diff --git a/src/workspaces/components/ErrorDialogs/ForbiddenDialog.tsx b/src/workspaces/components/ErrorDialogs/ForbiddenDialog.tsx index 28064c4e..bac459ac 100644 --- a/src/workspaces/components/ErrorDialogs/ForbiddenDialog.tsx +++ b/src/workspaces/components/ErrorDialogs/ForbiddenDialog.tsx @@ -2,9 +2,11 @@ import { Dialog, DialogContent, DialogDescription } from '@/components/ui/dialog import { DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Ban } from 'lucide-react'; +import { useTranslation } from '@/components/locales'; import type { ErrorDialogsProps } from './index'; export const ForbiddenDialog = ({ setApiError }: ErrorDialogsProps) => { + const { t } = useTranslation(); const onOpenChange = (value: boolean) => { if (!value) { setApiError(null); @@ -16,16 +18,14 @@ export const ForbiddenDialog = ({ setApiError }: ErrorDialogsProps) => { - Unauthorized Access + {t('error.forbidden.title')} - - Your are not authorized to perform this action. - + {t('error.forbidden.description')} -

If you think this is an error, please contact your manager.

+

{t('error.forbidden.hint')}

diff --git a/src/workspaces/components/ErrorDialogs/ServerError.tsx b/src/workspaces/components/ErrorDialogs/ServerError.tsx index 298378cd..214f03e9 100644 --- a/src/workspaces/components/ErrorDialogs/ServerError.tsx +++ b/src/workspaces/components/ErrorDialogs/ServerError.tsx @@ -2,9 +2,11 @@ import { Dialog, DialogContent, DialogDescription } from '@/components/ui/dialog import { DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Ban } from 'lucide-react'; +import { useTranslation } from '@/components/locales'; import type { ErrorDialogsProps } from './index'; export const ServerErrorDialog = ({ apiError, setApiError }: ErrorDialogsProps) => { + const { t } = useTranslation(); const onOpenChange = (value: boolean) => { if (!value) { setApiError(null); @@ -16,14 +18,15 @@ export const ServerErrorDialog = ({ apiError, setApiError }: ErrorDialogsProps) - Server Error + {t('error.server.title')} {apiError?.uuid} + {/* The server's own message, shown verbatim — it is a response, not UI copy (see D1). */}

{apiError?.message}

diff --git a/src/workspaces/components/ErrorDialogs/UnauthorizedDialog.tsx b/src/workspaces/components/ErrorDialogs/UnauthorizedDialog.tsx index efc797c2..592f7fe3 100644 --- a/src/workspaces/components/ErrorDialogs/UnauthorizedDialog.tsx +++ b/src/workspaces/components/ErrorDialogs/UnauthorizedDialog.tsx @@ -3,10 +3,12 @@ import { DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Button } from '@/components/ui/button'; import { Ban } from 'lucide-react'; import { useAuth } from 'hooks/useAuth'; +import { useTranslation } from '@/components/locales'; import type { ErrorDialogsProps } from './index'; export const UnauthorizedDialog = ({ setApiError }: ErrorDialogsProps) => { const { signout } = useAuth(); + const { t } = useTranslation(); const onOpenChange = (value: boolean) => { if (!value) { setApiError(null); @@ -20,14 +22,16 @@ export const UnauthorizedDialog = ({ setApiError }: ErrorDialogsProps) => { - Invalid Credentials + {t('error.unauthorized.title')} - Your access token has expired + + {t('error.unauthorized.description')} + -

Please Signin again

+

{t('error.unauthorized.hint')}

diff --git a/src/workspaces/components/locales/en-GB.json b/src/workspaces/components/locales/en-GB.json index 0967ef42..1c2cadce 100644 --- a/src/workspaces/components/locales/en-GB.json +++ b/src/workspaces/components/locales/en-GB.json @@ -1 +1,74 @@ -{} +{ + "button": { + "cancel": "Cancel", + "confirm": "Confirm", + "ok": "Ok", + "close": "Close" + }, + "search": { + "placeholder": "Search", + "open": "Open search", + "close": "Close search", + "clear": "Clear search" + }, + "select": { + "placeholder": "Select..." + }, + "tabs": { + "filterPlaceholder": "Filter" + }, + "state": { + "loading": "Loading…" + }, + "dataTable": { + "empty": "No Data Found.", + "pagination": { + "showingPage": "Showing page {{current}} of {{total}}", + "showingPageShort": "p {{current}}/{{total}}", + "rowsPerPage": "Rows per page", + "perPage": "{{size}} / page", + "perPageShort": "{{size}}/p", + "first": "First", + "prev": "Prev", + "next": "Next", + "last": "Last" + } + }, + "pagination": { + "label": "Pagination", + "previous": "Previous", + "next": "Next", + "morePages": "More pages", + "goToPrevious": "Go to previous page", + "goToNext": "Go to next page" + }, + "carousel": { + "previous": "Previous slide", + "next": "Next slide" + }, + "breadcrumb": { + "more": "More" + }, + "theme": { + "toggle": "Toggle color mode" + }, + "error": { + "forbidden": { + "title": "Unauthorized Access", + "description": "You are not authorized to perform this action.", + "hint": "If you think this is an error, please contact your manager." + }, + "unauthorized": { + "title": "Invalid Credentials", + "description": "Your access token has expired", + "hint": "Please sign in again" + }, + "server": { + "title": "Server Error" + } + }, + "logo": { + "icon": "Officer Icon", + "logo": "Officer Logo" + } +} diff --git a/src/workspaces/components/locales/pt-PT.json b/src/workspaces/components/locales/pt-PT.json index 0967ef42..743c0f7f 100644 --- a/src/workspaces/components/locales/pt-PT.json +++ b/src/workspaces/components/locales/pt-PT.json @@ -1 +1,74 @@ -{} +{ + "button": { + "cancel": "Cancelar", + "confirm": "Confirmar", + "ok": "OK", + "close": "Fechar" + }, + "search": { + "placeholder": "Pesquisar", + "open": "Abrir pesquisa", + "close": "Fechar pesquisa", + "clear": "Limpar pesquisa" + }, + "select": { + "placeholder": "Selecionar..." + }, + "tabs": { + "filterPlaceholder": "Filtrar" + }, + "state": { + "loading": "A carregar…" + }, + "dataTable": { + "empty": "Não foram encontrados dados.", + "pagination": { + "showingPage": "A mostrar página {{current}} de {{total}}", + "showingPageShort": "p {{current}}/{{total}}", + "rowsPerPage": "Linhas por página", + "perPage": "{{size}} / página", + "perPageShort": "{{size}}/p", + "first": "Primeira", + "prev": "Anterior", + "next": "Seguinte", + "last": "Última" + } + }, + "pagination": { + "label": "Paginação", + "previous": "Anterior", + "next": "Seguinte", + "morePages": "Mais páginas", + "goToPrevious": "Ir para a página anterior", + "goToNext": "Ir para a página seguinte" + }, + "carousel": { + "previous": "Diapositivo anterior", + "next": "Diapositivo seguinte" + }, + "breadcrumb": { + "more": "Mais" + }, + "theme": { + "toggle": "Alternar modo de cor" + }, + "error": { + "forbidden": { + "title": "Acesso não autorizado", + "description": "Não tem autorização para executar esta ação.", + "hint": "Se acha que isto é um erro, contacte o seu gestor." + }, + "unauthorized": { + "title": "Credenciais inválidas", + "description": "O seu token de acesso expirou", + "hint": "Inicie sessão novamente" + }, + "server": { + "title": "Erro do servidor" + } + }, + "logo": { + "icon": "Ícone Officer", + "logo": "Logótipo Officer" + } +}