diff --git a/.codex/config.toml b/.codex/config.toml index 6b7b014..c11de17 100644 --- a/.codex/config.toml +++ b/.codex/config.toml @@ -14,7 +14,7 @@ project_doc_fallback_filenames = ["AGENTS.md"] # Without this flag, hooks.json is ignored and Trellis context won't # be injected into Codex sessions. -sandbox_mode = "workspace-write" +sandbox_mode = "danger-full-access" [sandbox_workspace_write] network_access = true diff --git a/.trellis/spec/backend/error-handling.md b/.trellis/spec/backend/error-handling.md index cccc38a..51ef725 100644 --- a/.trellis/spec/backend/error-handling.md +++ b/.trellis/spec/backend/error-handling.md @@ -52,3 +52,10 @@ DAOs report database failures without leaking SQL details to JSP pages. Use concise messages suitable for JSP rendering. For protected operations, prefer generic denial messages over exposing permission internals. + +For this application, messages rendered into JSP pages should be Simplified +Chinese. This includes `ServiceResult.message`, field-level validation errors, +flash messages set by Servlet controllers, and display names returned by entity +helpers. Keep log-only diagnostics, exception types, stored enum codes, request +parameter names, and database values unchanged unless a separate contract change +requires it. diff --git a/.trellis/spec/frontend/component-guidelines.md b/.trellis/spec/frontend/component-guidelines.md index 573f468..579dd1a 100644 --- a/.trellis/spec/frontend/component-guidelines.md +++ b/.trellis/spec/frontend/component-guidelines.md @@ -23,6 +23,19 @@ the reusable UI units. --- +## Interface Copy + +- Render user-visible JSP copy in Simplified Chinese, including navigation, + headings, form labels, buttons, table headers, empty states, and accessible + labels. +- Keep machine-readable values unchanged: URLs, request parameter names, CSS + classes, Java identifiers, enum codes, database values, and servlet names stay + in their existing code form. +- Translate display helper output and controller/service messages when they are + rendered into JSP pages. + +--- + ## Forms - Forms should post to Servlet controller endpoints, not directly to DAOs or diff --git a/.trellis/tasks/04-28-frontend-chinese-ui/check.jsonl b/.trellis/tasks/04-28-frontend-chinese-ui/check.jsonl new file mode 100644 index 0000000..514d020 --- /dev/null +++ b/.trellis/tasks/04-28-frontend-chinese-ui/check.jsonl @@ -0,0 +1,6 @@ +{"file": ".trellis/spec/frontend/index.md", "reason": "Check translated UI against frontend conventions."} +{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Verify forms, tables, fragments, and UI copy remain presentation-focused."} +{"file": ".trellis/spec/frontend/type-safety.md", "reason": "Verify JSP/Servlet display contracts and escaping were preserved."} +{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "Verify accessibility labels, layout preservation, and JSP/CSS quality."} +{"file": ".trellis/spec/backend/error-handling.md", "reason": "Review translated backend messages displayed in the UI."} +{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "Review backend layer boundaries for message-only changes."} diff --git a/.trellis/tasks/04-28-frontend-chinese-ui/implement.jsonl b/.trellis/tasks/04-28-frontend-chinese-ui/implement.jsonl new file mode 100644 index 0000000..2867c99 --- /dev/null +++ b/.trellis/tasks/04-28-frontend-chinese-ui/implement.jsonl @@ -0,0 +1,7 @@ +{"file": ".trellis/spec/frontend/index.md", "reason": "Frontend JSP/CSS conventions and pre-development checklist for UI changes."} +{"file": ".trellis/spec/frontend/directory-structure.md", "reason": "Confirms JSP/static asset layout and forbidden SPA conventions."} +{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "JSP fragments, forms, tables, and reusable UI conventions affected by translation."} +{"file": ".trellis/spec/frontend/type-safety.md", "reason": "JSP/Servlet display contracts and safe rendering guidance while changing visible text."} +{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "Frontend quality bar for preserving JSP/CSS behavior and accessibility basics."} +{"file": ".trellis/spec/backend/error-handling.md", "reason": "Server-generated UI messages must remain safe and user-facing."} +{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "Layer boundary constraints for any controller/service message changes."} diff --git a/.trellis/tasks/04-28-frontend-chinese-ui/prd.md b/.trellis/tasks/04-28-frontend-chinese-ui/prd.md new file mode 100644 index 0000000..ce8d525 --- /dev/null +++ b/.trellis/tasks/04-28-frontend-chinese-ui/prd.md @@ -0,0 +1,61 @@ +# brainstorm: Frontend Chinese UI + +## Goal + +Make the existing JSP/Servlet frontend interface display in Simplified Chinese so users see Chinese page titles, navigation, labels, action buttons, empty states, accessibility labels, and server-rendered feedback messages. + +## What I already know + +* The user requested: "前端界面需要中文". +* The project uses JSP/CSS rendered by Servlet/Tomcat, not a SPA framework. +* Visible English text is concentrated in `src/main/webapp/WEB-INF/jsp/**`. +* Some user-facing messages are set by Java controllers/services and rendered by JSP pages. +* The application already uses UTF-8 JSP page encoding and a UTF-8 character encoding filter. + +## Assumptions + +* Use Simplified Chinese for all user-visible frontend copy. +* Keep URLs, form field names, Java identifiers, enum codes, database values, CSS class names, and servlet names unchanged. +* Translate dynamic display names exposed by Java enums/role helpers where they are shown in the UI. +* Do not add a full i18n framework in this task. + +## Open Questions + +* None blocking; proceed with the Simplified Chinese assumption. + +## Requirements + +* Translate all hardcoded visible English text in JSP pages to Simplified Chinese. +* Change HTML language attributes from English to Simplified Chinese where applicable. +* Translate visible document titles and the web app display name. +* Translate server-generated messages that are displayed to users on the frontend. +* Preserve existing page structure, routing, permissions, form submission behavior, JSTL/EL bindings, and backend workflows. +* Leave stored data and machine-readable codes unchanged. + +## Acceptance Criteria + +* [x] Navigation, page headings, labels, buttons, table headers, empty states, option labels, and accessible labels appear in Simplified Chinese. +* [x] Login, unauthorized, dashboard, role home, catalog, management, reader, borrowing, report, system log, and admin user pages no longer show English UI copy except product/brand names and technical/user data. +* [x] Server-rendered success/error messages shown in the UI are Simplified Chinese. +* [x] Maven build succeeds. + +## Definition of Done + +* Tests or build verification run where practical. +* Lint/typecheck/build green for the Java webapp. +* Spec update considered after implementation. + +## Out of Scope + +* Runtime language switching. +* Browser locale detection. +* New translation resource bundles. +* Database data migration. +* Visual redesign beyond any minor layout-preserving text fit adjustments. + +## Technical Notes + +* Relevant spec index: `.trellis/spec/frontend/index.md`. +* Backend messages may require `.trellis/spec/backend/error-handling.md` and `.trellis/spec/backend/quality-guidelines.md`. +* Likely affected frontend files include `src/main/webapp/WEB-INF/jsp/**`, `src/main/webapp/WEB-INF/web.xml`, and possibly `src/main/webapp/static/images/library-login.svg` for accessible text. +* Likely affected Java files include controllers/services/entities that expose user-facing display names or request messages. diff --git a/.trellis/tasks/04-28-frontend-chinese-ui/task.json b/.trellis/tasks/04-28-frontend-chinese-ui/task.json new file mode 100644 index 0000000..e74f741 --- /dev/null +++ b/.trellis/tasks/04-28-frontend-chinese-ui/task.json @@ -0,0 +1,26 @@ +{ + "id": "frontend-chinese-ui", + "name": "frontend-chinese-ui", + "title": "brainstorm: 前端界面中文化", + "description": "", + "status": "in_progress", + "dev_type": null, + "scope": null, + "package": null, + "priority": "P2", + "creator": "Zzzz", + "assignee": "Zzzz", + "createdAt": "2026-04-28", + "completedAt": null, + "branch": null, + "base_branch": "master", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [], + "notes": "", + "meta": {} +} \ No newline at end of file diff --git a/src/main/java/com/mzh/library/controller/BookManagementServlet.java b/src/main/java/com/mzh/library/controller/BookManagementServlet.java index 124a0fb..44750a2 100644 --- a/src/main/java/com/mzh/library/controller/BookManagementServlet.java +++ b/src/main/java/com/mzh/library/controller/BookManagementServlet.java @@ -44,7 +44,7 @@ public class BookManagementServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getServletPath(); if ("/books/new".equals(path)) { - renderForm(request, response, "Create book", "/books", new Book(), Collections.emptyMap(), + renderForm(request, response, "创建图书", "/books", new Book(), Collections.emptyMap(), Collections.emptyMap(), null); return; } @@ -57,7 +57,7 @@ public class BookManagementServlet extends HttpServlet { return; } if ("/book-categories/new".equals(path)) { - renderCategoryForm(request, response, "Create category", "/book-categories", new BookCategory(), + renderCategoryForm(request, response, "创建分类", "/book-categories", new BookCategory(), Collections.emptyMap(), Collections.emptyMap(), null); return; } @@ -134,12 +134,12 @@ public class BookManagementServlet extends HttpServlet { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult> result = bookService.findBook(id); if (!result.isSuccessful() || !result.getData().isPresent()) { - flashError(request, result.isSuccessful() ? "Book was not found." : result.getMessage()); + flashError(request, result.isSuccessful() ? "未找到图书。" : result.getMessage()); response.sendRedirect(request.getContextPath() + "/books"); return; } - renderForm(request, response, "Edit book", "/books/update", result.getData().get(), + renderForm(request, response, "编辑图书", "/books/update", result.getData().get(), Collections.emptyMap(), Collections.emptyMap(), null); } @@ -160,26 +160,26 @@ public class BookManagementServlet extends HttpServlet { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult> result = bookService.findCategory(id); if (!result.isSuccessful() || !result.getData().isPresent()) { - flashError(request, result.isSuccessful() ? "Category was not found." : result.getMessage()); + flashError(request, result.isSuccessful() ? "未找到分类。" : result.getMessage()); response.sendRedirect(request.getContextPath() + "/book-categories"); return; } - renderCategoryForm(request, response, "Edit category", "/book-categories/update", result.getData().get(), + renderCategoryForm(request, response, "编辑分类", "/book-categories/update", result.getData().get(), Collections.emptyMap(), Collections.emptyMap(), null); } private void createBook(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BookForm form = readBookForm(request, false); if (!form.getErrors().isEmpty()) { - renderForm(request, response, "Create book", "/books", form.getBook(), form.getValues(), - form.getErrors(), "Please correct the highlighted book fields."); + renderForm(request, response, "创建图书", "/books", form.getBook(), form.getValues(), + form.getErrors(), "请修正高亮的图书字段。"); return; } ServiceResult result = bookService.createBook(currentUser(request), form.getBook()); if (!result.isSuccessful()) { - handleFormFailure(request, response, "Create book", "/books", form, result); + handleFormFailure(request, response, "创建图书", "/books", form, result); return; } @@ -190,14 +190,14 @@ public class BookManagementServlet extends HttpServlet { private void updateBook(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BookForm form = readBookForm(request, true); if (!form.getErrors().isEmpty()) { - renderForm(request, response, "Edit book", "/books/update", form.getBook(), form.getValues(), - form.getErrors(), "Please correct the highlighted book fields."); + renderForm(request, response, "编辑图书", "/books/update", form.getBook(), form.getValues(), + form.getErrors(), "请修正高亮的图书字段。"); return; } ServiceResult result = bookService.updateBook(currentUser(request), form.getBook()); if (!result.isSuccessful()) { - handleFormFailure(request, response, "Edit book", "/books/update", form, result); + handleFormFailure(request, response, "编辑图书", "/books/update", form, result); return; } @@ -224,14 +224,14 @@ public class BookManagementServlet extends HttpServlet { throws ServletException, IOException { CategoryForm form = readCategoryForm(request, false); if (!form.getErrors().isEmpty()) { - renderCategoryForm(request, response, "Create category", "/book-categories", form.getCategory(), - form.getValues(), form.getErrors(), "Please correct the highlighted category fields."); + renderCategoryForm(request, response, "创建分类", "/book-categories", form.getCategory(), + form.getValues(), form.getErrors(), "请修正高亮的分类字段。"); return; } ServiceResult result = bookService.createCategory(currentUser(request), form.getCategory()); if (!result.isSuccessful()) { - handleCategoryFormFailure(request, response, "Create category", "/book-categories", form, result); + handleCategoryFormFailure(request, response, "创建分类", "/book-categories", form, result); return; } @@ -243,14 +243,14 @@ public class BookManagementServlet extends HttpServlet { throws ServletException, IOException { CategoryForm form = readCategoryForm(request, true); if (!form.getErrors().isEmpty()) { - renderCategoryForm(request, response, "Edit category", "/book-categories/update", form.getCategory(), - form.getValues(), form.getErrors(), "Please correct the highlighted category fields."); + renderCategoryForm(request, response, "编辑分类", "/book-categories/update", form.getCategory(), + form.getValues(), form.getErrors(), "请修正高亮的分类字段。"); return; } ServiceResult result = bookService.updateCategory(currentUser(request), form.getCategory()); if (!result.isSuccessful()) { - handleCategoryFormFailure(request, response, "Edit category", "/book-categories/update", form, result); + handleCategoryFormFailure(request, response, "编辑分类", "/book-categories/update", form, result); return; } @@ -338,20 +338,20 @@ public class BookManagementServlet extends HttpServlet { Book book = new Book(); if (requireId) { - book.setId(parseLong(values.get("id"), "id", "Select a valid book.", errors)); + book.setId(parseLong(values.get("id"), "id", "请选择有效的图书。", errors)); } book.setIdentifier(values.get("identifier")); book.setTitle(values.get("title")); book.setAuthor(values.get("author")); - book.setCategoryId(parseLong(values.get("categoryId"), "categoryId", "Select a category.", errors)); - book.setTotalCopies(parseInt(values.get("totalCopies"), "totalCopies", "Enter a valid total copy count.", errors)); + book.setCategoryId(parseLong(values.get("categoryId"), "categoryId", "请选择分类。", errors)); + book.setTotalCopies(parseInt(values.get("totalCopies"), "totalCopies", "请输入有效的馆藏总数。", errors)); book.setAvailableCopies(parseInt(values.get("availableCopies"), "availableCopies", - "Enter a valid available copy count.", errors)); + "请输入有效的可借数量。", errors)); try { book.setStatus(BookStatus.fromCode(values.get("status"))); } catch (IllegalArgumentException ex) { - errors.put("status", "Select a status."); + errors.put("status", "请选择状态。"); } return new BookForm(book, values, errors); @@ -376,7 +376,7 @@ public class BookManagementServlet extends HttpServlet { BookCategory category = new BookCategory(); if (requireId) { - category.setId(parseLong(values.get("id"), "id", "Select a valid category.", errors)); + category.setId(parseLong(values.get("id"), "id", "请选择有效的分类。", errors)); } category.setName(values.get("name")); category.setDescription(values.get("description")); @@ -454,7 +454,7 @@ public class BookManagementServlet extends HttpServlet { } private boolean isPermissionDenied(ServiceResult result) { - return !result.isSuccessful() && "You do not have permission to manage books.".equals(result.getMessage()); + return !result.isSuccessful() && "您无权管理图书。".equals(result.getMessage()); } private void forwardDenied(HttpServletRequest request, HttpServletResponse response, String message) diff --git a/src/main/java/com/mzh/library/controller/BorrowingManagementServlet.java b/src/main/java/com/mzh/library/controller/BorrowingManagementServlet.java index 7b920f4..a004dff 100644 --- a/src/main/java/com/mzh/library/controller/BorrowingManagementServlet.java +++ b/src/main/java/com/mzh/library/controller/BorrowingManagementServlet.java @@ -115,7 +115,7 @@ public class BorrowingManagementServlet extends HttpServlet { throws IOException, ServletException { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult result = id <= 0 - ? ServiceResult.failure("Select a valid borrowing record.") + ? ServiceResult.failure("请选择有效的借阅记录。") : borrowingService.returnBook(currentUser(request), id); redirectWithResult(request, response, result); } @@ -124,7 +124,7 @@ public class BorrowingManagementServlet extends HttpServlet { throws IOException, ServletException { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult result = id <= 0 - ? ServiceResult.failure("Select a valid borrowing record.") + ? ServiceResult.failure("请选择有效的借阅记录。") : borrowingService.renewLoan(currentUser(request), id); redirectWithResult(request, response, result); } @@ -185,12 +185,12 @@ public class BorrowingManagementServlet extends HttpServlet { if (result.hasErrors()) { return result.getErrors().values().iterator().next(); } - return "Borrowing action failed."; + return "借阅操作失败。"; } private boolean isPermissionDenied(ServiceResult result) { return !result.isSuccessful() - && "You do not have permission to manage borrowing.".equals(result.getMessage()); + && "您无权管理借阅。".equals(result.getMessage()); } private void forwardDenied(HttpServletRequest request, HttpServletResponse response, String message) diff --git a/src/main/java/com/mzh/library/controller/ReaderLoanHistoryServlet.java b/src/main/java/com/mzh/library/controller/ReaderLoanHistoryServlet.java index 8a32f04..07ced8c 100644 --- a/src/main/java/com/mzh/library/controller/ReaderLoanHistoryServlet.java +++ b/src/main/java/com/mzh/library/controller/ReaderLoanHistoryServlet.java @@ -20,7 +20,7 @@ import javax.servlet.http.HttpSession; public class ReaderLoanHistoryServlet extends HttpServlet { private static final String HISTORY_JSP = "/WEB-INF/jsp/reader/loans.jsp"; private static final String UNAUTHORIZED_JSP = "/WEB-INF/jsp/auth/unauthorized.jsp"; - private static final String HISTORY_DENIED_MESSAGE = "You do not have permission to view loan history."; + private static final String HISTORY_DENIED_MESSAGE = "您无权查看借阅历史。"; private BorrowingServiceImpl borrowingService; diff --git a/src/main/java/com/mzh/library/controller/ReaderManagementServlet.java b/src/main/java/com/mzh/library/controller/ReaderManagementServlet.java index aab4344..43d0ed2 100644 --- a/src/main/java/com/mzh/library/controller/ReaderManagementServlet.java +++ b/src/main/java/com/mzh/library/controller/ReaderManagementServlet.java @@ -41,7 +41,7 @@ public class ReaderManagementServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getServletPath(); if ("/readers/new".equals(path)) { - renderForm(request, response, "Create reader", "/readers", defaultReader(), Collections.emptyMap(), + renderForm(request, response, "创建读者", "/readers", defaultReader(), Collections.emptyMap(), Collections.emptyMap(), null); return; } @@ -99,12 +99,12 @@ public class ReaderManagementServlet extends HttpServlet { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult> result = readerService.findReader(id); if (!result.isSuccessful() || !result.getData().isPresent()) { - flashError(request, result.isSuccessful() ? "Reader profile was not found." : result.getMessage()); + flashError(request, result.isSuccessful() ? "未找到读者档案。" : result.getMessage()); response.sendRedirect(request.getContextPath() + "/readers"); return; } - renderForm(request, response, "Edit reader", "/readers/update", result.getData().get(), + renderForm(request, response, "编辑读者", "/readers/update", result.getData().get(), Collections.emptyMap(), Collections.emptyMap(), null); } @@ -112,14 +112,14 @@ public class ReaderManagementServlet extends HttpServlet { throws ServletException, IOException { ReaderForm form = readReaderForm(request, false); if (!form.getErrors().isEmpty()) { - renderForm(request, response, "Create reader", "/readers", form.getReader(), form.getValues(), - form.getErrors(), "Please correct the highlighted reader fields."); + renderForm(request, response, "创建读者", "/readers", form.getReader(), form.getValues(), + form.getErrors(), "请修正高亮的读者字段。"); return; } ServiceResult result = readerService.createReader(currentUser(request), form.getReader()); if (!result.isSuccessful()) { - handleFormFailure(request, response, "Create reader", "/readers", form, result); + handleFormFailure(request, response, "创建读者", "/readers", form, result); return; } @@ -131,14 +131,14 @@ public class ReaderManagementServlet extends HttpServlet { throws ServletException, IOException { ReaderForm form = readReaderForm(request, true); if (!form.getErrors().isEmpty()) { - renderForm(request, response, "Edit reader", "/readers/update", form.getReader(), form.getValues(), - form.getErrors(), "Please correct the highlighted reader fields."); + renderForm(request, response, "编辑读者", "/readers/update", form.getReader(), form.getValues(), + form.getErrors(), "请修正高亮的读者字段。"); return; } ServiceResult result = readerService.updateReader(currentUser(request), form.getReader()); if (!result.isSuccessful()) { - handleFormFailure(request, response, "Edit reader", "/readers/update", form, result); + handleFormFailure(request, response, "编辑读者", "/readers/update", form, result); return; } @@ -195,21 +195,21 @@ public class ReaderManagementServlet extends HttpServlet { Reader reader = new Reader(); if (requireId) { - reader.setId(parseLong(values.get("id"), "id", "Select a valid reader.", errors)); + reader.setId(parseLong(values.get("id"), "id", "请选择有效的读者。", errors)); } reader.setIdentifier(values.get("identifier")); reader.setUserId(optionalPositiveLong(values.get("userId"), "userId", - "Enter a valid linked account ID.", errors)); + "请输入有效的关联账户 ID。", errors)); reader.setFullName(values.get("fullName")); reader.setPhone(values.get("phone")); reader.setEmail(values.get("email")); reader.setMaxBorrowCount(parseInt(values.get("maxBorrowCount"), "maxBorrowCount", - "Enter a valid max borrow count.", errors)); + "请输入有效的最大借阅数量。", errors)); try { reader.setStatus(ReaderStatus.fromCode(values.get("status"))); } catch (IllegalArgumentException ex) { - errors.put("status", "Select a status."); + errors.put("status", "请选择状态。"); } return new ReaderForm(reader, values, errors); @@ -304,7 +304,7 @@ public class ReaderManagementServlet extends HttpServlet { } private boolean isPermissionDenied(ServiceResult result) { - return !result.isSuccessful() && "You do not have permission to manage readers.".equals(result.getMessage()); + return !result.isSuccessful() && "您无权管理读者。".equals(result.getMessage()); } private void forwardDenied(HttpServletRequest request, HttpServletResponse response, String message) diff --git a/src/main/java/com/mzh/library/controller/ReportServlet.java b/src/main/java/com/mzh/library/controller/ReportServlet.java index 94dbf63..fb025d6 100644 --- a/src/main/java/com/mzh/library/controller/ReportServlet.java +++ b/src/main/java/com/mzh/library/controller/ReportServlet.java @@ -46,7 +46,7 @@ public class ReportServlet extends HttpServlet { private boolean isPermissionDenied(ServiceResult result) { return !result.isSuccessful() - && "You do not have permission to view reports.".equals(result.getMessage()); + && "您无权查看报表。".equals(result.getMessage()); } private void forwardDenied(HttpServletRequest request, HttpServletResponse response, String message) diff --git a/src/main/java/com/mzh/library/controller/RoleAreaServlet.java b/src/main/java/com/mzh/library/controller/RoleAreaServlet.java index 1209bf5..bc002cc 100644 --- a/src/main/java/com/mzh/library/controller/RoleAreaServlet.java +++ b/src/main/java/com/mzh/library/controller/RoleAreaServlet.java @@ -14,14 +14,14 @@ public class RoleAreaServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String servletPath = request.getServletPath(); if (servletPath.startsWith("/admin")) { - request.setAttribute("areaName", "Administration"); - request.setAttribute("areaSummary", "Account, role, permission, and system-maintenance entry point."); + request.setAttribute("areaName", "系统管理"); + request.setAttribute("areaSummary", "账户、角色、权限和系统维护入口。"); } else if (servletPath.startsWith("/librarian")) { - request.setAttribute("areaName", "Librarian Workspace"); - request.setAttribute("areaSummary", "Book, reader, borrowing, return, renewal, and overdue entry point."); + request.setAttribute("areaName", "馆员工作台"); + request.setAttribute("areaSummary", "图书、读者、借阅、归还、续借和逾期处理入口。"); } else { - request.setAttribute("areaName", "Reader Center"); - request.setAttribute("areaSummary", "Catalog search and reader self-service entry point."); + request.setAttribute("areaName", "读者中心"); + request.setAttribute("areaSummary", "馆藏检索和读者自助服务入口。"); } request.getRequestDispatcher(ROLE_HOME_JSP).forward(request, response); diff --git a/src/main/java/com/mzh/library/controller/SystemLogServlet.java b/src/main/java/com/mzh/library/controller/SystemLogServlet.java index bedb6d9..b1654d9 100644 --- a/src/main/java/com/mzh/library/controller/SystemLogServlet.java +++ b/src/main/java/com/mzh/library/controller/SystemLogServlet.java @@ -21,7 +21,7 @@ import javax.servlet.http.HttpSession; public class SystemLogServlet extends HttpServlet { private static final String LOGS_JSP = "/WEB-INF/jsp/maintenance/system-logs.jsp"; private static final String UNAUTHORIZED_JSP = "/WEB-INF/jsp/auth/unauthorized.jsp"; - private static final String DENIED_MESSAGE = "You do not have permission to view system logs."; + private static final String DENIED_MESSAGE = "您无权查看系统日志。"; private SystemLogService systemLogService; diff --git a/src/main/java/com/mzh/library/controller/UserManagementServlet.java b/src/main/java/com/mzh/library/controller/UserManagementServlet.java index cf7ddf3..5181ded 100644 --- a/src/main/java/com/mzh/library/controller/UserManagementServlet.java +++ b/src/main/java/com/mzh/library/controller/UserManagementServlet.java @@ -30,7 +30,7 @@ public class UserManagementServlet extends HttpServlet { private static final String UNAUTHORIZED_JSP = "/WEB-INF/jsp/auth/unauthorized.jsp"; private static final String FLASH_SUCCESS = "flashSuccess"; private static final String FLASH_ERROR = "flashError"; - private static final String DENIED_MESSAGE = "You do not have permission to manage users."; + private static final String DENIED_MESSAGE = "您无权管理用户。"; private UserAccountService userAccountService; @@ -44,7 +44,7 @@ public class UserManagementServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getServletPath(); if ("/admin/users/new".equals(path)) { - renderForm(request, response, "Create user account", "/admin/users", defaultUser(), + renderForm(request, response, "创建用户账户", "/admin/users", defaultUser(), Collections.emptyMap(), Collections.emptyMap(), null); return; } @@ -108,12 +108,12 @@ public class UserManagementServlet extends HttpServlet { return; } if (!result.isSuccessful() || !result.getData().isPresent()) { - flashError(request, result.isSuccessful() ? "User account was not found." : result.getMessage()); + flashError(request, result.isSuccessful() ? "未找到用户账户。" : result.getMessage()); response.sendRedirect(request.getContextPath() + "/admin/users"); return; } - renderForm(request, response, "Edit user account", "/admin/users/update", result.getData().get(), + renderForm(request, response, "编辑用户账户", "/admin/users/update", result.getData().get(), Collections.emptyMap(), Collections.emptyMap(), null); } @@ -121,15 +121,15 @@ public class UserManagementServlet extends HttpServlet { throws ServletException, IOException { UserForm form = readUserForm(request, false); if (!form.getErrors().isEmpty()) { - renderForm(request, response, "Create user account", "/admin/users", form.getUser(), form.getValues(), - form.getErrors(), "Please correct the highlighted account fields."); + renderForm(request, response, "创建用户账户", "/admin/users", form.getUser(), form.getValues(), + form.getErrors(), "请修正高亮的账户字段。"); return; } ServiceResult result = userAccountService.createUser(currentUser(request), form.getUser(), form.getPassword(), clientIp(request)); if (!result.isSuccessful()) { - handleFormFailure(request, response, "Create user account", "/admin/users", form, result); + handleFormFailure(request, response, "创建用户账户", "/admin/users", form, result); return; } @@ -141,15 +141,15 @@ public class UserManagementServlet extends HttpServlet { throws ServletException, IOException { UserForm form = readUserForm(request, true); if (!form.getErrors().isEmpty()) { - renderForm(request, response, "Edit user account", "/admin/users/update", form.getUser(), form.getValues(), - form.getErrors(), "Please correct the highlighted account fields."); + renderForm(request, response, "编辑用户账户", "/admin/users/update", form.getUser(), form.getValues(), + form.getErrors(), "请修正高亮的账户字段。"); return; } ServiceResult result = userAccountService.updateUser(currentUser(request), form.getUser(), form.getPassword(), clientIp(request)); if (!result.isSuccessful()) { - handleFormFailure(request, response, "Edit user account", "/admin/users/update", form, result); + handleFormFailure(request, response, "编辑用户账户", "/admin/users/update", form, result); return; } @@ -206,7 +206,7 @@ public class UserManagementServlet extends HttpServlet { User user = new User(); if (requireId) { - user.setId(parseLong(values.get("id"), "id", "Select a valid user account.", errors)); + user.setId(parseLong(values.get("id"), "id", "请选择有效的用户账户。", errors)); } user.setUsername(values.get("username")); user.setDisplayName(values.get("displayName")); @@ -214,7 +214,7 @@ public class UserManagementServlet extends HttpServlet { try { user.setRole(Role.fromCode(values.get("role"))); } catch (IllegalArgumentException ex) { - errors.put("role", "Select a role."); + errors.put("role", "请选择角色。"); } return new UserForm(user, values, errors, request.getParameter("password")); @@ -253,7 +253,7 @@ public class UserManagementServlet extends HttpServlet { if ("false".equals(normalized) || UserSearchCriteria.INACTIVE_STATUS.equals(normalized)) { return false; } - errors.put("active", "Select an active state."); + errors.put("active", "请选择启用状态。"); return false; } diff --git a/src/main/java/com/mzh/library/entity/BookStatus.java b/src/main/java/com/mzh/library/entity/BookStatus.java index 860b1ba..fcdcfe4 100644 --- a/src/main/java/com/mzh/library/entity/BookStatus.java +++ b/src/main/java/com/mzh/library/entity/BookStatus.java @@ -3,9 +3,9 @@ package com.mzh.library.entity; import java.util.Locale; public enum BookStatus { - AVAILABLE("available", "Available"), - UNAVAILABLE("unavailable", "Unavailable"), - ARCHIVED("archived", "Archived"); + AVAILABLE("available", "可借"), + UNAVAILABLE("unavailable", "不可借"), + ARCHIVED("archived", "已归档"); private final String code; private final String displayName; diff --git a/src/main/java/com/mzh/library/entity/BorrowRecord.java b/src/main/java/com/mzh/library/entity/BorrowRecord.java index f31a01c..c7231c8 100644 --- a/src/main/java/com/mzh/library/entity/BorrowRecord.java +++ b/src/main/java/com/mzh/library/entity/BorrowRecord.java @@ -145,7 +145,7 @@ public class BorrowRecord { } public String getDisplayStatusName() { - return isOverdue() ? "Overdue" : status.getDisplayName(); + return isOverdue() ? "逾期" : status.getDisplayName(); } public String getBorrowedAtText() { diff --git a/src/main/java/com/mzh/library/entity/BorrowRecordStatus.java b/src/main/java/com/mzh/library/entity/BorrowRecordStatus.java index 179669e..42fda91 100644 --- a/src/main/java/com/mzh/library/entity/BorrowRecordStatus.java +++ b/src/main/java/com/mzh/library/entity/BorrowRecordStatus.java @@ -3,8 +3,8 @@ package com.mzh.library.entity; import java.util.Locale; public enum BorrowRecordStatus { - ACTIVE("active", "Active"), - RETURNED("returned", "Returned"); + ACTIVE("active", "借阅中"), + RETURNED("returned", "已归还"); private final String code; private final String displayName; diff --git a/src/main/java/com/mzh/library/entity/ReaderStatus.java b/src/main/java/com/mzh/library/entity/ReaderStatus.java index bc59248..911e191 100644 --- a/src/main/java/com/mzh/library/entity/ReaderStatus.java +++ b/src/main/java/com/mzh/library/entity/ReaderStatus.java @@ -3,9 +3,9 @@ package com.mzh.library.entity; import java.util.Locale; public enum ReaderStatus { - ACTIVE("active", "Active"), - SUSPENDED("suspended", "Suspended"), - INACTIVE("inactive", "Inactive"); + ACTIVE("active", "正常"), + SUSPENDED("suspended", "暂停"), + INACTIVE("inactive", "停用"); private final String code; private final String displayName; diff --git a/src/main/java/com/mzh/library/entity/Role.java b/src/main/java/com/mzh/library/entity/Role.java index 0650e16..64b248d 100644 --- a/src/main/java/com/mzh/library/entity/Role.java +++ b/src/main/java/com/mzh/library/entity/Role.java @@ -3,9 +3,9 @@ package com.mzh.library.entity; import java.util.Locale; public enum Role { - ADMINISTRATOR("administrator", "Administrator"), - LIBRARIAN("librarian", "Librarian"), - READER("reader", "Reader"); + ADMINISTRATOR("administrator", "管理员"), + LIBRARIAN("librarian", "馆员"), + READER("reader", "读者"); private final String code; private final String displayName; diff --git a/src/main/java/com/mzh/library/entity/SystemLog.java b/src/main/java/com/mzh/library/entity/SystemLog.java index b5095cf..c80d281 100644 --- a/src/main/java/com/mzh/library/entity/SystemLog.java +++ b/src/main/java/com/mzh/library/entity/SystemLog.java @@ -131,7 +131,7 @@ public class SystemLog { return username; } - return operatorId == null ? "System" : "User #" + operatorId; + return operatorId == null ? "系统" : "用户 #" + operatorId; } public String getOperatorMetaText() { @@ -144,7 +144,7 @@ public class SystemLog { if (operatorId != null && (!displayName.isEmpty() || !username.isEmpty())) { appendMeta(meta, "#" + operatorId); } - appendMeta(meta, trim(operatorRole)); + appendMeta(meta, displayRole(operatorRole)); return meta.toString(); } @@ -157,8 +157,22 @@ public class SystemLog { } public String getResultStatusName() { - String trimmed = trim(resultStatus); - return trimmed.isEmpty() ? "Unknown" : trimmed; + String normalized = trim(resultStatus).toLowerCase(Locale.ROOT); + if ("success".equals(normalized)) { + return "成功"; + } + if ("failure".equals(normalized)) { + return "失败"; + } + return normalized.isEmpty() ? "未知" : trim(resultStatus); + } + + public String getTargetTableName() { + String normalized = trim(targetTable).toLowerCase(Locale.ROOT); + if ("users".equals(normalized)) { + return "用户"; + } + return trim(targetTable); } private void appendMeta(StringBuilder meta, String value) { @@ -174,4 +188,16 @@ public class SystemLog { private String trim(String value) { return value == null ? "" : value.trim(); } + + private String displayRole(String roleCode) { + String normalized = trim(roleCode); + if (normalized.isEmpty()) { + return ""; + } + try { + return Role.fromCode(normalized).getDisplayName(); + } catch (IllegalArgumentException ex) { + return normalized; + } + } } diff --git a/src/main/java/com/mzh/library/entity/User.java b/src/main/java/com/mzh/library/entity/User.java index 6d9ef2c..7758c20 100644 --- a/src/main/java/com/mzh/library/entity/User.java +++ b/src/main/java/com/mzh/library/entity/User.java @@ -84,7 +84,7 @@ public class User { } public String getActiveStatusName() { - return active ? "Active" : "Inactive"; + return active ? "启用" : "停用"; } public String getCreatedAtText() { diff --git a/src/main/java/com/mzh/library/filter/AuthorizationFilter.java b/src/main/java/com/mzh/library/filter/AuthorizationFilter.java index 5967530..8fdacf7 100644 --- a/src/main/java/com/mzh/library/filter/AuthorizationFilter.java +++ b/src/main/java/com/mzh/library/filter/AuthorizationFilter.java @@ -62,7 +62,7 @@ public class AuthorizationFilter implements Filter { logDeniedAccess(user, requiredRule, path); httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); - request.setAttribute("errorMessage", "You do not have permission to access this page."); + request.setAttribute("errorMessage", "您无权访问此页面。"); request.getRequestDispatcher(UNAUTHORIZED_JSP).forward(request, response); } diff --git a/src/main/java/com/mzh/library/service/impl/AuthServiceImpl.java b/src/main/java/com/mzh/library/service/impl/AuthServiceImpl.java index 4aa9090..ae71761 100644 --- a/src/main/java/com/mzh/library/service/impl/AuthServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/AuthServiceImpl.java @@ -17,9 +17,9 @@ import java.util.logging.Logger; public class AuthServiceImpl implements AuthService { private static final Logger LOGGER = Logger.getLogger(AuthServiceImpl.class.getName()); - private static final String REQUIRED_MESSAGE = "Username and password are required."; - private static final String INVALID_MESSAGE = "Invalid username or password."; - private static final String UNAVAILABLE_MESSAGE = "Login service is temporarily unavailable. Please try again later."; + private static final String REQUIRED_MESSAGE = "请输入用户名和密码。"; + private static final String INVALID_MESSAGE = "用户名或密码不正确。"; + private static final String UNAVAILABLE_MESSAGE = "登录服务暂时不可用,请稍后重试。"; private final UserDao userDao; private final PermissionPolicy permissionPolicy; diff --git a/src/main/java/com/mzh/library/service/impl/BookServiceImpl.java b/src/main/java/com/mzh/library/service/impl/BookServiceImpl.java index 3ca6da4..7cc2285 100644 --- a/src/main/java/com/mzh/library/service/impl/BookServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/BookServiceImpl.java @@ -21,10 +21,10 @@ import java.util.logging.Logger; public class BookServiceImpl implements BookService { private static final Logger LOGGER = Logger.getLogger(BookServiceImpl.class.getName()); private static final String UNAVAILABLE_MESSAGE = - "Book service is temporarily unavailable. Please try again later."; - private static final String VALIDATION_MESSAGE = "Please correct the highlighted book fields."; - private static final String CATEGORY_VALIDATION_MESSAGE = "Please correct the highlighted category fields."; - private static final String DENIED_MESSAGE = "You do not have permission to manage books."; + "图书服务暂时不可用,请稍后重试。"; + private static final String VALIDATION_MESSAGE = "请修正高亮的图书字段。"; + private static final String CATEGORY_VALIDATION_MESSAGE = "请修正高亮的分类字段。"; + private static final String DENIED_MESSAGE = "您无权管理图书。"; private final BookDao bookDao; private final PermissionPolicy permissionPolicy; @@ -51,7 +51,7 @@ public class BookServiceImpl implements BookService { @Override public ServiceResult> findCategory(long id) { if (id <= 0) { - return ServiceResult.failure("Select a valid category."); + return ServiceResult.failure("请选择有效的分类。"); } try { @@ -76,13 +76,13 @@ public class BookServiceImpl implements BookService { try { if (bookDao.findCategoryByName(category.getName()).isPresent()) { - errors.put("name", "Category name is already in use."); + errors.put("name", "分类名称已被使用。"); return ServiceResult.validationFailure(CATEGORY_VALIDATION_MESSAGE, errors); } long id = bookDao.createCategory(category); LOGGER.info("Created book category id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(id, "Category created."); + return ServiceResult.success(id, "分类已创建。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to create book category actorId=" + actor.getId() + " name=" + safeCategoryName(category), ex); @@ -105,16 +105,16 @@ public class BookServiceImpl implements BookService { try { Optional existingWithName = bookDao.findCategoryByName(category.getName()); if (existingWithName.isPresent() && existingWithName.get().getId() != category.getId()) { - errors.put("name", "Category name is already in use."); + errors.put("name", "分类名称已被使用。"); return ServiceResult.validationFailure(CATEGORY_VALIDATION_MESSAGE, errors); } if (!bookDao.updateCategory(category)) { - return ServiceResult.failure("Category was not found."); + return ServiceResult.failure("未找到分类。"); } LOGGER.info("Updated book category id=" + category.getId() + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Category updated."); + return ServiceResult.success(null, "分类已更新。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to update book category id=" + category.getId() + " actorId=" + actor.getId(), ex); @@ -128,25 +128,25 @@ public class BookServiceImpl implements BookService { return ServiceResult.failure(DENIED_MESSAGE); } if (id <= 0) { - return ServiceResult.failure("Select a valid category."); + return ServiceResult.failure("请选择有效的分类。"); } try { if (!bookDao.findCategoryById(id).isPresent()) { - return ServiceResult.failure("Category was not found."); + return ServiceResult.failure("未找到分类。"); } if (bookDao.countBooksByCategoryId(id) > 0) { Map errors = new LinkedHashMap<>(); - errors.put("category", "Category is used by existing books and cannot be deleted."); - return ServiceResult.validationFailure("Category is used by existing books and cannot be deleted.", + errors.put("category", "该分类已被现有图书使用,不能删除。"); + return ServiceResult.validationFailure("该分类已被现有图书使用,不能删除。", errors); } if (!bookDao.deleteCategory(id)) { - return ServiceResult.failure("Category was not found."); + return ServiceResult.failure("未找到分类。"); } LOGGER.info("Deleted book category id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Category deleted."); + return ServiceResult.success(null, "分类已删除。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to delete book category id=" + id + " actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -158,8 +158,8 @@ public class BookServiceImpl implements BookService { BookSearchCriteria normalized = criteria == null ? new BookSearchCriteria() : criteria; if (normalized.getCategoryId() != null && normalized.getCategoryId() <= 0) { Map errors = new LinkedHashMap<>(); - errors.put("categoryId", "Select a valid category."); - return ServiceResult.validationFailure("Please correct the catalog search filters.", errors); + errors.put("categoryId", "请选择有效的分类。"); + return ServiceResult.validationFailure("请修正馆藏检索筛选条件。", errors); } try { @@ -173,7 +173,7 @@ public class BookServiceImpl implements BookService { @Override public ServiceResult> findBook(long id) { if (id <= 0) { - return ServiceResult.failure("Select a valid book."); + return ServiceResult.failure("请选择有效的图书。"); } try { @@ -198,13 +198,13 @@ public class BookServiceImpl implements BookService { try { if (bookDao.findByIdentifier(book.getIdentifier()).isPresent()) { - errors.put("identifier", "Book identifier is already in use."); + errors.put("identifier", "图书编号已被使用。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } long id = bookDao.create(book); LOGGER.info("Created book id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(id, "Book created."); + return ServiceResult.success(id, "图书已创建。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to create book actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -226,16 +226,16 @@ public class BookServiceImpl implements BookService { try { Optional existingWithIdentifier = bookDao.findByIdentifier(book.getIdentifier()); if (existingWithIdentifier.isPresent() && existingWithIdentifier.get().getId() != book.getId()) { - errors.put("identifier", "Book identifier is already in use."); + errors.put("identifier", "图书编号已被使用。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } if (!bookDao.update(book)) { - return ServiceResult.failure("Book was not found."); + return ServiceResult.failure("未找到图书。"); } LOGGER.info("Updated book id=" + book.getId() + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Book updated."); + return ServiceResult.success(null, "图书已更新。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to update book id=" + book.getId() + " actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -248,16 +248,16 @@ public class BookServiceImpl implements BookService { return ServiceResult.failure(DENIED_MESSAGE); } if (id <= 0) { - return ServiceResult.failure("Select a valid book."); + return ServiceResult.failure("请选择有效的图书。"); } try { if (!bookDao.delete(id)) { - return ServiceResult.failure("Book was not found."); + return ServiceResult.failure("未找到图书。"); } LOGGER.info("Deleted book id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Book deleted."); + return ServiceResult.success(null, "图书已删除。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to delete book id=" + id + " actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -288,30 +288,30 @@ public class BookServiceImpl implements BookService { private Map validate(Book book, boolean requireId) { Map errors = new LinkedHashMap<>(); if (book == null) { - errors.put("book", "Book details are required."); + errors.put("book", "请填写图书详情。"); return errors; } if (requireId && book.getId() <= 0) { - errors.put("id", "Select a valid book."); + errors.put("id", "请选择有效的图书。"); } - requireLength(errors, "identifier", book.getIdentifier(), "Book identifier", 64); - requireLength(errors, "title", book.getTitle(), "Title", 200); - requireLength(errors, "author", book.getAuthor(), "Author", 120); + requireLength(errors, "identifier", book.getIdentifier(), "图书编号", 64); + requireLength(errors, "title", book.getTitle(), "书名", 200); + requireLength(errors, "author", book.getAuthor(), "作者", 120); if (book.getCategoryId() <= 0) { - errors.put("categoryId", "Select a category."); + errors.put("categoryId", "请选择分类。"); } if (book.getTotalCopies() < 0) { - errors.put("totalCopies", "Total copies cannot be negative."); + errors.put("totalCopies", "馆藏总数不能为负数。"); } if (book.getAvailableCopies() < 0) { - errors.put("availableCopies", "Available copies cannot be negative."); + errors.put("availableCopies", "可借数量不能为负数。"); } if (book.getAvailableCopies() > book.getTotalCopies()) { - errors.put("availableCopies", "Available copies cannot exceed total copies."); + errors.put("availableCopies", "可借数量不能超过馆藏总数。"); } if (book.getStatus() == null) { - errors.put("status", "Select a status."); + errors.put("status", "请选择状态。"); } return errors; } @@ -319,16 +319,16 @@ public class BookServiceImpl implements BookService { private Map validate(BookCategory category, boolean requireId) { Map errors = new LinkedHashMap<>(); if (category == null) { - errors.put("category", "Category details are required."); + errors.put("category", "请填写分类详情。"); return errors; } if (requireId && category.getId() <= 0) { - errors.put("id", "Select a valid category."); + errors.put("id", "请选择有效的分类。"); } - requireLength(errors, "name", category.getName(), "Category name", 96); + requireLength(errors, "name", category.getName(), "分类名称", 96); if (category.getDescription() != null && category.getDescription().length() > 255) { - errors.put("description", "Description must be 255 characters or fewer."); + errors.put("description", "说明不能超过 255 个字符。"); } return errors; } @@ -339,11 +339,11 @@ public class BookServiceImpl implements BookService { private void requireLength(Map errors, String field, String value, String label, int maxLength) { if (value == null || value.isEmpty()) { - errors.put(field, label + " is required."); + errors.put(field, "请填写" + label + "。"); return; } if (value.length() > maxLength) { - errors.put(field, label + " must be " + maxLength + " characters or fewer."); + errors.put(field, label + "不能超过 " + maxLength + " 个字符。"); } } diff --git a/src/main/java/com/mzh/library/service/impl/BorrowingServiceImpl.java b/src/main/java/com/mzh/library/service/impl/BorrowingServiceImpl.java index 5f6915a..014d1dd 100644 --- a/src/main/java/com/mzh/library/service/impl/BorrowingServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/BorrowingServiceImpl.java @@ -35,10 +35,10 @@ public class BorrowingServiceImpl implements BorrowingService { private static final Logger LOGGER = Logger.getLogger(BorrowingServiceImpl.class.getName()); private static final String UNAVAILABLE_MESSAGE = - "Borrowing service is temporarily unavailable. Please try again later."; - private static final String VALIDATION_MESSAGE = "Please correct the highlighted borrowing fields."; - private static final String DENIED_MESSAGE = "You do not have permission to manage borrowing."; - private static final String HISTORY_DENIED_MESSAGE = "You do not have permission to view loan history."; + "借阅服务暂时不可用,请稍后重试。"; + private static final String VALIDATION_MESSAGE = "请修正高亮的借阅字段。"; + private static final String DENIED_MESSAGE = "您无权管理借阅。"; + private static final String HISTORY_DENIED_MESSAGE = "您无权查看借阅历史。"; private static final int LOAN_DAYS = 14; private static final int MAX_RENEWALS = 1; @@ -68,7 +68,7 @@ public class BorrowingServiceImpl implements BorrowingService { BorrowRecordSearchCriteria normalized = criteria == null ? new BorrowRecordSearchCriteria() : criteria; Map errors = validateSearch(normalized); if (!errors.isEmpty()) { - return ServiceResult.validationFailure("Please correct the borrowing search filters.", errors); + return ServiceResult.validationFailure("请修正借阅检索筛选条件。", errors); } try { @@ -98,13 +98,13 @@ public class BorrowingServiceImpl implements BorrowingService { Optional readerResult = borrowRecordDao.findReaderByIdentifierForUpdate(connection, normalizedReaderIdentifier); if (!readerResult.isPresent()) { - transactionErrors.put("readerIdentifier", "Reader was not found."); + transactionErrors.put("readerIdentifier", "未找到读者。"); } Optional bookResult = borrowRecordDao.findBookByIdentifierForUpdate(connection, normalizedBookIdentifier); if (!bookResult.isPresent()) { - transactionErrors.put("bookIdentifier", "Book was not found."); + transactionErrors.put("bookIdentifier", "未找到图书。"); } if (!transactionErrors.isEmpty()) { @@ -134,7 +134,7 @@ public class BorrowingServiceImpl implements BorrowingService { LOGGER.info("Borrowed book recordId=" + id + " readerId=" + reader.getId() + " bookId=" + book.getId() + " actorId=" + actor.getId()); - return ServiceResult.success(id, "Book borrowed."); + return ServiceResult.success(id, "图书已借出。"); }); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to borrow book actorId=" + actor.getId() @@ -150,20 +150,20 @@ public class BorrowingServiceImpl implements BorrowingService { return ServiceResult.failure(DENIED_MESSAGE); } if (recordId <= 0) { - return ServiceResult.failure("Select a valid borrowing record."); + return ServiceResult.failure("请选择有效的借阅记录。"); } try { return transactionExecutor.execute(connection -> { Optional recordResult = borrowRecordDao.findByIdForUpdate(connection, recordId); if (!recordResult.isPresent()) { - return ServiceResult.failure("Borrowing record was not found."); + return ServiceResult.failure("未找到借阅记录。"); } BorrowRecord record = recordResult.get(); Map errors = validateActiveLoan(record); if (!errors.isEmpty()) { - return ServiceResult.validationFailure("Borrowing record cannot be returned.", errors); + return ServiceResult.validationFailure("借阅记录不能归还。", errors); } if (!borrowRecordDao.markReturned(connection, recordId, now())) { @@ -172,7 +172,7 @@ public class BorrowingServiceImpl implements BorrowingService { borrowRecordDao.incrementAvailableCopies(connection, record.getBookId()); LOGGER.info("Returned borrow recordId=" + recordId + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Book returned."); + return ServiceResult.success(null, "图书已归还。"); }); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to return borrow record id=" + recordId + " actorId=" + actor.getId(), ex); @@ -186,23 +186,23 @@ public class BorrowingServiceImpl implements BorrowingService { return ServiceResult.failure(DENIED_MESSAGE); } if (recordId <= 0) { - return ServiceResult.failure("Select a valid borrowing record."); + return ServiceResult.failure("请选择有效的借阅记录。"); } try { return transactionExecutor.execute(connection -> { Optional recordResult = borrowRecordDao.findByIdForUpdate(connection, recordId); if (!recordResult.isPresent()) { - return ServiceResult.failure("Borrowing record was not found."); + return ServiceResult.failure("未找到借阅记录。"); } BorrowRecord record = recordResult.get(); Map errors = validateActiveLoan(record); if (record.getRenewalCount() >= MAX_RENEWALS) { - errors.put("renewalCount", "This loan has already reached the renewal limit."); + errors.put("renewalCount", "该借阅已达到续借次数上限。"); } if (!errors.isEmpty()) { - return ServiceResult.validationFailure("Borrowing record cannot be renewed.", errors); + return ServiceResult.validationFailure("借阅记录不能续借。", errors); } LocalDateTime currentDueAt = record.getDueAt() == null ? now() : record.getDueAt(); @@ -212,7 +212,7 @@ public class BorrowingServiceImpl implements BorrowingService { } LOGGER.info("Renewed borrow recordId=" + recordId + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Loan renewed."); + return ServiceResult.success(null, "借阅已续借。"); }); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to renew borrow record id=" + recordId + " actorId=" + actor.getId(), ex); @@ -229,7 +229,7 @@ public class BorrowingServiceImpl implements BorrowingService { try { Optional readerResult = borrowRecordDao.findReaderByUserId(actor.getId()); if (!readerResult.isPresent()) { - return ServiceResult.success(Collections.emptyList(), "No reader profile is linked to your account."); + return ServiceResult.success(Collections.emptyList(), "您的账户未关联读者档案。"); } return ServiceResult.success(borrowRecordDao.findByReaderId(readerResult.get().getId())); @@ -246,16 +246,16 @@ public class BorrowingServiceImpl implements BorrowingService { private void validateBorrowEligibility(Map errors, Reader reader, Book book, java.sql.Connection connection) { if (reader.getStatus() != ReaderStatus.ACTIVE) { - errors.put("readerIdentifier", "Reader must be active to borrow books."); + errors.put("readerIdentifier", "读者状态必须为正常才能借阅图书。"); } int activeLoans = borrowRecordDao.countActiveByReaderId(connection, reader.getId()); if (activeLoans >= reader.getMaxBorrowCount()) { - errors.put("readerIdentifier", "Reader has reached the active borrowing limit."); + errors.put("readerIdentifier", "读者已达到在借数量上限。"); } if (book.getStatus() != BookStatus.AVAILABLE) { - errors.put("bookIdentifier", "Book status does not allow borrowing."); + errors.put("bookIdentifier", "图书状态不允许借阅。"); } else if (book.getAvailableCopies() <= 0) { - errors.put("bookIdentifier", "No available copies remain for this book."); + errors.put("bookIdentifier", "该图书没有可借副本。"); } } @@ -270,7 +270,7 @@ public class BorrowingServiceImpl implements BorrowingService { try { BorrowRecordStatus.fromCode(statusCode); } catch (IllegalArgumentException ex) { - errors.put("status", "Select a valid borrowing status."); + errors.put("status", "请选择有效的借阅状态。"); } } return errors; @@ -278,26 +278,26 @@ public class BorrowingServiceImpl implements BorrowingService { private Map validateBorrowIdentifiers(String readerIdentifier, String bookIdentifier) { Map errors = new LinkedHashMap<>(); - requireLength(errors, "readerIdentifier", readerIdentifier, "Reader ID", 64); - requireLength(errors, "bookIdentifier", bookIdentifier, "Book ID", 64); + requireLength(errors, "readerIdentifier", readerIdentifier, "读者编号", 64); + requireLength(errors, "bookIdentifier", bookIdentifier, "图书编号", 64); return errors; } private Map validateActiveLoan(BorrowRecord record) { Map errors = new LinkedHashMap<>(); if (record.getStatus() != BorrowRecordStatus.ACTIVE || record.getReturnedAt() != null) { - errors.put("status", "Only active loans can use this action."); + errors.put("status", "只有借阅中的记录可以执行此操作。"); } return errors; } private void requireLength(Map errors, String field, String value, String label, int maxLength) { if (value == null || value.isEmpty()) { - errors.put(field, label + " is required."); + errors.put(field, "请填写" + label + "。"); return; } if (value.length() > maxLength) { - errors.put(field, label + " must be " + maxLength + " characters or fewer."); + errors.put(field, label + "不能超过 " + maxLength + " 个字符。"); } } diff --git a/src/main/java/com/mzh/library/service/impl/ReaderServiceImpl.java b/src/main/java/com/mzh/library/service/impl/ReaderServiceImpl.java index 48e8e31..002774f 100644 --- a/src/main/java/com/mzh/library/service/impl/ReaderServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/ReaderServiceImpl.java @@ -22,10 +22,10 @@ import java.util.logging.Logger; public class ReaderServiceImpl implements ReaderService { private static final Logger LOGGER = Logger.getLogger(ReaderServiceImpl.class.getName()); private static final String UNAVAILABLE_MESSAGE = - "Reader service is temporarily unavailable. Please try again later."; - private static final String VALIDATION_MESSAGE = "Please correct the highlighted reader fields."; - private static final String SEARCH_VALIDATION_MESSAGE = "Please correct the reader search filters."; - private static final String DENIED_MESSAGE = "You do not have permission to manage readers."; + "读者服务暂时不可用,请稍后重试。"; + private static final String VALIDATION_MESSAGE = "请修正高亮的读者字段。"; + private static final String SEARCH_VALIDATION_MESSAGE = "请修正读者检索筛选条件。"; + private static final String DENIED_MESSAGE = "您无权管理读者。"; private static final int MAX_BORROW_LIMIT = 50; private static final Pattern PHONE_PATTERN = Pattern.compile("(?=.*\\d)[0-9+()\\-\\s]{6,32}"); private static final Pattern EMAIL_PATTERN = Pattern.compile("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"); @@ -61,7 +61,7 @@ public class ReaderServiceImpl implements ReaderService { @Override public ServiceResult> findReader(long id) { if (id <= 0) { - return ServiceResult.failure("Select a valid reader."); + return ServiceResult.failure("请选择有效的读者。"); } try { @@ -86,17 +86,17 @@ public class ReaderServiceImpl implements ReaderService { try { if (readerDao.findByIdentifier(reader.getIdentifier()).isPresent()) { - errors.put("identifier", "Reader identifier is already in use."); + errors.put("identifier", "读者编号已被使用。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } if (reader.getUserId() != null && readerDao.findByUserId(reader.getUserId()).isPresent()) { - errors.put("userId", "Linked account is already assigned to a reader profile."); + errors.put("userId", "关联账户已绑定到其他读者档案。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } long id = readerDao.create(reader); LOGGER.info("Created reader id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(id, "Reader profile created."); + return ServiceResult.success(id, "读者档案已创建。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to create reader actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -118,23 +118,23 @@ public class ReaderServiceImpl implements ReaderService { try { Optional existingWithIdentifier = readerDao.findByIdentifier(reader.getIdentifier()); if (existingWithIdentifier.isPresent() && existingWithIdentifier.get().getId() != reader.getId()) { - errors.put("identifier", "Reader identifier is already in use."); + errors.put("identifier", "读者编号已被使用。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } if (reader.getUserId() != null) { Optional existingWithUser = readerDao.findByUserId(reader.getUserId()); if (existingWithUser.isPresent() && existingWithUser.get().getId() != reader.getId()) { - errors.put("userId", "Linked account is already assigned to a reader profile."); + errors.put("userId", "关联账户已绑定到其他读者档案。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } } if (!readerDao.update(reader)) { - return ServiceResult.failure("Reader profile was not found."); + return ServiceResult.failure("未找到读者档案。"); } LOGGER.info("Updated reader id=" + reader.getId() + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Reader profile updated."); + return ServiceResult.success(null, "读者档案已更新。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to update reader id=" + reader.getId() + " actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -147,16 +147,16 @@ public class ReaderServiceImpl implements ReaderService { return ServiceResult.failure(DENIED_MESSAGE); } if (id <= 0) { - return ServiceResult.failure("Select a valid reader."); + return ServiceResult.failure("请选择有效的读者。"); } try { if (!readerDao.deactivate(id)) { - return ServiceResult.failure("Reader profile was not found."); + return ServiceResult.failure("未找到读者档案。"); } LOGGER.info("Deactivated reader id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(null, "Reader profile deactivated."); + return ServiceResult.success(null, "读者档案已停用。"); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to deactivate reader id=" + id + " actorId=" + actor.getId(), ex); return ServiceResult.failure(UNAVAILABLE_MESSAGE); @@ -183,7 +183,7 @@ public class ReaderServiceImpl implements ReaderService { try { criteria.setStatusCode(ReaderStatus.fromCode(criteria.getStatusCode()).getCode()); } catch (IllegalArgumentException ex) { - errors.put("status", "Select a valid status."); + errors.put("status", "请选择有效的状态。"); } } return errors; @@ -192,24 +192,24 @@ public class ReaderServiceImpl implements ReaderService { private Map validate(Reader reader, boolean requireId) { Map errors = new LinkedHashMap<>(); if (reader == null) { - errors.put("reader", "Reader details are required."); + errors.put("reader", "请填写读者详情。"); return errors; } if (requireId && reader.getId() <= 0) { - errors.put("id", "Select a valid reader."); + errors.put("id", "请选择有效的读者。"); } - requireLength(errors, "identifier", reader.getIdentifier(), "Reader identifier", 64); - requireLength(errors, "fullName", reader.getFullName(), "Full name", 100); + requireLength(errors, "identifier", reader.getIdentifier(), "读者编号", 64); + requireLength(errors, "fullName", reader.getFullName(), "姓名", 100); if (reader.getUserId() != null && reader.getUserId() <= 0) { - errors.put("userId", "Linked account ID must be positive."); + errors.put("userId", "关联账户 ID 必须为正数。"); } validateContact(errors, reader); if (reader.getStatus() == null) { - errors.put("status", "Select a status."); + errors.put("status", "请选择状态。"); } if (reader.getMaxBorrowCount() < 1 || reader.getMaxBorrowCount() > MAX_BORROW_LIMIT) { - errors.put("maxBorrowCount", "Max borrow count must be between 1 and " + MAX_BORROW_LIMIT + "."); + errors.put("maxBorrowCount", "最大借阅数量必须在 1 到 " + MAX_BORROW_LIMIT + " 之间。"); } return errors; } @@ -218,24 +218,24 @@ public class ReaderServiceImpl implements ReaderService { String phone = reader.getPhone(); String email = reader.getEmail(); if ((phone == null || phone.isEmpty()) && (email == null || email.isEmpty())) { - errors.put("phone", "Phone or email is required."); + errors.put("phone", "请填写电话或邮箱。"); return; } if (phone != null && !phone.isEmpty() && !PHONE_PATTERN.matcher(phone).matches()) { - errors.put("phone", "Phone must include a digit and use 6 to 32 digits or common phone symbols."); + errors.put("phone", "电话必须包含数字,并使用 6 到 32 位数字或常见电话符号。"); } if (email != null && !email.isEmpty() && !EMAIL_PATTERN.matcher(email).matches()) { - errors.put("email", "Email must be a valid address."); + errors.put("email", "邮箱格式不正确。"); } } private void requireLength(Map errors, String field, String value, String label, int maxLength) { if (value == null || value.isEmpty()) { - errors.put(field, label + " is required."); + errors.put(field, "请填写" + label + "。"); return; } if (value.length() > maxLength) { - errors.put(field, label + " must be " + maxLength + " characters or fewer."); + errors.put(field, label + "不能超过 " + maxLength + " 个字符。"); } } diff --git a/src/main/java/com/mzh/library/service/impl/ReportServiceImpl.java b/src/main/java/com/mzh/library/service/impl/ReportServiceImpl.java index 9a6dc77..45eb393 100644 --- a/src/main/java/com/mzh/library/service/impl/ReportServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/ReportServiceImpl.java @@ -15,8 +15,8 @@ import java.util.logging.Logger; public class ReportServiceImpl implements ReportService { private static final Logger LOGGER = Logger.getLogger(ReportServiceImpl.class.getName()); private static final String UNAVAILABLE_MESSAGE = - "Report service is temporarily unavailable. Please try again later."; - private static final String DENIED_MESSAGE = "You do not have permission to view reports."; + "报表服务暂时不可用,请稍后重试。"; + private static final String DENIED_MESSAGE = "您无权查看报表。"; private static final int POPULAR_BOOK_LIMIT = 10; private final ReportDao reportDao; diff --git a/src/main/java/com/mzh/library/service/impl/SystemLogServiceImpl.java b/src/main/java/com/mzh/library/service/impl/SystemLogServiceImpl.java index 3b7f926..394c2cb 100644 --- a/src/main/java/com/mzh/library/service/impl/SystemLogServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/SystemLogServiceImpl.java @@ -20,9 +20,9 @@ import java.util.logging.Logger; public class SystemLogServiceImpl implements SystemLogService { private static final Logger LOGGER = Logger.getLogger(SystemLogServiceImpl.class.getName()); private static final String UNAVAILABLE_MESSAGE = - "System log service is temporarily unavailable. Please try again later."; - private static final String DENIED_MESSAGE = "You do not have permission to view system logs."; - private static final String VALIDATION_MESSAGE = "Please correct the system log search filters."; + "系统日志服务暂时不可用,请稍后重试。"; + private static final String DENIED_MESSAGE = "您无权查看系统日志。"; + private static final String VALIDATION_MESSAGE = "请修正系统日志检索筛选条件。"; private final SystemLogDao systemLogDao; private final PermissionPolicy permissionPolicy; @@ -62,18 +62,18 @@ public class SystemLogServiceImpl implements SystemLogService { private Map validate(SystemLogSearchCriteria criteria) { Map errors = new LinkedHashMap<>(); if (criteria.getOperationType().length() > 64) { - errors.put("operationType", "Operation type must be 64 characters or fewer."); + errors.put("operationType", "操作类型不能超过 64 个字符。"); } if (criteria.getKeyword().length() > 120) { - errors.put("keyword", "Keyword must be 120 characters or fewer."); + errors.put("keyword", "关键词不能超过 120 个字符。"); } - parseDate(criteria.getCreatedFromText(), "createdFrom", "Start date", errors, criteria, true); - parseDate(criteria.getCreatedToText(), "createdTo", "End date", errors, criteria, false); + parseDate(criteria.getCreatedFromText(), "createdFrom", "开始日期", errors, criteria, true); + parseDate(criteria.getCreatedToText(), "createdTo", "结束日期", errors, criteria, false); if (criteria.getCreatedFrom() != null && criteria.getCreatedTo() != null && criteria.getCreatedFrom().isAfter(criteria.getCreatedTo())) { - errors.put("createdTo", "End date must be on or after start date."); + errors.put("createdTo", "结束日期必须晚于或等于开始日期。"); } return errors; } @@ -91,7 +91,7 @@ public class SystemLogServiceImpl implements SystemLogService { criteria.setCreatedTo(parsed); } } catch (DateTimeParseException ex) { - errors.put(field, label + " must use YYYY-MM-DD."); + errors.put(field, label + "必须使用 YYYY-MM-DD 格式。"); } } diff --git a/src/main/java/com/mzh/library/service/impl/UserAccountServiceImpl.java b/src/main/java/com/mzh/library/service/impl/UserAccountServiceImpl.java index c1150b1..12d3984 100644 --- a/src/main/java/com/mzh/library/service/impl/UserAccountServiceImpl.java +++ b/src/main/java/com/mzh/library/service/impl/UserAccountServiceImpl.java @@ -30,12 +30,12 @@ public class UserAccountServiceImpl implements UserAccountService { private static final Logger LOGGER = Logger.getLogger(UserAccountServiceImpl.class.getName()); private static final String UNAVAILABLE_MESSAGE = - "User management service is temporarily unavailable. Please try again later."; - private static final String VALIDATION_MESSAGE = "Please correct the highlighted account fields."; - private static final String SEARCH_VALIDATION_MESSAGE = "Please correct the account search filters."; - private static final String DENIED_MESSAGE = "You do not have permission to manage users."; - private static final String SELF_DEACTIVATE_MESSAGE = "You cannot deactivate your own administrator account."; - private static final String SELF_ROLE_MESSAGE = "You cannot change your own administrator role."; + "用户管理服务暂时不可用,请稍后重试。"; + private static final String VALIDATION_MESSAGE = "请修正高亮的账户字段。"; + private static final String SEARCH_VALIDATION_MESSAGE = "请修正账户检索筛选条件。"; + private static final String DENIED_MESSAGE = "您无权管理用户。"; + private static final String SELF_DEACTIVATE_MESSAGE = "不能停用您自己的管理员账户。"; + private static final String SELF_ROLE_MESSAGE = "不能修改您自己的管理员角色。"; private final UserAccountDao userAccountDao; private final SystemLogDao systemLogDao; @@ -80,7 +80,7 @@ public class UserAccountServiceImpl implements UserAccountService { return ServiceResult.failure(DENIED_MESSAGE); } if (id <= 0) { - return ServiceResult.failure("Select a valid user account."); + return ServiceResult.failure("请选择有效的用户账户。"); } try { @@ -105,7 +105,7 @@ public class UserAccountServiceImpl implements UserAccountService { try { if (userAccountDao.findByUsername(user.getUsername()).isPresent()) { - errors.put("username", "Username is already in use."); + errors.put("username", "用户名已被使用。"); return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors); } @@ -113,10 +113,10 @@ public class UserAccountServiceImpl implements UserAccountService { return transactionExecutor.execute(connection -> { long id = userAccountDao.create(connection, user); systemLogDao.create(connection, auditLog(actor, "user.create", id, - "Created account username=" + user.getUsername() + " role=" + user.getRole().getCode(), + "创建账户:用户名=" + user.getUsername() + ",角色=" + user.getRole().getDisplayName(), requestIp)); LOGGER.info("Created user id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(id, "User account created."); + return ServiceResult.success(id, "用户账户已创建。"); }); } catch (DaoException | IllegalStateException ex) { LOGGER.log(Level.SEVERE, "Unable to create user actorId=" + actor.getId() @@ -140,7 +140,7 @@ public class UserAccountServiceImpl implements UserAccountService { try { Optional existingResult = userAccountDao.findById(user.getId()); if (!existingResult.isPresent()) { - return ServiceResult.failure("User account was not found."); + return ServiceResult.failure("未找到用户账户。"); } protectCurrentAdministrator(actor, user, errors); @@ -158,15 +158,15 @@ public class UserAccountServiceImpl implements UserAccountService { final boolean passwordChanged = updatePassword; return transactionExecutor.execute(connection -> { if (!userAccountDao.update(connection, user, passwordChanged)) { - return ServiceResult.failure("User account was not found."); + return ServiceResult.failure("未找到用户账户。"); } systemLogDao.create(connection, auditLog(actor, "user.update", user.getId(), - "Updated account username=" + user.getUsername() + " role=" + user.getRole().getCode() - + " active=" + user.isActive() - + (passwordChanged ? " passwordReset=true" : ""), + "更新账户:用户名=" + user.getUsername() + ",角色=" + user.getRole().getDisplayName() + + ",状态=" + (user.isActive() ? "启用" : "停用") + + (passwordChanged ? ",已重置密码" : ""), requestIp)); LOGGER.info("Updated user id=" + user.getId() + " actorId=" + actor.getId()); - return ServiceResult.success(null, "User account updated."); + return ServiceResult.success(null, "用户账户已更新。"); }); } catch (DaoException | IllegalStateException ex) { LOGGER.log(Level.SEVERE, "Unable to update user id=" + user.getId() + " actorId=" + actor.getId(), ex); @@ -180,7 +180,7 @@ public class UserAccountServiceImpl implements UserAccountService { return ServiceResult.failure(DENIED_MESSAGE); } if (id <= 0) { - return ServiceResult.failure("Select a valid user account."); + return ServiceResult.failure("请选择有效的用户账户。"); } if (actor.getId() == id) { Map errors = new LinkedHashMap<>(); @@ -191,20 +191,20 @@ public class UserAccountServiceImpl implements UserAccountService { try { Optional existingResult = userAccountDao.findById(id); if (!existingResult.isPresent()) { - return ServiceResult.failure("User account was not found."); + return ServiceResult.failure("未找到用户账户。"); } User user = existingResult.get(); user.setActive(false); return transactionExecutor.execute(connection -> { if (!userAccountDao.update(connection, user, false)) { - return ServiceResult.failure("User account was not found."); + return ServiceResult.failure("未找到用户账户。"); } systemLogDao.create(connection, auditLog(actor, "user.deactivate", id, - "Deactivated account username=" + user.getUsername(), + "停用账户:用户名=" + user.getUsername(), requestIp)); LOGGER.info("Deactivated user id=" + id + " actorId=" + actor.getId()); - return ServiceResult.success(null, "User account deactivated."); + return ServiceResult.success(null, "用户账户已停用。"); }); } catch (DaoException ex) { LOGGER.log(Level.SEVERE, "Unable to deactivate user id=" + id + " actorId=" + actor.getId(), ex); @@ -218,7 +218,7 @@ public class UserAccountServiceImpl implements UserAccountService { try { criteria.setRoleCode(Role.fromCode(criteria.getRoleCode()).getCode()); } catch (IllegalArgumentException ex) { - errors.put("role", "Select a valid role."); + errors.put("role", "请选择有效的角色。"); } } @@ -226,7 +226,7 @@ public class UserAccountServiceImpl implements UserAccountService { if (!activeStatus.isEmpty() && !UserSearchCriteria.ACTIVE_STATUS.equals(activeStatus) && !UserSearchCriteria.INACTIVE_STATUS.equals(activeStatus)) { - errors.put("active", "Select a valid active state."); + errors.put("active", "请选择有效的启用状态。"); } return errors; } @@ -234,19 +234,19 @@ public class UserAccountServiceImpl implements UserAccountService { private Map validateUser(User user, boolean requireId, String password, boolean requirePassword) { Map errors = new LinkedHashMap<>(); if (user == null) { - errors.put("user", "User account details are required."); + errors.put("user", "请填写用户账户详情。"); return errors; } if (requireId && user.getId() <= 0) { - errors.put("id", "Select a valid user account."); + errors.put("id", "请选择有效的用户账户。"); } if (!requireId) { - requireLength(errors, "username", user.getUsername(), "Username", 64); + requireLength(errors, "username", user.getUsername(), "用户名", 64); } - requireLength(errors, "displayName", user.getDisplayName(), "Display name", 100); + requireLength(errors, "displayName", user.getDisplayName(), "显示名称", 100); if (user.getRole() == null) { - errors.put("role", "Select a role."); + errors.put("role", "请选择角色。"); } validatePassword(errors, password, requirePassword); return errors; @@ -256,12 +256,12 @@ public class UserAccountServiceImpl implements UserAccountService { String trimmed = password == null ? "" : password.trim(); if (trimmed.isEmpty()) { if (required) { - errors.put("password", "Password is required."); + errors.put("password", "请填写密码。"); } return; } if (password.length() > 128) { - errors.put("password", "Password must be 128 characters or fewer."); + errors.put("password", "密码不能超过 128 个字符。"); } } @@ -279,11 +279,11 @@ public class UserAccountServiceImpl implements UserAccountService { private void requireLength(Map errors, String field, String value, String label, int maxLength) { if (value == null || value.isEmpty()) { - errors.put(field, label + " is required."); + errors.put(field, "请填写" + label + "。"); return; } if (value.length() > maxLength) { - errors.put(field, label + " must be " + maxLength + " characters or fewer."); + errors.put(field, label + "不能超过 " + maxLength + " 个字符。"); } } diff --git a/src/main/webapp/WEB-INF/jsp/admin/users/form.jsp b/src/main/webapp/WEB-INF/jsp/admin/users/form.jsp index 61be306..4de884d 100644 --- a/src/main/webapp/WEB-INF/jsp/admin/users/form.jsp +++ b/src/main/webapp/WEB-INF/jsp/admin/users/form.jsp @@ -2,18 +2,18 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - <c:out value="${formTitle}" /> - MZH Library + <c:out value="${formTitle}" /> - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Administration

