feat(frontend): i18n for admin users page
This commit is contained in:
parent
e845ba63c8
commit
3cb1db81c0
4 changed files with 227 additions and 51 deletions
|
|
@ -23,6 +23,7 @@ import { usersApi, adminCompaniesApi, type ApiUser, type AdminCompany } from "@/
|
|||
import { getCurrentUser, isAdminUser } from "@/lib/auth"
|
||||
import { toast } from "sonner"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import { useTranslation } from "@/lib/i18n"
|
||||
|
||||
const userDateFormatter = new Intl.DateTimeFormat("en-US", {
|
||||
dateStyle: "medium",
|
||||
|
|
@ -31,6 +32,7 @@ const userDateFormatter = new Intl.DateTimeFormat("en-US", {
|
|||
|
||||
export default function AdminUsersPage() {
|
||||
const router = useRouter()
|
||||
const { t } = useTranslation()
|
||||
const [users, setUsers] = useState<ApiUser[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [searchTerm, setSearchTerm] = useState("")
|
||||
|
|
@ -105,7 +107,7 @@ export default function AdminUsersPage() {
|
|||
setPage(data?.pagination?.page || targetPage)
|
||||
} catch (error) {
|
||||
console.error("[USER_FLOW] Error loading users:", error)
|
||||
toast.error("Failed to load users")
|
||||
toast.error(t('admin.users.messages.load_error'))
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
|
|
@ -120,14 +122,14 @@ export default function AdminUsersPage() {
|
|||
roles: [formData.role],
|
||||
}
|
||||
await usersApi.create(payload)
|
||||
toast.success("User created successfully!")
|
||||
toast.success(t('admin.users.messages.create_success'))
|
||||
setIsDialogOpen(false)
|
||||
setFormData({ name: "", email: "", password: "", role: "candidate", status: "active", companyId: "" })
|
||||
setPage(1)
|
||||
loadUsers(1)
|
||||
} catch (error) {
|
||||
console.error("[USER_FLOW] Error creating user:", error)
|
||||
toast.error("Failed to create user")
|
||||
toast.error(t('admin.users.messages.create_error'))
|
||||
} finally {
|
||||
setCreating(false)
|
||||
}
|
||||
|
|
@ -169,12 +171,12 @@ export default function AdminUsersPage() {
|
|||
roles: [editFormData.role],
|
||||
}
|
||||
await usersApi.update(selectedUser.id, payload)
|
||||
toast.success("User updated successfully!")
|
||||
toast.success(t('admin.users.messages.update_success'))
|
||||
setIsEditDialogOpen(false)
|
||||
loadUsers()
|
||||
} catch (error) {
|
||||
console.error("[USER_FLOW] Error updating user:", error)
|
||||
toast.error("Failed to update user")
|
||||
toast.error(t('admin.users.messages.update_error'))
|
||||
} finally {
|
||||
setUpdating(false)
|
||||
}
|
||||
|
|
@ -193,7 +195,7 @@ export default function AdminUsersPage() {
|
|||
try {
|
||||
setDeleting(true)
|
||||
await usersApi.delete(selectedUser.id)
|
||||
toast.success("User deleted!")
|
||||
toast.success(t('admin.users.messages.delete_success'))
|
||||
|
||||
// UI Update logic
|
||||
if (users.length === 1 && page > 1) {
|
||||
|
|
@ -210,7 +212,7 @@ export default function AdminUsersPage() {
|
|||
if (error.message && error.message.includes("403")) {
|
||||
toast.error("You don't have permission to delete this user (403)")
|
||||
} else {
|
||||
toast.error("Failed to delete user")
|
||||
toast.error(t('admin.users.messages.delete_error'))
|
||||
}
|
||||
} finally {
|
||||
setDeleting(false)
|
||||
|
|
@ -247,44 +249,44 @@ export default function AdminUsersPage() {
|
|||
{/* Header */}
|
||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl sm:text-3xl font-bold text-foreground">User management</h1>
|
||||
<p className="text-sm sm:text-base text-muted-foreground mt-1">Manage all platform users</p>
|
||||
<h1 className="text-2xl sm:text-3xl font-bold text-foreground">{t('admin.users.title')}</h1>
|
||||
<p className="text-sm sm:text-base text-muted-foreground mt-1">{t('admin.users.subtitle')}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={() => loadUsers()} disabled={loading}>
|
||||
<RefreshCw className={`h-4 w-4 mr-2 ${loading ? "animate-spin" : ""}`} />
|
||||
Refresh
|
||||
{t('admin.users.refresh')}
|
||||
</Button>
|
||||
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="gap-2">
|
||||
<Plus className="h-4 w-4" />
|
||||
New user
|
||||
{t('admin.users.new_user')}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create new user</DialogTitle>
|
||||
<DialogDescription>Fill in the new user details</DialogDescription>
|
||||
<DialogTitle>{t('admin.users.create_dialog.title')}</DialogTitle>
|
||||
<DialogDescription>{t('admin.users.create_dialog.description')}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Label htmlFor="name">{t('admin.users.table.name')}</Label>
|
||||
<Input
|
||||
id="name"
|
||||
value={formData.name}
|
||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
||||
placeholder="Full name"
|
||||
placeholder={t('admin.users.table.name')}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Label htmlFor="email">{t('admin.users.table.email')}</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
||||
placeholder="email@example.com"
|
||||
placeholder={t('admin.users.table.email')}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
|
|
@ -314,7 +316,7 @@ export default function AdminUsersPage() {
|
|||
</div>
|
||||
)}
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="status">Status</Label>
|
||||
<Label htmlFor="status">{t('admin.users.table.status')}</Label>
|
||||
<Select value={formData.status} onValueChange={(v) => setFormData({ ...formData, status: v })}>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
|
|
@ -326,7 +328,7 @@ export default function AdminUsersPage() {
|
|||
</Select>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="role">Role</Label>
|
||||
<Label htmlFor="role">{t('admin.users.table.role')}</Label>
|
||||
<Select value={formData.role} onValueChange={(v) => setFormData({ ...formData, role: v })}>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
|
|
@ -341,10 +343,10 @@ export default function AdminUsersPage() {
|
|||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setIsDialogOpen(false)}>Cancel</Button>
|
||||
<Button variant="outline" onClick={() => setIsDialogOpen(false)}>{t('admin.users.create_dialog.cancel')}</Button>
|
||||
<Button onClick={handleCreate} disabled={creating}>
|
||||
{creating && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||||
Create user
|
||||
{t('admin.users.create_dialog.submit')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
|
@ -355,29 +357,29 @@ export default function AdminUsersPage() {
|
|||
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
|
||||
<DialogContent className="max-w-md max-h-[85vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{viewing ? "User Details" : "Edit User"}</DialogTitle>
|
||||
<DialogDescription>{viewing ? "View user information" : "Update user details"}</DialogDescription>
|
||||
<DialogTitle>{viewing ? t('admin.users.edit_dialog.title_view') : t('admin.users.edit_dialog.title_edit')}</DialogTitle>
|
||||
<DialogDescription>{viewing ? t('admin.users.edit_dialog.description_view') : t('admin.users.edit_dialog.description_edit')}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="edit-name">Name</Label>
|
||||
<Label htmlFor="edit-name">{t('admin.users.table.name')}</Label>
|
||||
<Input
|
||||
id="edit-name"
|
||||
value={editFormData.name}
|
||||
onChange={(e) => setEditFormData({ ...editFormData, name: e.target.value })}
|
||||
placeholder="Full name"
|
||||
placeholder={t('admin.users.table.name')}
|
||||
readOnly={viewing}
|
||||
disabled={viewing}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="edit-email">Email</Label>
|
||||
<Label htmlFor="edit-email">{t('admin.users.table.email')}</Label>
|
||||
<Input
|
||||
id="edit-email"
|
||||
type="email"
|
||||
value={editFormData.email}
|
||||
onChange={(e) => setEditFormData({ ...editFormData, email: e.target.value })}
|
||||
placeholder="email@example.com"
|
||||
placeholder={t('admin.users.table.email')}
|
||||
readOnly={viewing}
|
||||
disabled={viewing}
|
||||
/>
|
||||
|
|
@ -421,7 +423,7 @@ export default function AdminUsersPage() {
|
|||
{viewing ? (
|
||||
<>
|
||||
<Button variant="outline" onClick={() => setIsEditDialogOpen(false)}>
|
||||
Close
|
||||
{t('admin.users.edit_dialog.close')}
|
||||
</Button>
|
||||
<Button onClick={() => setViewing(false)}>
|
||||
Edit
|
||||
|
|
@ -430,11 +432,11 @@ export default function AdminUsersPage() {
|
|||
) : (
|
||||
<>
|
||||
<Button variant="outline" onClick={() => setIsEditDialogOpen(false)}>
|
||||
Cancel
|
||||
{t('admin.users.create_dialog.cancel')}
|
||||
</Button>
|
||||
<Button onClick={handleUpdate} disabled={updating}>
|
||||
{updating && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||||
Save Changes
|
||||
{t('admin.users.edit_dialog.save')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
|
@ -446,9 +448,9 @@ export default function AdminUsersPage() {
|
|||
<Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete User</DialogTitle>
|
||||
<DialogTitle>{t('admin.users.delete_confirm.title')}</DialogTitle>
|
||||
<DialogDescription>
|
||||
Are you sure you want to delete this user? This action cannot be undone.
|
||||
{t('admin.users.delete_confirm.description')}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="py-4">
|
||||
|
|
@ -462,11 +464,11 @@ export default function AdminUsersPage() {
|
|||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setIsDeleteDialogOpen(false)}>
|
||||
Cancel
|
||||
{t('admin.users.delete_confirm.cancel')}
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={confirmDelete} disabled={deleting}>
|
||||
{deleting && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||||
Delete User
|
||||
{t('admin.users.delete_confirm.confirm')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
|
@ -478,13 +480,13 @@ export default function AdminUsersPage() {
|
|||
<div className="grid gap-3 sm:gap-4 grid-cols-2 md:grid-cols-4">
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardDescription>Total users</CardDescription>
|
||||
<CardDescription>{t('admin.users.total')}</CardDescription>
|
||||
<CardTitle className="text-3xl">{totalUsers}</CardTitle>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardDescription>Admins (page)</CardDescription>
|
||||
<CardDescription>{t('admin.users.admins')}</CardDescription>
|
||||
<CardTitle className="text-3xl">
|
||||
{users.filter((u) => u.role === "superadmin" || u.role === "admin" || u.role === "admin").length}
|
||||
</CardTitle>
|
||||
|
|
@ -492,13 +494,13 @@ export default function AdminUsersPage() {
|
|||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardDescription>Recruiters (page)</CardDescription>
|
||||
<CardDescription>{t('admin.users.recruiters')}</CardDescription>
|
||||
<CardTitle className="text-3xl">{users.filter((u) => u.role === "recruiter").length}</CardTitle>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<CardDescription>Candidates (page)</CardDescription>
|
||||
<CardDescription>{t('admin.users.candidates')}</CardDescription>
|
||||
<CardTitle className="text-3xl">{users.filter((u) => u.role === "candidate" || u.role === "candidate").length}</CardTitle>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
|
|
@ -511,7 +513,7 @@ export default function AdminUsersPage() {
|
|||
<div className="relative flex-1">
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="Search users by name or email..."
|
||||
placeholder={t('admin.users.search_placeholder')}
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="pl-10"
|
||||
|
|
@ -534,19 +536,19 @@ export default function AdminUsersPage() {
|
|||
<Table className="min-w-[600px]">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead className="hidden sm:table-cell">Email</TableHead>
|
||||
<TableHead>Role</TableHead>
|
||||
<TableHead className="hidden md:table-cell">Status</TableHead>
|
||||
<TableHead className="hidden lg:table-cell">Created</TableHead>
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
<TableHead>{t('admin.users.table.name')}</TableHead>
|
||||
<TableHead className="hidden sm:table-cell">{t('admin.users.table.email')}</TableHead>
|
||||
<TableHead>{t('admin.users.table.role')}</TableHead>
|
||||
<TableHead className="hidden md:table-cell">{t('admin.users.table.status')}</TableHead>
|
||||
<TableHead className="hidden lg:table-cell">{t('admin.users.table.created')}</TableHead>
|
||||
<TableHead className="text-right">{t('admin.users.table.actions')}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredUsers.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center text-muted-foreground py-8">
|
||||
No users found
|
||||
{t('admin.users.table.no_users')}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
|
|
@ -607,8 +609,8 @@ export default function AdminUsersPage() {
|
|||
<div className="flex flex-col sm:flex-row items-center justify-between gap-3 text-sm text-muted-foreground pt-4">
|
||||
<span className="text-center sm:text-left">
|
||||
{totalUsers === 0
|
||||
? "No users to display"
|
||||
: `Showing ${(page - 1) * limit + 1}-${Math.min(page * limit, totalUsers)} of ${totalUsers}`}
|
||||
? t('admin.users.pagination.no_users_display')
|
||||
: t('admin.users.pagination.showing', { start: (page - 1) * limit + 1, end: Math.min(page * limit, totalUsers), total: totalUsers })}
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
|
|
@ -617,10 +619,10 @@ export default function AdminUsersPage() {
|
|||
onClick={() => loadUsers(page - 1)}
|
||||
disabled={page <= 1 || loading}
|
||||
>
|
||||
Previous
|
||||
{t('admin.users.pagination.previous')}
|
||||
</Button>
|
||||
<span>
|
||||
Page {page} of {totalPages}
|
||||
{t('admin.users.pagination.page', { current: page, total: totalPages })}
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
|
|
@ -628,7 +630,7 @@ export default function AdminUsersPage() {
|
|||
onClick={() => loadUsers(page + 1)}
|
||||
disabled={page >= totalPages || loading}
|
||||
>
|
||||
Next
|
||||
{t('admin.users.pagination.next')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -660,5 +660,63 @@
|
|||
"a": "Use the Contact page to reach our support team."
|
||||
}
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"users": {
|
||||
"title": "User management",
|
||||
"subtitle": "Manage all platform users",
|
||||
"total": "Total users",
|
||||
"admins": "Admins",
|
||||
"recruiters": "Recruiters",
|
||||
"candidates": "Candidates",
|
||||
"new_user": "New user",
|
||||
"refresh": "Refresh",
|
||||
"search_placeholder": "Search users by name or email...",
|
||||
"table": {
|
||||
"name": "Name",
|
||||
"email": "Email",
|
||||
"role": "Role",
|
||||
"status": "Status",
|
||||
"created": "Created",
|
||||
"actions": "Actions",
|
||||
"no_users": "No users found"
|
||||
},
|
||||
"pagination": {
|
||||
"showing": "Showing {start}-{end} of {total}",
|
||||
"previous": "Previous",
|
||||
"next": "Next",
|
||||
"page": "Page {current} of {total}",
|
||||
"no_users_display": "No users to display"
|
||||
},
|
||||
"delete_confirm": {
|
||||
"title": "Delete User",
|
||||
"description": "Are you sure you want to delete this user? This action cannot be undone.",
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Delete User"
|
||||
},
|
||||
"create_dialog": {
|
||||
"title": "Create new user",
|
||||
"description": "Fill in the new user details",
|
||||
"cancel": "Cancel",
|
||||
"submit": "Create user"
|
||||
},
|
||||
"edit_dialog": {
|
||||
"title_edit": "Edit User",
|
||||
"title_view": "User Details",
|
||||
"description_edit": "Update user details",
|
||||
"description_view": "View user information",
|
||||
"close": "Close",
|
||||
"save": "Save Changes"
|
||||
},
|
||||
"messages": {
|
||||
"create_success": "User created successfully!",
|
||||
"create_error": "Failed to create user",
|
||||
"update_success": "User updated successfully!",
|
||||
"update_error": "Failed to update user",
|
||||
"delete_success": "User deleted!",
|
||||
"delete_error": "Failed to delete user",
|
||||
"load_error": "Failed to load users"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -660,5 +660,63 @@
|
|||
"a": "Usa la página de contacto para hablar con nuestro equipo."
|
||||
}
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"users": {
|
||||
"title": "Gestión de Usuarios",
|
||||
"subtitle": "Gestione todos los usuarios de la plataforma",
|
||||
"total": "Total de usuarios",
|
||||
"admins": "Admins",
|
||||
"recruiters": "Reclutadores",
|
||||
"candidates": "Candidatos",
|
||||
"new_user": "Nuevo usuario",
|
||||
"refresh": "Actualizar",
|
||||
"search_placeholder": "Buscar usuarios por nombre o correo...",
|
||||
"table": {
|
||||
"name": "Nombre",
|
||||
"email": "Correo",
|
||||
"role": "Rol",
|
||||
"status": "Estado",
|
||||
"created": "Creado el",
|
||||
"actions": "Acciones",
|
||||
"no_users": "No se encontraron usuarios"
|
||||
},
|
||||
"pagination": {
|
||||
"showing": "Mostrando {start}-{end} de {total}",
|
||||
"previous": "Anterior",
|
||||
"next": "Siguiente",
|
||||
"page": "Página {current} de {total}",
|
||||
"no_users_display": "No hay usuarios para mostrar"
|
||||
},
|
||||
"delete_confirm": {
|
||||
"title": "Eliminar Usuario",
|
||||
"description": "¿Está seguro de querer eliminar este usuario? Esta acción no se puede deshacer.",
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Eliminar Usuario"
|
||||
},
|
||||
"create_dialog": {
|
||||
"title": "Crear nuevo usuario",
|
||||
"description": "Complete los detalles del nuevo usuario",
|
||||
"cancel": "Cancelar",
|
||||
"submit": "Crear usuario"
|
||||
},
|
||||
"edit_dialog": {
|
||||
"title_edit": "Editar Usuario",
|
||||
"title_view": "Detalles del Usuario",
|
||||
"description_edit": "Actualizar detalles del usuario",
|
||||
"description_view": "Ver información del usuario",
|
||||
"close": "Cerrar",
|
||||
"save": "Guardar Cambios"
|
||||
},
|
||||
"messages": {
|
||||
"create_success": "¡Usuario creado con éxito!",
|
||||
"create_error": "Error al crear usuario",
|
||||
"update_success": "¡Usuario actualizado con éxito!",
|
||||
"update_error": "Error al actualizar usuario",
|
||||
"delete_success": "¡Usuario eliminado!",
|
||||
"delete_error": "Error al eliminar usuario",
|
||||
"load_error": "Error al cargar usuarios"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -660,5 +660,63 @@
|
|||
"a": "Use a página de contato para falar com nosso suporte."
|
||||
}
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"users": {
|
||||
"title": "Gestão de Usuários",
|
||||
"subtitle": "Gerencie todos os usuários da plataforma",
|
||||
"total": "Total de usuários",
|
||||
"admins": "Admins",
|
||||
"recruiters": "Recrutadores",
|
||||
"candidates": "Candidatos",
|
||||
"new_user": "Novo usuário",
|
||||
"refresh": "Atualizar",
|
||||
"search_placeholder": "Buscar usuários por nome ou e-mail...",
|
||||
"table": {
|
||||
"name": "Nome",
|
||||
"email": "E-mail",
|
||||
"role": "Função",
|
||||
"status": "Status",
|
||||
"created": "Criado em",
|
||||
"actions": "Ações",
|
||||
"no_users": "Nenhum usuário encontrado"
|
||||
},
|
||||
"pagination": {
|
||||
"showing": "Mostrando {start}-{end} de {total}",
|
||||
"previous": "Anterior",
|
||||
"next": "Próximo",
|
||||
"page": "Página {current} de {total}",
|
||||
"no_users_display": "Nenhum usuário para mostrar"
|
||||
},
|
||||
"delete_confirm": {
|
||||
"title": "Excluir Usuário",
|
||||
"description": "Tem certeza que deseja excluir este usuário? Esta ação não pode ser desfeita.",
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Excluir Usuário"
|
||||
},
|
||||
"create_dialog": {
|
||||
"title": "Criar novo usuário",
|
||||
"description": "Preencha os detalhes do novo usuário",
|
||||
"cancel": "Cancelar",
|
||||
"submit": "Criar usuário"
|
||||
},
|
||||
"edit_dialog": {
|
||||
"title_edit": "Editar Usuário",
|
||||
"title_view": "Detalhes do Usuário",
|
||||
"description_edit": "Atualizar detalhes do usuário",
|
||||
"description_view": "Ver informações do usuário",
|
||||
"close": "Fechar",
|
||||
"save": "Salvar Alterações"
|
||||
},
|
||||
"messages": {
|
||||
"create_success": "Usuário criado com sucesso!",
|
||||
"create_error": "Falha ao criar usuário",
|
||||
"update_success": "Usuário atualizado com sucesso!",
|
||||
"update_error": "Falha ao atualizar usuário",
|
||||
"delete_success": "Usuário excluído!",
|
||||
"delete_error": "Falha ao excluir usuário",
|
||||
"load_error": "Falha ao carregar usuários"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue