diff --git a/src/app/(main)/analytics/ResourceOverconsumptionReport/page.tsx b/src/app/(main)/analytics/ResourceOverconsumptionReport/page.tsx index 771d21f..ae2085a 100644 --- a/src/app/(main)/analytics/ResourceOverconsumptionReport/page.tsx +++ b/src/app/(main)/analytics/ResourceOverconsumptionReport/page.tsx @@ -9,7 +9,7 @@ export const metadata: Metadata = { }; const StaffMonthlyWorkHoursAnalysisReport: React.FC = async () => { - const { t } = await getServerI18n("User Group"); + const { t } = await getServerI18n("report"); return ( <> diff --git a/src/app/(main)/analytics/StaffMonthlyWorkHoursAnalysisReport/page.tsx b/src/app/(main)/analytics/StaffMonthlyWorkHoursAnalysisReport/page.tsx index 49ba399..ed9e686 100644 --- a/src/app/(main)/analytics/StaffMonthlyWorkHoursAnalysisReport/page.tsx +++ b/src/app/(main)/analytics/StaffMonthlyWorkHoursAnalysisReport/page.tsx @@ -9,7 +9,7 @@ export const metadata: Metadata = { }; const StaffMonthlyWorkHoursAnalysisReport: React.FC = async () => { - const { t } = await getServerI18n("User Group"); + const { t } = await getServerI18n("report"); return ( <> diff --git a/src/app/(main)/settings/changepassword/page.tsx b/src/app/(main)/settings/changepassword/page.tsx index e470ca7..3de74eb 100644 --- a/src/app/(main)/settings/changepassword/page.tsx +++ b/src/app/(main)/settings/changepassword/page.tsx @@ -19,7 +19,7 @@ export const metadata: Metadata = { }; const ChangePasswordPage: React.FC = async () => { - const { t } = await getServerI18n("User Group"); + const { t } = await getServerI18n("changePassword"); // preloadTeamLeads(); // preloadStaff(); return ( @@ -34,7 +34,7 @@ const ChangePasswordPage: React.FC = async () => { {t("Change Password")} - + }> diff --git a/src/app/(main)/settings/group/create/page.tsx b/src/app/(main)/settings/group/create/page.tsx index 9130236..9460a71 100644 --- a/src/app/(main)/settings/group/create/page.tsx +++ b/src/app/(main)/settings/group/create/page.tsx @@ -11,7 +11,7 @@ const CreateStaff: React.FC = async () => { return ( <> - {t("Create Group")} + {t("Create User Group")} diff --git a/src/app/(main)/settings/group/page.tsx b/src/app/(main)/settings/group/page.tsx index 5322132..c602990 100644 --- a/src/app/(main)/settings/group/page.tsx +++ b/src/app/(main)/settings/group/page.tsx @@ -20,7 +20,7 @@ export const metadata: Metadata = { const UserGroup: React.FC = async () => { - const { t } = await getServerI18n("User Group"); + const { t } = await getServerI18n("group"); // preloadTeamLeads(); // preloadStaff(); return ( @@ -43,7 +43,7 @@ export const metadata: Metadata = { {t("Create User Group")} - + }> diff --git a/src/components/ChangePassword/ChangePasswordForm.tsx b/src/components/ChangePassword/ChangePasswordForm.tsx index 9801ec7..ff2965e 100644 --- a/src/components/ChangePassword/ChangePasswordForm.tsx +++ b/src/components/ChangePassword/ChangePasswordForm.tsx @@ -14,7 +14,7 @@ import { Visibility, VisibilityOff } from "@mui/icons-material"; import { IconButton, InputAdornment } from "@mui/material"; const ChagnePasswordForm: React.FC = () => { - const { t } = useTranslation(); + const { t } = useTranslation("changePassword"); const [showNewPassword, setShowNewPassword] = useState(false); const handleClickShowNewPassword = () => setShowNewPassword(!showNewPassword); @@ -38,7 +38,7 @@ const ChagnePasswordForm: React.FC = () => { - {t("Please Fill in all the Fields")} + {t("Please Fill in All Fields")} diff --git a/src/components/CreateGroup/AuthorityAllocation.tsx b/src/components/CreateGroup/AuthorityAllocation.tsx index bdd4ccb..794b98d 100644 --- a/src/components/CreateGroup/AuthorityAllocation.tsx +++ b/src/components/CreateGroup/AuthorityAllocation.tsx @@ -84,8 +84,8 @@ const AuthorityAllocation: React.FC = ({ auth }) => { onClick: addAuth, buttonIcon: , }, - { label: t("authority"), name: "authority" }, - { label: t("Auth Name"), name: "name" }, + { label: t("Authority"), name: "authority" }, + { label: t("Description"), name: "name" }, // { label: t("Current Position"), name: "currentPosition" }, ], [addAuth, t] @@ -97,10 +97,10 @@ const AuthorityAllocation: React.FC = ({ auth }) => { label: t("Remove"), name: "id", onClick: removeAuth, - buttonIcon: , + buttonIcon: , }, - { label: t("authority"), name: "authority" }, - { label: t("Auth Name"), name: "name" }, + { label: t("Authority"), name: "authority" }, + { label: t("Description"), name: "name" }, ], [removeAuth, selectedAuths, t] ); @@ -115,16 +115,13 @@ const AuthorityAllocation: React.FC = ({ auth }) => { }, []); React.useEffect(() => { - // setFilteredStaff( - // initialStaffs.filter((s) => { - // const q = query.toLowerCase(); - // // s.staffId.toLowerCase().includes(q) - // // const q = query.toLowerCase(); - // // return s.name.toLowerCase().includes(q); - // // s.code.toString().includes(q) || - // // (s.brNo != null && s.brNo.toLowerCase().includes(q)) - // }) - // ); + setFilteredAuths( + initialAuths.filter( + (a) => + a.authority.toLowerCase().includes(query.toLowerCase()) || + a.name?.toLowerCase().includes(query.toLowerCase()) + ) + ); }, [auth, query]); const resetAuth = React.useCallback(() => { @@ -152,7 +149,7 @@ const AuthorityAllocation: React.FC = ({ auth }) => { > - {t("Authority")} + {/* {t("Authority")} */} @@ -162,7 +159,7 @@ const AuthorityAllocation: React.FC = ({ auth }) => { fullWidth onChange={onQueryInputChange} value={query} - placeholder={t("Search by staff ID, name or position.")} + placeholder={t("Search by ") + t("Authority") + " / " + t("Description")} InputProps={{ endAdornment: query && ( @@ -178,18 +175,20 @@ const AuthorityAllocation: React.FC = ({ auth }) => { - {tabIndex === 0 && ( + {tabIndex === 0 && ( )} - {tabIndex === 1 && ( + {tabIndex === 1 && ( = ({ auth, users }) => { const [serverError, setServerError] = useState(""); const router = useRouter(); const [tabIndex, setTabIndex] = useState(0); - const { t } = useTranslation(); + const { t } = useTranslation("group"); const errors = formProps.formState.errors; diff --git a/src/components/CreateGroup/GroupInfo.tsx b/src/components/CreateGroup/GroupInfo.tsx index d9141bc..5792050 100644 --- a/src/components/CreateGroup/GroupInfo.tsx +++ b/src/components/CreateGroup/GroupInfo.tsx @@ -51,13 +51,13 @@ const GroupInfo: React.FC = () => { Boolean(errors.name) && (errors.name?.message ? t(errors.name.message) - : t("Please input correct name")) + : t("Please input correct ") + t("Group Name")) } /> { Boolean(errors.description) && (errors.description?.message ? t(errors.description.message) - : t("Please input correct description")) + : t("Please input correct ") + t("Description")) } /> diff --git a/src/components/CreateGroup/UserAllocation.tsx b/src/components/CreateGroup/UserAllocation.tsx index ff13c52..351303a 100644 --- a/src/components/CreateGroup/UserAllocation.tsx +++ b/src/components/CreateGroup/UserAllocation.tsx @@ -85,8 +85,8 @@ const UserAllocation: React.FC = ({ users }) => { onClick: addUser, buttonIcon: , }, - { label: t("User Name"), name: "username" }, - { label: t("name"), name: "name" }, + { label: t("Username"), name: "username" }, + { label: t("Staff Name"), name: "name" }, ], [addUser, t] ); @@ -99,8 +99,8 @@ const UserAllocation: React.FC = ({ users }) => { onClick: removeUser, buttonIcon: , }, - { label: t("User Name"), name: "username" }, - { label: t("name"), name: "name" }, + { label: t("Username"), name: "username" }, + { label: t("Staff Name"), name: "name" }, ], [removeUser, selectedUsers, t] ); @@ -116,16 +116,13 @@ const UserAllocation: React.FC = ({ users }) => { }, []); React.useEffect(() => { - // setFilteredStaff( - // initialStaffs.filter((s) => { - // const q = query.toLowerCase(); - // // s.staffId.toLowerCase().includes(q) - // // const q = query.toLowerCase(); - // // return s.name.toLowerCase().includes(q); - // // s.code.toString().includes(q) || - // // (s.brNo != null && s.brNo.toLowerCase().includes(q)) - // }) - // ); + const q = query.toLowerCase(); + setFilteredUsers( + initialUsers.filter((u) => ( + u.username.toLowerCase().includes(q) || + u.name.toLowerCase().includes(q) + )) + ); }, [users, query]); const resetUser = React.useCallback(() => { @@ -153,7 +150,7 @@ const UserAllocation: React.FC = ({ users }) => { > - {t("User")} + {/* {t("User")} */} @@ -163,7 +160,7 @@ const UserAllocation: React.FC = ({ users }) => { fullWidth onChange={onQueryInputChange} value={query} - placeholder={t("Search by staff ID, name or position.")} + placeholder={t("Search by ") + t("Username") + " / " + t("Staff Name")} InputProps={{ endAdornment: query && ( diff --git a/src/components/CreateTeam/StaffAllocation.tsx b/src/components/CreateTeam/StaffAllocation.tsx index 04b880c..6f267de 100644 --- a/src/components/CreateTeam/StaffAllocation.tsx +++ b/src/components/CreateTeam/StaffAllocation.tsx @@ -48,7 +48,6 @@ const StaffAllocation: React.FC = ({ allStaffs: staff }) => { } = useFormContext(); const initialStaffs = staff.map((s) => ({ ...s })); - // console.log(initialStaffs) const [filteredStaff, setFilteredStaff] = useState(initialStaffs); const [selectedStaff, setSelectedStaff] = useState( initialStaffs.filter((s) => getValues("addStaffIds")?.includes(s.id)) @@ -158,15 +157,13 @@ const StaffAllocation: React.FC = ({ allStaffs: staff }) => { }, []); React.useEffect(() => { + const q = query.toLowerCase(); setFilteredStaff( - initialStaffs.filter((i) => { - const q = query.toLowerCase(); - return ( + initialStaffs.filter((i) => ( i.staffId.toLowerCase().includes(q) || i.name.toLowerCase().includes(q) || i.currentPosition.toLowerCase().includes(q) - ); - }) + )) ); }, [staff, query]); diff --git a/src/components/EditUser/EditUser.tsx b/src/components/EditUser/EditUser.tsx index 947a116..1d3c473 100644 --- a/src/components/EditUser/EditUser.tsx +++ b/src/components/EditUser/EditUser.tsx @@ -50,7 +50,7 @@ interface Props { } const EditUser: React.FC = async ({ user, rules, auths }) => { - const { t } = useTranslation(); + const { t } = useTranslation("user"); const formProps = useForm(); const searchParams = useSearchParams(); const id = parseInt(searchParams.get("id") || "0"); diff --git a/src/components/EditUserGroup/AuthorityAllocation.tsx b/src/components/EditUserGroup/AuthorityAllocation.tsx index da502da..856ca3b 100644 --- a/src/components/EditUserGroup/AuthorityAllocation.tsx +++ b/src/components/EditUserGroup/AuthorityAllocation.tsx @@ -41,7 +41,6 @@ const AuthorityAllocation: React.FC = ({ auth }) => { reset, resetField, } = useFormContext(); - console.log(auth) const initialAuths = auth.map((a) => ({ ...a })).sort((a, b) => a.id - b.id); const [filteredAuths, setFilteredAuths] = useState(initialAuths); const [selectedAuths, setSelectedAuths] = useState( @@ -86,8 +85,8 @@ const AuthorityAllocation: React.FC = ({ auth }) => { onClick: addAuth, buttonIcon: , }, - { label: t("authority"), name: "authority" }, - { label: t("Auth Name"), name: "name" }, + { label: t("Authority"), name: "authority" }, + { label: t("Description"), name: "name" }, // { label: t("Current Position"), name: "currentPosition" }, ], [addAuth, t] @@ -101,8 +100,8 @@ const AuthorityAllocation: React.FC = ({ auth }) => { onClick: removeAuth, buttonIcon: , }, - { label: t("authority"), name: "authority" }, - { label: t("Auth Name"), name: "name" }, + { label: t("Authority"), name: "authority" }, + { label: t("Description"), name: "name" }, ], [removeAuth, selectedAuths, t] ); @@ -117,16 +116,13 @@ const AuthorityAllocation: React.FC = ({ auth }) => { }, []); React.useEffect(() => { - // setFilteredStaff( - // initialStaffs.filter((s) => { - // const q = query.toLowerCase(); - // // s.staffId.toLowerCase().includes(q) - // // const q = query.toLowerCase(); - // // return s.name.toLowerCase().includes(q); - // // s.code.toString().includes(q) || - // // (s.brNo != null && s.brNo.toLowerCase().includes(q)) - // }) - // ); + const q = query.toLowerCase(); + setFilteredAuths( + initialAuths.filter((a) => ( + a.authority.toLowerCase().includes(q) || + a.name.toLowerCase().includes(q) + )) + ); }, [auth, query]); const resetAuth = React.useCallback(() => { @@ -164,7 +160,7 @@ const AuthorityAllocation: React.FC = ({ auth }) => { fullWidth onChange={onQueryInputChange} value={query} - placeholder={t("Search by staff ID, name or position.")} + placeholder={t("Search by ")+ t("Authority") + " / " + t("Description")} InputProps={{ endAdornment: query && ( diff --git a/src/components/EditUserGroup/GroupInfo.tsx b/src/components/EditUserGroup/GroupInfo.tsx index d9141bc..3817cec 100644 --- a/src/components/EditUserGroup/GroupInfo.tsx +++ b/src/components/EditUserGroup/GroupInfo.tsx @@ -51,13 +51,13 @@ const GroupInfo: React.FC = () => { Boolean(errors.name) && (errors.name?.message ? t(errors.name.message) - : t("Please input correct name")) + : t("Please input correct ") + t("name")) } /> { Boolean(errors.description) && (errors.description?.message ? t(errors.description.message) - : t("Please input correct description")) + : t("Please input correct ") + t("Description")) } /> diff --git a/src/components/EditUserGroup/UserAllocation.tsx b/src/components/EditUserGroup/UserAllocation.tsx index 14ed975..5173311 100644 --- a/src/components/EditUserGroup/UserAllocation.tsx +++ b/src/components/EditUserGroup/UserAllocation.tsx @@ -92,8 +92,8 @@ const UserAllocation: React.FC = ({ users }) => { onClick: addUser, buttonIcon: , }, - { label: t("User Name"), name: "username" }, - { label: t("name"), name: "name" }, + { label: t("Username"), name: "username" }, + { label: t("Staff Name"), name: "name" }, ], [addUser, t] ); @@ -106,8 +106,8 @@ const UserAllocation: React.FC = ({ users }) => { onClick: removeUser, buttonIcon: , }, - { label: t("User Name"), name: "username" }, - { label: t("name"), name: "name" }, + { label: t("Username"), name: "username" }, + { label: t("Staff Name"), name: "name" }, ], [removeUser, selectedUsers, t] ); @@ -123,16 +123,13 @@ const UserAllocation: React.FC = ({ users }) => { }, []); React.useEffect(() => { - // setFilteredStaff( - // initialStaffs.filter((s) => { - // const q = query.toLowerCase(); - // // s.staffId.toLowerCase().includes(q) - // // const q = query.toLowerCase(); - // // return s.name.toLowerCase().includes(q); - // // s.code.toString().includes(q) || - // // (s.brNo != null && s.brNo.toLowerCase().includes(q)) - // }) - // ); + const q = query.toLowerCase(); + setFilteredUsers( + initialUsers.filter((item) => ( + item.username.toLowerCase().includes(q) || + item.name.toLowerCase().includes(q) + )) + ); }, [users, query]); const resetUser = React.useCallback(() => { @@ -170,7 +167,7 @@ const UserAllocation: React.FC = ({ users }) => { fullWidth onChange={onQueryInputChange} value={query} - placeholder={t("Search by staff ID, name or position.")} + placeholder={t("Search by ") + t("Username") + " / " + t("Staff Name")} InputProps={{ endAdornment: query && ( diff --git a/src/components/GenerateMonthlyWorkHoursReport/GenerateMonthlyWorkHoursReport.tsx b/src/components/GenerateMonthlyWorkHoursReport/GenerateMonthlyWorkHoursReport.tsx index 072e297..a858406 100644 --- a/src/components/GenerateMonthlyWorkHoursReport/GenerateMonthlyWorkHoursReport.tsx +++ b/src/components/GenerateMonthlyWorkHoursReport/GenerateMonthlyWorkHoursReport.tsx @@ -3,61 +3,66 @@ import React, { useMemo } from "react"; import SearchBox, { Criterion } from "../SearchBox"; import { useTranslation } from "react-i18next"; import { ProjectResult } from "@/app/api/projects"; -import { fetchMonthlyWorkHoursReport, fetchProjectCashFlowReport } from "@/app/api/reports/actions"; +import { + fetchMonthlyWorkHoursReport, + fetchProjectCashFlowReport, +} from "@/app/api/reports/actions"; import { downloadFile } from "@/app/utils/commonUtil"; import { BASE_API_URL } from "@/config/api"; import { MonthlyWorkHoursReportFilter } from "@/app/api/reports"; import { records } from "@/app/api/staff/actions"; import { StaffResult } from "@/app/api/staff"; +import dayjs from "dayjs"; interface Props { - staffs: StaffResult[] + staffs: StaffResult[]; } type SearchQuery = Partial>; type SearchParamNames = keyof SearchQuery; const GenerateMonthlyWorkHoursReport: React.FC = ({ staffs }) => { - const { t } = useTranslation(); - const staffCombo = staffs.map(staff => `${staff.name} - ${staff.staffId}`) - console.log(staffs) + const { t } = useTranslation("report"); + const staffCombo = staffs.map((staff) => `${staff.name} - ${staff.staffId}`); - const searchCriteria: Criterion[] = useMemo( - () => [ - { - label: t("Staff"), - paramName: "staff", - type: "select", - options: staffCombo, - needAll: false - }, - { - label: t("date"), - paramName: "date", - type: "monthYear", - }, - ], - [t], - ); + const searchCriteria: Criterion[] = useMemo( + () => [ + { + label: t("Staff"), + paramName: "staff", + type: "select", + options: staffCombo, + needAll: false, + }, + { + label: t("Date"), + paramName: "date", + type: "monthYear", + }, + ], + [t] + ); -return ( + return ( <> - { - const index = staffCombo.findIndex(staff => staff === query.staff) - if (query.staff.length > 0 && query.staff.toLocaleLowerCase() !== "all" && query.date.length > 0) { - const index = staffCombo.findIndex(staff => staff === query.staff) - const response = await fetchMonthlyWorkHoursReport({ id: staffs[index].id, yearMonth: query.date }) - if (response) { - downloadFile(new Uint8Array(response.blobValue), response.filename!!) - } - } - } - } - /> - - ) -} + const index = staffCombo.findIndex((staff) => staff === query.staff); + const response = await fetchMonthlyWorkHoursReport({ + id: staffs[index].id, + yearMonth: query.date, + }); + if (response) { + downloadFile( + new Uint8Array(response.blobValue), + response.filename!! + ); + } + }} + /> + + ); +}; -export default GenerateMonthlyWorkHoursReport \ No newline at end of file +export default GenerateMonthlyWorkHoursReport; diff --git a/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx b/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx index 5e6e76a..fb49dba 100644 --- a/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx +++ b/src/components/ResourceOverconsumptionReport/ResourceOverconsumptionReport.tsx @@ -20,10 +20,10 @@ type SearchQuery = Partial = ({ team, customer }) => { - const { t } = useTranslation(); + const { t } = useTranslation("report"); const teamCombo = team.map(t => `${t.name} - ${t.code}`) const custCombo = customer.map(c => `${c.name} - ${c.code}`) - const statusCombo = ["Within Budget, Overconsumption", "Potential Overconsumption"] + const statusCombo = ["Overconsumption", "Potential Overconsumption"] // const staffCombo = staffs.map(staff => `${staff.name} - ${staff.staffId}`) // console.log(staffs) diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx index 0f342d0..ad6cbeb 100644 --- a/src/components/SearchBox/SearchBox.tsx +++ b/src/components/SearchBox/SearchBox.tsx @@ -226,19 +226,18 @@ function SearchBox({ adapterLocale="zh-hk" > - - {c.label} - - + + + )} diff --git a/src/components/UserGroupSearch/UserGroupSearch.tsx b/src/components/UserGroupSearch/UserGroupSearch.tsx index 7a8f7dd..85f01c6 100644 --- a/src/components/UserGroupSearch/UserGroupSearch.tsx +++ b/src/components/UserGroupSearch/UserGroupSearch.tsx @@ -26,10 +26,15 @@ const UserGroupSearch: React.FC = ({ users }) => { const searchCriteria: Criterion[] = useMemo( () => [ { - label: t("User Name"), + label: t("Group Name"), paramName: "name", type: "text", }, + { + label: t("Description"), + paramName: "description", + type: "text", + }, ], [t] ); @@ -75,14 +80,13 @@ const UserGroupSearch: React.FC = ({ users }) => { { - // setFilteredUser( - // users.filter( - // (t) => - // t.name.toLowerCase().includes(query.name.toLowerCase()) && - // t.code.toLowerCase().includes(query.code.toLowerCase()) && - // t.description.toLowerCase().includes(query.description.toLowerCase()) - // ) - // ) + setFilteredUser( + users.filter( + (u) => + u.name.toLowerCase().includes(query.name.toLowerCase()) && + u.description.toLowerCase().includes(query.description.toLowerCase()) + ) + ) }} /> items={filteredUser} columns={columns} /> diff --git a/src/i18n/zh/changePassword.json b/src/i18n/zh/changePassword.json new file mode 100644 index 0000000..6ddba8e --- /dev/null +++ b/src/i18n/zh/changePassword.json @@ -0,0 +1,7 @@ +{ + "Change Password": "更改密碼", + "Please Fill in All Fields": "請填寫以下項目", + "Input Old Password": "舊密碼", + "Input New Password": "新密碼", + "Input New Password Again": "重複輸入新密碼" +} \ No newline at end of file diff --git a/src/i18n/zh/group.json b/src/i18n/zh/group.json new file mode 100644 index 0000000..d976095 --- /dev/null +++ b/src/i18n/zh/group.json @@ -0,0 +1,27 @@ +{ + "User Group": "用戶群組", + "Create User Group": "建立用戶群組", + "Edit User Group": "編輯用戶群組", + "Edit": "編輯", + "Group Name": "名稱", + "Description": "描述", + "Group Info": "群組資料", + "Add": "新增", + "User": "用戶", + "Remove": "移除", + "Confirm": "確定", + "Cancel": "取消", + "Delete": "刪除", + "Search by ": "搜尋", + "Delete Success": "刪除成功", + "Please input correct ": "請輸入正確", + "Authority Allocation": "權限分配", + "Authority Pool": "權限池", + "Allocated Authority": "已分配權限", + "User Allocation": "用戶分配", + "User Pool": "用戶池", + "Allocated Users": "已分配用戶", + "Username": "用戶名", + "Staff Name": "員工名字", + "Authority": "權限" +} \ No newline at end of file diff --git a/src/i18n/zh/report.json b/src/i18n/zh/report.json index 5b2e784..d15eec9 100644 --- a/src/i18n/zh/report.json +++ b/src/i18n/zh/report.json @@ -1,4 +1,12 @@ { + "Staff Monthly Work Hours Analysis Report": "Staff Monthly Work Hours Analysis Report", + "Project Resource Overconsumption Report": "Project Resource Overconsumption Report", + "Project": "項目", - "Date Type": "日期類型" + "Date Type": "日期類型", + "Date": "日期", + "Team": "隊伍", + "Client": "客戶", + "Status": "狀態", + "Staff": "員工" } \ No newline at end of file diff --git a/src/i18n/zh/user.json b/src/i18n/zh/user.json new file mode 100644 index 0000000..e92a8ad --- /dev/null +++ b/src/i18n/zh/user.json @@ -0,0 +1,7 @@ +{ + "Edit User": "編輯用戶", + "User Detail": "用戶資料", + "User Authority": "權限", + "username": "用戶名", + "password": "更改密碼" +} \ No newline at end of file