+

系统管理

@@ -36,7 +36,7 @@
- + @@ -51,7 +51,7 @@
- + @@ -60,9 +60,9 @@
- + @@ -92,8 +92,8 @@
@@ -111,8 +111,8 @@
- - Cancel + + 取消
diff --git a/src/main/webapp/WEB-INF/jsp/admin/users/manage.jsp b/src/main/webapp/WEB-INF/jsp/admin/users/manage.jsp index bf2a62d..f12aff3 100644 --- a/src/main/webapp/WEB-INF/jsp/admin/users/manage.jsp +++ b/src/main/webapp/WEB-INF/jsp/admin/users/manage.jsp @@ -2,11 +2,11 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - Manage Users - MZH Library + 用户管理 - MZH 图书馆 @@ -14,11 +14,11 @@
-

Administration

-

Manage users

-

Create, update, deactivate, and review administrator, librarian, and reader accounts.

+

系统管理

+

管理用户

+

创建、更新、停用和查看管理员、馆员与读者账户。

- New user + 新增用户
@@ -32,10 +32,10 @@ -
+
- + @@ -43,9 +43,9 @@
- + - - - + + +
- - Clear + + 清空
-

User accounts

+

用户账户

-

No user accounts match the current filters.

+

没有符合当前筛选条件的用户账户。

