Apply i18n
This commit is contained in:
@@ -19,5 +19,32 @@
|
||||
"create": "Create",
|
||||
"update": "Update",
|
||||
"please_enter": "Please enter project name"
|
||||
},
|
||||
"Project": {
|
||||
"home": "Home",
|
||||
"test_cases": "Test Cases",
|
||||
"test_run": "Test Runs"
|
||||
},
|
||||
"Folders": {
|
||||
"folder": "Folder",
|
||||
"new_folder": "New Folder",
|
||||
"edit_folder": "Edit Folder",
|
||||
"delete_folder": "Delete Folder",
|
||||
"folder_name": "Folder Name",
|
||||
"folder_detail": "Folder Detail",
|
||||
"close": "Close",
|
||||
"create": "Create",
|
||||
"update": "Update",
|
||||
"please_enter": "Please enter folder name"
|
||||
},
|
||||
"Cases": {
|
||||
"test_cases": "Test Cases",
|
||||
"id": "ID",
|
||||
"name": "Name",
|
||||
"priority": "Priority",
|
||||
"actions": "Actions",
|
||||
"delete_case": "Delete test case",
|
||||
"delete": "Delete",
|
||||
"new_test_case": "New Test Case"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,5 +19,32 @@
|
||||
"create": "作成",
|
||||
"update": "更新",
|
||||
"please_enter": "プロジェクト名を入力してください"
|
||||
},
|
||||
"Project": {
|
||||
"home": "ホーム",
|
||||
"test_cases": "テストケース",
|
||||
"test_runs": "テストラン"
|
||||
},
|
||||
"Folders": {
|
||||
"folder": "フォルダー",
|
||||
"new_folder": "新規フォルダー",
|
||||
"edit_folder": "フォルダーの編集",
|
||||
"delete_folder": "フォルダーの削除",
|
||||
"folder_name": "フォルダー名",
|
||||
"folder_detail": "フォルダー詳細",
|
||||
"close": "閉じる",
|
||||
"create": "作成",
|
||||
"update": "更新",
|
||||
"please_enter": "フォルダ名を入力してください"
|
||||
},
|
||||
"Cases": {
|
||||
"test_cases": "テストケース",
|
||||
"id": "ID",
|
||||
"title": "タイトル",
|
||||
"priority": "優先度",
|
||||
"actions": "アクション",
|
||||
"delete_case": "テストケースを削除",
|
||||
"delete": "削除",
|
||||
"new_test_case": "新規テストケース"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ import { Listbox, ListboxItem } from "@nextui-org/react";
|
||||
import { Home, Files, FlaskConical } from "lucide-react";
|
||||
import { usePathname, useRouter } from "@/src/navigation";
|
||||
import useGetCurrentIds from "@/utils/useGetCurrentIds";
|
||||
import { ProjectMessages } from "@/types/project";
|
||||
|
||||
export type Props = {
|
||||
messages: ProjectMessages;
|
||||
locale: string;
|
||||
};
|
||||
|
||||
export default function Sidebar({ locale }: Props) {
|
||||
export default function Sidebar({ messages, locale }: Props) {
|
||||
const { projectId } = useGetCurrentIds();
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
@@ -45,17 +47,17 @@ export default function Sidebar({ locale }: Props) {
|
||||
const tabItems = [
|
||||
{
|
||||
key: "home",
|
||||
text: "Home",
|
||||
text: messages.home,
|
||||
startContent: <Home strokeWidth={1} size={28} />,
|
||||
},
|
||||
{
|
||||
key: "cases",
|
||||
text: "Test Cases",
|
||||
text: messages.testCases,
|
||||
startContent: <Files strokeWidth={1} size={28} />,
|
||||
},
|
||||
{
|
||||
key: "runs",
|
||||
text: "Test Runs",
|
||||
text: messages.testRuns,
|
||||
startContent: <FlaskConical strokeWidth={1} size={28} />,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -11,13 +11,14 @@ import {
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
} from "@nextui-org/react";
|
||||
import { FolderType } from "@/types/folder";
|
||||
import { FolderType, FoldersMessages } from "@/types/folder";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
editingFolder: FolderType;
|
||||
onCancel: () => void;
|
||||
onSubmit: (name: string, detail: string) => void;
|
||||
messages: FoldersMessages;
|
||||
};
|
||||
|
||||
export default function FolderDialog({
|
||||
@@ -25,6 +26,7 @@ export default function FolderDialog({
|
||||
editingFolder,
|
||||
onCancel,
|
||||
onSubmit,
|
||||
messages,
|
||||
}: Props) {
|
||||
const [folderName, setFolderName] = useState({
|
||||
text: editingFolder ? editingFolder.name : "",
|
||||
@@ -80,7 +82,7 @@ export default function FolderDialog({
|
||||
setFolderName({
|
||||
text: "",
|
||||
isValid: false,
|
||||
errorMessage: "Please enter folder name",
|
||||
errorMessage: messages.pleaseEnter,
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -98,11 +100,13 @@ export default function FolderDialog({
|
||||
}}
|
||||
>
|
||||
<ModalContent>
|
||||
<ModalHeader className="flex flex-col gap-1">Folder</ModalHeader>
|
||||
<ModalHeader className="flex flex-col gap-1">
|
||||
{messages.folder}
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<Input
|
||||
type="text"
|
||||
label="Folder Name"
|
||||
label={messages.folderName}
|
||||
value={folderName.text}
|
||||
isInvalid={folderName.isValid}
|
||||
errorMessage={folderName.errorMessage}
|
||||
@@ -114,7 +118,7 @@ export default function FolderDialog({
|
||||
}}
|
||||
/>
|
||||
<Textarea
|
||||
label="Folder Detail"
|
||||
label={messages.folderDetail}
|
||||
value={folderDetail.text}
|
||||
isInvalid={folderDetail.isValid}
|
||||
errorMessage={folderDetail.errorMessage}
|
||||
@@ -128,10 +132,10 @@ export default function FolderDialog({
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant="light" onPress={onCancel}>
|
||||
Close
|
||||
{messages.close}
|
||||
</Button>
|
||||
<Button color="primary" onPress={validate}>
|
||||
{editingFolder ? "Update" : "Create"}
|
||||
{editingFolder ? messages.update : messages.create}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -6,8 +6,21 @@ import {
|
||||
DropdownItem,
|
||||
} from "@nextui-org/react";
|
||||
import { MoreVertical } from "lucide-react";
|
||||
import { FolderType, FoldersMessages } from "@/types/folder";
|
||||
|
||||
export default function FolderEditMenu({ folder, onEditClick, onDeleteClick }) {
|
||||
type Props = {
|
||||
folder: FolderType;
|
||||
onEditClick: (folder: FolderType) => void;
|
||||
onDeleteClick: (folder: FolderType) => void;
|
||||
messages: FoldersMessages;
|
||||
};
|
||||
|
||||
export default function FolderEditMenu({
|
||||
folder,
|
||||
onEditClick,
|
||||
onDeleteClick,
|
||||
messages,
|
||||
}: Props) {
|
||||
return (
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
@@ -17,7 +30,7 @@ export default function FolderEditMenu({ folder, onEditClick, onDeleteClick }) {
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu aria-label="Static Actions">
|
||||
<DropdownItem key="edit" onClick={() => onEditClick(folder)}>
|
||||
Edit folder
|
||||
{messages.editFolder}
|
||||
</DropdownItem>
|
||||
<DropdownItem
|
||||
key="delete"
|
||||
@@ -25,7 +38,7 @@ export default function FolderEditMenu({ folder, onEditClick, onDeleteClick }) {
|
||||
color="danger"
|
||||
onClick={() => onDeleteClick(folder.id)}
|
||||
>
|
||||
Delete folder
|
||||
{messages.deleteFolder}
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { FolderType } from "@/types/folder";
|
||||
import { FolderType, FoldersMessages } from "@/types/folder";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button, Listbox, ListboxItem } from "@nextui-org/react";
|
||||
import { Folder, Plus } from "lucide-react";
|
||||
@@ -18,10 +18,11 @@ import {
|
||||
|
||||
type Props = {
|
||||
projectId: string;
|
||||
messages: FoldersMessages;
|
||||
locale: string;
|
||||
};
|
||||
|
||||
export default function FoldersPane({ projectId, locale }: Props) {
|
||||
export default function FoldersPane({ projectId, messages, locale }: Props) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [folders, setFolders] = useState([]);
|
||||
@@ -112,7 +113,7 @@ export default function FoldersPane({ projectId, locale }: Props) {
|
||||
className="m-2"
|
||||
onClick={openDialogForCreate}
|
||||
>
|
||||
New Folder
|
||||
{messages.newFolder}
|
||||
</Button>
|
||||
<Listbox aria-label="Listbox Variants" variant="light">
|
||||
{folders.map((folder, index) => (
|
||||
@@ -135,6 +136,7 @@ export default function FoldersPane({ projectId, locale }: Props) {
|
||||
folder={folder}
|
||||
onEditClick={onEditClick}
|
||||
onDeleteClick={onDeleteClick}
|
||||
messages={messages}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -149,6 +151,7 @@ export default function FoldersPane({ projectId, locale }: Props) {
|
||||
editingFolder={editingFolder}
|
||||
onCancel={closeDialog}
|
||||
onSubmit={onSubmit}
|
||||
messages={messages}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import TestCaseTable from "./TestCaseTable";
|
||||
import { fetchCases, createCase, deleteCase, deleteCases } from "./caseControl";
|
||||
import { CasesMessages } from "@/types/case";
|
||||
|
||||
type Props = {
|
||||
projectId: string;
|
||||
folderId: string;
|
||||
messages: CasesMessages;
|
||||
locale: string;
|
||||
};
|
||||
|
||||
export default function CasesPane({ projectId, folderId, locale }: Props) {
|
||||
export default function CasesPane({
|
||||
projectId,
|
||||
folderId,
|
||||
messages,
|
||||
locale,
|
||||
}: Props) {
|
||||
const [cases, setCases] = useState([]);
|
||||
useEffect(() => {
|
||||
async function fetchDataEffect() {
|
||||
@@ -51,6 +58,7 @@ export default function CasesPane({ projectId, folderId, locale }: Props) {
|
||||
onCreateCase={() => handleCreateCase(folderId)}
|
||||
onDeleteCase={handleDeleteCase}
|
||||
onDeleteCases={handleDeleteCases}
|
||||
messages={messages}
|
||||
locale={locale}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -16,14 +16,7 @@ import {
|
||||
} from "@nextui-org/react";
|
||||
import { Link, NextUiLinkClasses } from "@/src/navigation";
|
||||
import { Plus, MoreVertical, Trash, Circle } from "lucide-react";
|
||||
|
||||
const headerColumns = [
|
||||
{ name: "ID", uid: "id", sortable: true },
|
||||
{ name: "Title", uid: "title", sortable: true },
|
||||
{ name: "Priority", uid: "priority", sortable: true },
|
||||
{ name: "Actions", uid: "actions" },
|
||||
];
|
||||
|
||||
import { CasesMessages } from "@/types/case";
|
||||
import { priorities } from "@/config/selection";
|
||||
|
||||
type Case = {
|
||||
@@ -48,6 +41,7 @@ type Props = {
|
||||
onCreateCase: () => void;
|
||||
onDeleteCase: (caseId: number) => void;
|
||||
onDeleteCases: (selectedCases: string[]) => void;
|
||||
messages: CasesMessages;
|
||||
locale: string;
|
||||
};
|
||||
|
||||
@@ -57,8 +51,16 @@ export default function TestCaseTable({
|
||||
onCreateCase,
|
||||
onDeleteCase,
|
||||
onDeleteCases,
|
||||
messages,
|
||||
locale,
|
||||
}: Props) {
|
||||
const headerColumns = [
|
||||
{ name: messages.id, uid: "id", sortable: true },
|
||||
{ name: messages.title, uid: "title", sortable: true },
|
||||
{ name: messages.priority, uid: "priority", sortable: true },
|
||||
{ name: messages.actions, uid: "actions" },
|
||||
];
|
||||
|
||||
const [selectedKeys, setSelectedKeys] = useState<Selection>(new Set([]));
|
||||
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
|
||||
column: "id",
|
||||
@@ -121,7 +123,7 @@ export default function TestCaseTable({
|
||||
className="text-danger"
|
||||
onClick={() => onDeleteCase(testCase.id)}
|
||||
>
|
||||
Delete test case
|
||||
{messages.deleteCase}
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
@@ -163,7 +165,7 @@ export default function TestCaseTable({
|
||||
return (
|
||||
<>
|
||||
<div className="border-b-1 dark:border-neutral-700 w-full p-3 flex items-center justify-between">
|
||||
<h3 className="font-bold">Cases</h3>
|
||||
<h3 className="font-bold">{messages.testCases}</h3>
|
||||
<div>
|
||||
{(selectedKeys.size > 0 || selectedKeys === "all") && (
|
||||
<Button
|
||||
@@ -173,7 +175,7 @@ export default function TestCaseTable({
|
||||
className="me-2"
|
||||
onClick={onDeleteCasesClick}
|
||||
>
|
||||
Delete
|
||||
{messages.delete}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
@@ -182,7 +184,7 @@ export default function TestCaseTable({
|
||||
color="primary"
|
||||
onClick={onCreateCase}
|
||||
>
|
||||
New Test Case
|
||||
{messages.newTestCase}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,40 @@
|
||||
import CasesPane from "./CasesPane";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function Page({
|
||||
params,
|
||||
}: {
|
||||
params: { projectId: string; folderId: string; locale: string };
|
||||
}) {
|
||||
const t = useTranslations("Cases");
|
||||
const messages = {
|
||||
testCases: t("test_cases"),
|
||||
// folder: t("folder"),
|
||||
// newFolder: t("new_folder"),
|
||||
|
||||
// deleteFolder: t("delete_folder"),
|
||||
id: t("id"),
|
||||
title: t("title"),
|
||||
priority: t("priority"),
|
||||
actions: t("actions"),
|
||||
deleteCase: t("delete_case"),
|
||||
delete: t("delete"),
|
||||
newTestCase: t("new_test_case"),
|
||||
// projectName: t("folder_name"),
|
||||
// projectDetail: t("folder_detail"),
|
||||
// close: t("close"),
|
||||
// create: t("create"),
|
||||
// update: t("update"),
|
||||
// pleaseEnter: t("please_enter"),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<CasesPane
|
||||
projectId={params.projectId}
|
||||
folderId={params.folderId}
|
||||
locale={params.locale}
|
||||
messages={messages}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import FoldersPane from "./FoldersPane";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function FoldersLayout({
|
||||
children,
|
||||
@@ -7,9 +8,27 @@ export default function FoldersLayout({
|
||||
children: React.ReactNode;
|
||||
params: { projectId: string; locale: string };
|
||||
}) {
|
||||
const t = useTranslations("Folders");
|
||||
const messages = {
|
||||
folder: t("folder"),
|
||||
newFolder: t("new_folder"),
|
||||
editFolder: t("edit_folder"),
|
||||
deleteFolder: t("delete_folder"),
|
||||
folderName: t("folder_name"),
|
||||
folderDetail: t("folder_detail"),
|
||||
close: t("close"),
|
||||
create: t("create"),
|
||||
update: t("update"),
|
||||
pleaseEnter: t("please_enter"),
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex w-full">
|
||||
<FoldersPane projectId={params.projectId} locale={params.locale} />
|
||||
<FoldersPane
|
||||
projectId={params.projectId}
|
||||
messages={messages}
|
||||
locale={params.locale}
|
||||
/>
|
||||
<div className="flex-grow w-full">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Sidebar from "./Sidebar";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function SidebarLayout({
|
||||
children,
|
||||
@@ -7,10 +8,17 @@ export default function SidebarLayout({
|
||||
children: React.ReactNode;
|
||||
params: { locale: string };
|
||||
}) {
|
||||
const t = useTranslations("Project");
|
||||
const messages = {
|
||||
home: t("home"),
|
||||
testCases: t("test_cases"),
|
||||
testRuns: t("test_runs"),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex border-t-1 dark:border-neutral-700 min-h-[calc(100vh-64px)]">
|
||||
<Sidebar locale={locale} />
|
||||
<Sidebar messages={messages} locale={locale} />
|
||||
<div className="flex w-full">
|
||||
<div className="flex-grow">{children}</div>
|
||||
</div>
|
||||
|
||||
@@ -49,4 +49,15 @@ type AttachmentType = {
|
||||
caseAttachments: CaseAttachmentType;
|
||||
};
|
||||
|
||||
export { CaseType, StepType, AttachmentType };
|
||||
export type CasesMessages = {
|
||||
testCases: string;
|
||||
id: string;
|
||||
title: string;
|
||||
priority: string;
|
||||
actions: string;
|
||||
deleteCase: string;
|
||||
delete: string;
|
||||
newTestCase: string;
|
||||
};
|
||||
|
||||
export { CaseType, StepType, AttachmentType, CasesMessages };
|
||||
|
||||
@@ -6,4 +6,17 @@ export type FolderType = {
|
||||
parentFolderId: number | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type FoldersMessages = {
|
||||
folder: string;
|
||||
newFolder: string;
|
||||
editFolder: string;
|
||||
deleteFolder: string;
|
||||
folderName: string;
|
||||
folderDetail: string;
|
||||
close: string;
|
||||
create: string;
|
||||
update: string;
|
||||
pleaseEnter: string;
|
||||
};
|
||||
|
||||
@@ -24,3 +24,9 @@ export type ProjectsMessages = {
|
||||
update: string;
|
||||
pleaseEnter: string;
|
||||
};
|
||||
|
||||
export type ProjectMessages = {
|
||||
home: string;
|
||||
testCases: string;
|
||||
testRuns: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user