- - - - - - - + + + + + + + @@ -110,17 +110,17 @@
UsernameDisplay nameRoleStateCreatedUpdatedActions用户名显示名称角色状态创建时间更新时间操作
Edit + href="${pageContext.request.contextPath}/admin/users/edit?id=${account.id}">编辑 - +
+ onsubmit="return confirm('确定停用这个用户账户吗?');"> - +
diff --git a/src/main/webapp/WEB-INF/jsp/auth/login.jsp b/src/main/webapp/WEB-INF/jsp/auth/login.jsp index 7f03fbc..ec0e189 100644 --- a/src/main/webapp/WEB-INF/jsp/auth/login.jsp +++ b/src/main/webapp/WEB-INF/jsp/auth/login.jsp @@ -2,11 +2,11 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - Login - MZH Library + 登录 - MZH 图书馆 @@ -14,8 +14,8 @@
diff --git a/src/main/webapp/WEB-INF/jsp/auth/unauthorized.jsp b/src/main/webapp/WEB-INF/jsp/auth/unauthorized.jsp index da2ab8b..e200ba6 100644 --- a/src/main/webapp/WEB-INF/jsp/auth/unauthorized.jsp +++ b/src/main/webapp/WEB-INF/jsp/auth/unauthorized.jsp @@ -1,27 +1,27 @@ <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - + - Unauthorized - MZH Library + 无权限 - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Access denied

+

无权访问

- You do not have permission to access this page. + 您无权访问此页面。

- Back to dashboard + 返回控制台
diff --git a/src/main/webapp/WEB-INF/jsp/books/catalog.jsp b/src/main/webapp/WEB-INF/jsp/books/catalog.jsp index d1f4976..1712e70 100644 --- a/src/main/webapp/WEB-INF/jsp/books/catalog.jsp +++ b/src/main/webapp/WEB-INF/jsp/books/catalog.jsp @@ -2,20 +2,20 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - Catalog - MZH Library + 馆藏检索 - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Catalog

-

Book catalog

-

Search the library collection by identifier, title, author, or category.

+

馆藏

+

馆藏检索

+

按图书编号、书名、作者或分类检索馆藏。

@@ -24,27 +24,27 @@
-
+
- +
- +
- +
- + - - - - - - + + + + + + diff --git a/src/main/webapp/WEB-INF/jsp/books/categories.jsp b/src/main/webapp/WEB-INF/jsp/books/categories.jsp index 65dedc0..6298690 100644 --- a/src/main/webapp/WEB-INF/jsp/books/categories.jsp +++ b/src/main/webapp/WEB-INF/jsp/books/categories.jsp @@ -1,11 +1,11 @@ <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - + - Manage Categories - MZH Library + 分类管理 - MZH 图书馆 @@ -13,13 +13,13 @@
-

Book Management

-

Manage categories

-

Maintain catalog groupings used by book records and search filters.

+

图书管理

+

管理分类

+

维护图书记录和检索筛选使用的馆藏分组。

@@ -35,19 +35,19 @@
-

Category records

+

分类记录

-

No categories have been created yet.

+

尚未创建分类。

Book IDTitleAuthorCategoryCopiesStatus图书编号书名作者分类馆藏数量状态
- - - + + + @@ -57,7 +57,7 @@ diff --git a/src/main/webapp/WEB-INF/jsp/books/category-form.jsp b/src/main/webapp/WEB-INF/jsp/books/category-form.jsp index b418be4..ae11a4b 100644 --- a/src/main/webapp/WEB-INF/jsp/books/category-form.jsp +++ b/src/main/webapp/WEB-INF/jsp/books/category-form.jsp @@ -2,18 +2,18 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - <c:out value="${formTitle}" /> - MZH Library + <c:out value="${formTitle}" /> - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Book Management

+

图书管理

@@ -33,7 +33,7 @@
- + @@ -41,7 +41,7 @@
- + @@ -56,8 +56,8 @@
- - Cancel + + 取消
diff --git a/src/main/webapp/WEB-INF/jsp/books/form.jsp b/src/main/webapp/WEB-INF/jsp/books/form.jsp index d612cf2..7bb8b99 100644 --- a/src/main/webapp/WEB-INF/jsp/books/form.jsp +++ b/src/main/webapp/WEB-INF/jsp/books/form.jsp @@ -2,18 +2,18 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - <c:out value="${formTitle}" /> - MZH Library + <c:out value="${formTitle}" /> - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Book Management

+

图书管理

@@ -38,7 +38,7 @@
- + @@ -46,7 +46,7 @@
- + @@ -54,7 +54,7 @@
- + @@ -62,9 +62,9 @@
- + @@ -85,7 +85,7 @@
- + @@ -93,9 +93,9 @@
- +
- +
- +
- +
NameDescriptionActions名称说明操作
- No description + 无说明 @@ -67,12 +67,12 @@
Edit + href="${pageContext.request.contextPath}/book-categories/edit?id=${category.id}">编辑 + onsubmit="return confirm('确定删除这个分类吗?');"> - +
- - - - - - - + + + + + + + @@ -108,12 +108,12 @@ diff --git a/src/main/webapp/WEB-INF/jsp/borrowing/form.jsp b/src/main/webapp/WEB-INF/jsp/borrowing/form.jsp index d5a5e54..33c35b8 100644 --- a/src/main/webapp/WEB-INF/jsp/borrowing/form.jsp +++ b/src/main/webapp/WEB-INF/jsp/borrowing/form.jsp @@ -2,19 +2,19 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - New Borrow - MZH Library + 新增借阅 - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Borrowing Management

-

New borrow

+

借阅管理

+

新增借阅

diff --git a/src/main/webapp/WEB-INF/jsp/borrowing/manage.jsp b/src/main/webapp/WEB-INF/jsp/borrowing/manage.jsp index 285d189..b3ecca0 100644 --- a/src/main/webapp/WEB-INF/jsp/borrowing/manage.jsp +++ b/src/main/webapp/WEB-INF/jsp/borrowing/manage.jsp @@ -2,11 +2,11 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - Borrowing Management - MZH Library + 借阅管理 - MZH 图书馆 @@ -14,11 +14,11 @@
-

Borrowing Management

-

Manage borrowing

-

Create borrow records, process returns, renew active loans, and review overdue items.

+

借阅管理

+

管理借阅

+

创建借阅记录、处理归还、续借有效借阅并查看逾期项目。

- New borrow + 新增借阅
@@ -32,31 +32,31 @@ -
+
- +
- +
- + @@ -64,30 +64,30 @@
- - Clear + + 清空
-

Borrowing records

+

借阅记录

-

No borrowing records match the current filters.

+

没有符合当前筛选条件的借阅记录。

Book IDTitleAuthorCategoryCopiesStatusActions图书编号书名作者分类馆藏数量状态操作
Edit + href="${pageContext.request.contextPath}/books/edit?id=${book.id}">编辑
+ onsubmit="return confirm('确定删除这条图书记录吗?');"> - +
- - - - - - - - + + + + + + + + @@ -108,7 +108,7 @@ - Not returned + 未归还 @@ -123,22 +123,22 @@
+ onsubmit="return confirm('确定归还这本书吗?');"> - +
+ onsubmit="return confirm('确定续借这条记录吗?');"> - +
- Complete + 已完成 diff --git a/src/main/webapp/WEB-INF/jsp/common/header.jspf b/src/main/webapp/WEB-INF/jsp/common/header.jspf index 71ac742..05b9225 100644 --- a/src/main/webapp/WEB-INF/jsp/common/header.jspf +++ b/src/main/webapp/WEB-INF/jsp/common/header.jspf @@ -1,31 +1,31 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- MZH Library + MZH 图书馆 -
diff --git a/src/main/webapp/WEB-INF/jsp/dashboard.jsp b/src/main/webapp/WEB-INF/jsp/dashboard.jsp index 80d716b..dde32f9 100644 --- a/src/main/webapp/WEB-INF/jsp/dashboard.jsp +++ b/src/main/webapp/WEB-INF/jsp/dashboard.jsp @@ -1,11 +1,11 @@ <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - + - Dashboard - MZH Library + 控制台 - MZH 图书馆 @@ -15,86 +15,86 @@

-

Dashboard

-

Signed in as .

+

控制台

+

当前登录:

-
+
-

Administration

-

Account, role, permission, and system-maintenance entry point.

- Open +

系统管理

+

账户、角色、权限和系统维护入口。

+ 打开
-

User Management

-

Create, update, deactivate, and review login accounts.

- Open +

用户管理

+

创建、更新、停用和查看登录账户。

+ 打开
-

System Logs

-

Review read-only audit entries for account and maintenance actions.

- Open +

系统日志

+

查看账户与维护操作的只读审计记录。

+ 打开
-

Librarian Workspace

-

Book, reader, borrowing, return, renewal, and overdue entry point.

- Open +

馆员工作台

+

图书、读者、借阅、归还、续借和逾期处理入口。

+ 打开
-

Book Management

-

Create, update, delete, and review book inventory records.

- Open +

图书管理

+

创建、更新、删除和查看图书库存记录。

+ 打开
-

Category Maintenance

-

Maintain catalog categories used by book records and search filters.

- Open +

分类维护

+

维护图书记录和检索筛选使用的馆藏分类。

+ 打开
-

Reader Management

-

Create, update, deactivate, and review reader eligibility records.

- Open +

读者管理

+

创建、更新、停用和查看读者借阅资格记录。

+ 打开
-

Borrowing Management

-

Create loans, process returns, renew active records, and review overdue items.

- Open +

借阅管理

+

创建借阅、处理归还、续借有效记录并查看逾期项目。

+ 打开
-

Report Center

-

Review inventory health, borrowing counts, overdue records, and popular books.

- Open +

报表中心

+

查看库存状况、借阅统计、逾期记录和热门图书。

+ 打开
-

Book Catalog

-

Search books by title, author, category, or book identifier.

- Search +

馆藏检索

+

按书名、作者、分类或图书编号检索图书。

+ 检索
-

Reader Center

-

Reader self-service entry point for catalog access and loan history.

- Open +

读者中心

+

读者自助访问馆藏和借阅历史的入口。

+ 打开
-

My Loan History

-

Review your active, returned, and overdue borrowing records.

- Open +

我的借阅历史

+

查看您的在借、已还和逾期借阅记录。

+ 打开
diff --git a/src/main/webapp/WEB-INF/jsp/maintenance/system-logs.jsp b/src/main/webapp/WEB-INF/jsp/maintenance/system-logs.jsp index 078792d..62d1d27 100644 --- a/src/main/webapp/WEB-INF/jsp/maintenance/system-logs.jsp +++ b/src/main/webapp/WEB-INF/jsp/maintenance/system-logs.jsp @@ -2,11 +2,11 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - System Logs - MZH Library + 系统日志 - MZH 图书馆 @@ -14,9 +14,9 @@
-

System Maintenance

-

System logs

-

Review administrative account changes and maintenance audit records.

+

系统维护

+

系统日志

+

查看管理账户变更和维护审计记录。

@@ -26,17 +26,22 @@ -
+
- + @@ -59,7 +64,7 @@
- + @@ -68,7 +73,7 @@
- + @@ -76,29 +81,29 @@
- - Clear + + 清空
-

Log entries

+

日志记录

-

No system logs match the current filters.

+

没有符合当前筛选条件的系统日志。

ReaderBookBorrowedDueReturnedRenewalsStatusActions读者图书借出时间应还时间归还时间续借次数状态操作
/
- - - - - - - + + + + + + + @@ -111,9 +116,16 @@
- +
TimeOperatorOperationTargetResultIP addressDetail时间操作人操作目标结果IP 地址详情
- + + 创建用户 + 更新用户 + 停用用户 + + + + # diff --git a/src/main/webapp/WEB-INF/jsp/reader/loans.jsp b/src/main/webapp/WEB-INF/jsp/reader/loans.jsp index 0895a41..c9a0b32 100644 --- a/src/main/webapp/WEB-INF/jsp/reader/loans.jsp +++ b/src/main/webapp/WEB-INF/jsp/reader/loans.jsp @@ -1,11 +1,11 @@ <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - + - Loan History - MZH Library + 借阅历史 - MZH 图书馆 @@ -13,11 +13,11 @@
-

Reader Center

-

Loan history

-

Review your active, returned, and overdue borrowing records.

+

读者中心

+

借阅历史

+

查看您的在借、已还和逾期借阅记录。

- Search catalog + 检索馆藏
@@ -32,23 +32,23 @@
-

Borrowing records

+

借阅记录

-

No borrowing records are available for this account.

+

此账户暂无借阅记录。

- - - - - - - + + + + + + + @@ -63,7 +63,7 @@ - Not returned + 未归还 diff --git a/src/main/webapp/WEB-INF/jsp/readers/form.jsp b/src/main/webapp/WEB-INF/jsp/readers/form.jsp index 8030ef4..38d49b1 100644 --- a/src/main/webapp/WEB-INF/jsp/readers/form.jsp +++ b/src/main/webapp/WEB-INF/jsp/readers/form.jsp @@ -2,18 +2,18 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> - + - <c:out value="${formTitle}" /> - MZH Library + <c:out value="${formTitle}" /> - MZH 图书馆 <%@ include file="/WEB-INF/jsp/common/header.jspf" %>
-

Reader Management

+

读者管理

@@ -38,7 +38,7 @@
- + @@ -46,7 +46,7 @@
- + @@ -54,7 +54,7 @@
- + @@ -62,7 +62,7 @@
- + @@ -70,7 +70,7 @@
- + @@ -78,7 +78,7 @@
- + @@ -87,9 +87,9 @@
- +
- +
- +
- +
Book IDTitleBorrowedDueReturnedRenewalsStatus图书编号书名借出时间应还时间归还时间续借次数状态
- - - - - - - + + + + + + + @@ -105,7 +105,7 @@ - Unlinked + 未关联 @@ -117,12 +117,12 @@ diff --git a/src/main/webapp/WEB-INF/jsp/reports/dashboard.jsp b/src/main/webapp/WEB-INF/jsp/reports/dashboard.jsp index 0df1501..71551ed 100644 --- a/src/main/webapp/WEB-INF/jsp/reports/dashboard.jsp +++ b/src/main/webapp/WEB-INF/jsp/reports/dashboard.jsp @@ -1,11 +1,11 @@ <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - + - Reports - MZH Library + 报表 - MZH 图书馆 @@ -13,11 +13,11 @@
-

Reports

-

Report center

-

Review collection inventory, borrowing health, overdue loans, and popular books.

+

报表

+

报表中心

+

查看馆藏库存、借阅状况、逾期借阅和热门图书。

- Borrowing records + 借阅记录
@@ -27,59 +27,59 @@ -
+
-

Inventory

-

Total titles

+

库存

+

图书种类总数

-

Inventory

-

Total copies

+

库存

+

馆藏总册数

-

Inventory

-

Available copies

+

库存

+

可借册数

-

Attention

-

Unavailable or empty

+

需关注

+

不可借或无库存

-

Borrowing

-

Currently borrowed

+

借阅

+

当前借出

-

Borrowing

-

Returned records

+

借阅

+

已归还记录

-

Borrowing

-

Overdue loans

+

借阅

+

逾期借阅

-

Overdue list

+

逾期列表

-

No active overdue borrowing records.

+

当前没有逾期未还的借阅记录。

Reader IDNameContactAccountBorrow limitStatusActions读者编号姓名联系方式关联账户借阅上限状态操作
Edit + href="${pageContext.request.contextPath}/readers/edit?id=${reader.id}">编辑
+ onsubmit="return confirm('确定停用这个读者档案吗?');"> - +
- - - - + + + + @@ -96,7 +96,7 @@ @@ -109,19 +109,19 @@
- + -

No borrowing records are available for ranking yet.

+

暂无可用于排行的借阅记录。

ReaderBookDue dateOverdue days读者图书应还日期逾期天数
- days +
- - - + + + diff --git a/src/main/webapp/WEB-INF/jsp/role-home.jsp b/src/main/webapp/WEB-INF/jsp/role-home.jsp index f9b8ab4..6e8468b 100644 --- a/src/main/webapp/WEB-INF/jsp/role-home.jsp +++ b/src/main/webapp/WEB-INF/jsp/role-home.jsp @@ -1,11 +1,11 @@ <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - + - <c:out value="${areaName}" /> - MZH Library + <c:out value="${areaName}" /> - MZH 图书馆 @@ -17,67 +17,67 @@

- Back to dashboard + 返回控制台 -
+
-

Book Catalog

-

Search available collection records by title, author, category, or book identifier.

- Search catalog +

馆藏检索

+

按书名、作者、分类或图书编号检索可用馆藏记录。

+ 检索馆藏
-

User Management

-

Create, update, deactivate, and review login accounts.

- Manage users +

用户管理

+

创建、更新、停用和查看登录账户。

+ 管理用户
-

System Logs

-

Review read-only audit entries for account and maintenance actions.

- View logs +

系统日志

+

查看账户与维护操作的只读审计记录。

+ 查看日志
-

Book Management

-

Create, update, delete, and review inventory fields for book records.

- Manage books +

图书管理

+

创建、更新、删除和查看图书记录的库存字段。

+ 管理图书
-

Category Maintenance

-

Create, update, and retire catalog categories used by book records.

- Manage categories +

分类维护

+

创建、更新和停用图书记录使用的馆藏分类。

+ 管理分类
-

Reader Management

-

Create, update, deactivate, and review eligibility fields for reader records.

- Manage readers +

读者管理

+

创建、更新、停用和查看读者记录的资格字段。

+ 管理读者
-

Borrowing Management

-

Create loans, process returns, renew records, and review overdue items.

- Manage borrowing +

借阅管理

+

创建借阅、处理归还、续借记录并查看逾期项目。

+ 管理借阅
-

Report Center

-

Review inventory summaries, borrowing health, overdue lists, and popular books.

- View reports +

报表中心

+

查看库存摘要、借阅状况、逾期列表和热门图书。

+ 查看报表
-

My Loan History

-

Review active loans, returned records, renewal counts, and overdue status.

- View history +

我的借阅历史

+

查看在借记录、已还记录、续借次数和逾期状态。

+ 查看历史
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 87efc5f..406571e 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> - MZH Library Management + MZH 图书馆管理系统 CharacterEncodingFilter diff --git a/src/main/webapp/static/images/library-login.svg b/src/main/webapp/static/images/library-login.svg index 0d7e72c..3cdd2d7 100644 --- a/src/main/webapp/static/images/library-login.svg +++ b/src/main/webapp/static/images/library-login.svg @@ -1,4 +1,4 @@ - + diff --git a/src/test/java/com/mzh/library/service/AuthServiceCheck.java b/src/test/java/com/mzh/library/service/AuthServiceCheck.java index 738374e..ad403fc 100644 --- a/src/test/java/com/mzh/library/service/AuthServiceCheck.java +++ b/src/test/java/com/mzh/library/service/AuthServiceCheck.java @@ -14,10 +14,10 @@ import java.util.logging.Level; import java.util.logging.Logger; public final class AuthServiceCheck { - private static final String REQUIRED_MESSAGE = "Username and password are required."; - private static final String INVALID_MESSAGE = "Invalid username or password."; + private static final String REQUIRED_MESSAGE = "请输入用户名和密码。"; + private static final String INVALID_MESSAGE = "用户名或密码不正确。"; private static final String UNAVAILABLE_MESSAGE = - "Login service is temporarily unavailable. Please try again later."; + "登录服务暂时不可用,请稍后重试。"; private AuthServiceCheck() { } diff --git a/src/test/java/com/mzh/library/service/BookServiceCheck.java b/src/test/java/com/mzh/library/service/BookServiceCheck.java index eb44ff0..164bb60 100644 --- a/src/test/java/com/mzh/library/service/BookServiceCheck.java +++ b/src/test/java/com/mzh/library/service/BookServiceCheck.java @@ -22,7 +22,7 @@ import java.util.logging.Logger; public final class BookServiceCheck { private static final String UNAVAILABLE_MESSAGE = - "Book service is temporarily unavailable. Please try again later."; + "图书服务暂时不可用,请稍后重试。"; private BookServiceCheck() { } @@ -44,13 +44,13 @@ public final class BookServiceCheck { ServiceResult denied = service.createBook(reader, book(0L, "BK-1001", "Reader Write", "Test Author", 1L, 1, 1, BookStatus.AVAILABLE)); require(!denied.isSuccessful(), "reader write should fail"); - require("You do not have permission to manage books.".equals(denied.getMessage()), + require("您无权管理图书。".equals(denied.getMessage()), "reader write should return permission message"); ServiceResult deniedCategory = service.createCategory(reader, category(0L, "Reader Category", "Denied category")); require(!deniedCategory.isSuccessful(), "reader category create should fail"); - require("You do not have permission to manage books.".equals(deniedCategory.getMessage()), + require("您无权管理图书。".equals(deniedCategory.getMessage()), "reader category write should return permission message"); ServiceResult created = service.createBook(librarian, @@ -70,7 +70,7 @@ public final class BookServiceCheck { ServiceResult deleteUsedCategory = service.deleteCategory(librarian, 1L); require(!deleteUsedCategory.isSuccessful(), "used category delete should fail"); - require("Category is used by existing books and cannot be deleted.".equals(deleteUsedCategory.getMessage()), + require("该分类已被现有图书使用,不能删除。".equals(deleteUsedCategory.getMessage()), "used category delete should return a safe specific message"); require(deleteUsedCategory.getErrors().containsKey("category"), "used category delete should return a category-level field error"); diff --git a/src/test/java/com/mzh/library/service/BorrowingServiceCheck.java b/src/test/java/com/mzh/library/service/BorrowingServiceCheck.java index 9871fb5..ef9aae8 100644 --- a/src/test/java/com/mzh/library/service/BorrowingServiceCheck.java +++ b/src/test/java/com/mzh/library/service/BorrowingServiceCheck.java @@ -30,7 +30,7 @@ import java.util.logging.Logger; public final class BorrowingServiceCheck { private static final String UNAVAILABLE_MESSAGE = - "Borrowing service is temporarily unavailable. Please try again later."; + "借阅服务暂时不可用,请稍后重试。"; private static final Clock FIXED_CLOCK = Clock.fixed( Instant.parse("2026-04-27T00:00:00Z"), ZoneId.of("UTC") @@ -62,7 +62,7 @@ public final class BorrowingServiceCheck { ServiceResult denied = service.borrowBook(readerUser, "RD-1000", "BK-1000"); require(!denied.isSuccessful(), "reader should not manage borrow creation"); - require("You do not have permission to manage borrowing.".equals(denied.getMessage()), + require("您无权管理借阅。".equals(denied.getMessage()), "reader borrow creation should return permission message"); ServiceResult suspended = service.borrowBook(librarian, "RD-1001", "BK-1000"); @@ -96,7 +96,7 @@ public final class BorrowingServiceCheck { ServiceResult> staffHistory = service.listCurrentReaderHistory(administrator); require(!staffHistory.isSuccessful(), "staff should use management history, not reader loan history"); - require("You do not have permission to view loan history.".equals(staffHistory.getMessage()), + require("您无权查看借阅历史。".equals(staffHistory.getMessage()), "staff reader-history access should return permission message"); ServiceResult returned = service.returnBook(librarian, borrowedId); diff --git a/src/test/java/com/mzh/library/service/ReaderServiceCheck.java b/src/test/java/com/mzh/library/service/ReaderServiceCheck.java index 2af82b8..4c9551c 100644 --- a/src/test/java/com/mzh/library/service/ReaderServiceCheck.java +++ b/src/test/java/com/mzh/library/service/ReaderServiceCheck.java @@ -21,7 +21,7 @@ import java.util.logging.Logger; public final class ReaderServiceCheck { private static final String UNAVAILABLE_MESSAGE = - "Reader service is temporarily unavailable. Please try again later."; + "读者服务暂时不可用,请稍后重试。"; private ReaderServiceCheck() { } @@ -64,7 +64,7 @@ public final class ReaderServiceCheck { ServiceResult denied = service.createReader(readerUser, reader(0L, "RD-1006", null, "Reader Write", "13800000007", "", ReaderStatus.ACTIVE, 5)); require(!denied.isSuccessful(), "reader write should fail"); - require("You do not have permission to manage readers.".equals(denied.getMessage()), + require("您无权管理读者。".equals(denied.getMessage()), "reader write should return permission message"); ServiceResult created = service.createReader(librarian, diff --git a/src/test/java/com/mzh/library/service/ReportServiceCheck.java b/src/test/java/com/mzh/library/service/ReportServiceCheck.java index f78cf33..8111a85 100644 --- a/src/test/java/com/mzh/library/service/ReportServiceCheck.java +++ b/src/test/java/com/mzh/library/service/ReportServiceCheck.java @@ -21,9 +21,9 @@ import java.util.logging.Level; import java.util.logging.Logger; public final class ReportServiceCheck { - private static final String DENIED_MESSAGE = "You do not have permission to view reports."; + private static final String DENIED_MESSAGE = "您无权查看报表。"; private static final String UNAVAILABLE_MESSAGE = - "Report service is temporarily unavailable. Please try again later."; + "报表服务暂时不可用,请稍后重试。"; private ReportServiceCheck() { } diff --git a/src/test/java/com/mzh/library/service/SystemLogServiceCheck.java b/src/test/java/com/mzh/library/service/SystemLogServiceCheck.java index 200ef28..aa102a6 100644 --- a/src/test/java/com/mzh/library/service/SystemLogServiceCheck.java +++ b/src/test/java/com/mzh/library/service/SystemLogServiceCheck.java @@ -20,9 +20,9 @@ import java.util.logging.Level; import java.util.logging.Logger; public final class SystemLogServiceCheck { - private static final String DENIED_MESSAGE = "You do not have permission to view system logs."; + private static final String DENIED_MESSAGE = "您无权查看系统日志。"; private static final String UNAVAILABLE_MESSAGE = - "System log service is temporarily unavailable. Please try again later."; + "系统日志服务暂时不可用,请稍后重试。"; private SystemLogServiceCheck() { } @@ -59,10 +59,10 @@ public final class SystemLogServiceCheck { SystemLog orphanedOperator = log(99L, "user.update", "Updated orphaned operator account"); orphanedOperator.setOperatorUsername(""); orphanedOperator.setOperatorDisplayName(""); - require("User #1".equals(orphanedOperator.getOperatorLabel()), + require("用户 #1".equals(orphanedOperator.getOperatorLabel()), "operator id should still render when joined user names are unavailable"); - require("administrator".equals(orphanedOperator.getOperatorMetaText()), - "operator meta should preserve role when names are unavailable"); + require("管理员".equals(orphanedOperator.getOperatorMetaText()), + "operator meta should display role when names are unavailable"); SystemLog unsafeStatus = log(100L, "user.update", "Unsafe status check"); unsafeStatus.setResultStatus("success\" onclick=\"x"); diff --git a/src/test/java/com/mzh/library/service/UserAccountServiceCheck.java b/src/test/java/com/mzh/library/service/UserAccountServiceCheck.java index 054cf41..01ca4ef 100644 --- a/src/test/java/com/mzh/library/service/UserAccountServiceCheck.java +++ b/src/test/java/com/mzh/library/service/UserAccountServiceCheck.java @@ -26,9 +26,9 @@ import java.util.logging.Logger; import java.util.stream.Collectors; public final class UserAccountServiceCheck { - private static final String DENIED_MESSAGE = "You do not have permission to manage users."; + private static final String DENIED_MESSAGE = "您无权管理用户。"; private static final String UNAVAILABLE_MESSAGE = - "User management service is temporarily unavailable. Please try again later."; + "用户管理服务暂时不可用,请稍后重试。"; private UserAccountServiceCheck() { }
BookAuthorBorrow records图书作者借阅次数