Apply i18n

This commit is contained in:
Takeshi Kimata
2024-05-05 18:39:05 +09:00
parent b0f3852bb2
commit ce078bb132
9 changed files with 157 additions and 39 deletions

View File

@@ -31,12 +31,12 @@ const automationStatus = [
const templates = [{ uid: "text" }, { uid: "step" }]; const templates = [{ uid: "text" }, { uid: "step" }];
const testRunStatus = [ const testRunStatus = [
{ name: "New", uid: "new" }, { uid: "new" },
{ name: "In progress", uid: "in-progress" }, { uid: "inProgress" },
{ name: "Under review", uid: "under-review" }, { uid: "underReview" },
{ name: "Rejected", uid: "rejected" }, { uid: "rejected" },
{ name: "Done", uid: "done" }, { uid: "done" },
{ name: "Closed", uid: "closed" }, { uid: "closed" },
]; ];
const testRunCaseStatus = [ const testRunCaseStatus = [

View File

@@ -100,8 +100,31 @@
"max_file_size": "Max. file size" "max_file_size": "Max. file size"
}, },
"Runs": { "Runs": {
"runs": "Test Runs",
"id": "ID",
"name": "Name",
"description": "Description",
"last_update": "Last update",
"actions": "Actions",
"new_run": "New Run",
"delete_run": "Delete Run",
"no_runs_found": "No runs found"
},
"Run": {
"back_to_runs": "Back to test runs",
"updating": "Updating...",
"update": "Update",
"progress": "Progress",
"id": "ID", "id": "ID",
"title": "Title", "title": "Title",
"please_enter": "Please enter run name",
"description": "Description",
"new": "New",
"inProgress": "In progress",
"underReview": "Under review",
"rejected": "Rejected",
"done": "Done",
"closed": "Closed",
"priority": "Priority", "priority": "Priority",
"status": "Status", "status": "Status",
"actions": "Actions", "actions": "Actions",
@@ -114,6 +137,8 @@
"failed": "Failed", "failed": "Failed",
"retest": "Retest", "retest": "Retest",
"skipped": "Skipped", "skipped": "Skipped",
"select_test_case": "Select test cases",
"test_case_selection": "Test case selection",
"include_in_run": "Include in run", "include_in_run": "Include in run",
"exclude_from_run": "Exclude from run", "exclude_from_run": "Exclude from run",
"no_cases_found": "No cases found" "no_cases_found": "No cases found"

View File

@@ -100,8 +100,31 @@
"max_file_size": "最大ファイルサイズ" "max_file_size": "最大ファイルサイズ"
}, },
"Runs": { "Runs": {
"runs": "テストラン",
"id": "ID",
"name": "名前",
"description": "詳細",
"last_update": "最終更新",
"actions": "アクション",
"new_run": "新規テストラン",
"delete_run": "テストランを削除",
"no_runs_found": "テストランがありません"
},
"Run": {
"back_to_runs": "テストラン一覧に戻る",
"updating": "更新中...",
"update": "更新",
"progress": "進捗",
"id": "ID", "id": "ID",
"title": "タイトル", "title": "タイトル",
"description": "詳細",
"new": "新規",
"inProgress": "進行中",
"underReview": "レビュー中",
"rejected": "却下",
"done": "完了",
"closed": "クローズ",
"please_enter": "タイトルを入力してください",
"priority": "優先度", "priority": "優先度",
"status": "ステータス", "status": "ステータス",
"actions": "アクション", "actions": "アクション",
@@ -114,6 +137,8 @@
"failed": "失敗", "failed": "失敗",
"retest": "再テスト", "retest": "再テスト",
"skipped": "スキップ", "skipped": "スキップ",
"select_test_case": "テストケースを選択",
"test_case_selection": "テストケース選択",
"include_in_run": "テストランに含める", "include_in_run": "テストランに含める",
"exclude_from_run": "テストランから除外する", "exclude_from_run": "テストランから除外する",
"no_cases_found": "テストケースが見つかりません" "no_cases_found": "テストケースが見つかりません"

View File

@@ -4,13 +4,15 @@ import { Button } from "@nextui-org/react";
import { Plus } from "lucide-react"; import { Plus } from "lucide-react";
import RunsTable from "./RunsTable"; import RunsTable from "./RunsTable";
import { fetchRuns, createRun, deleteRun } from "./runsControl"; import { fetchRuns, createRun, deleteRun } from "./runsControl";
import { RunsMessages } from "@/types/run";
type Props = { type Props = {
projectId: string; projectId: string;
locale: string; locale: string;
messages: RunsMessages;
}; };
export default function RunsPage({ projectId, locale }: Props) { export default function RunsPage({ projectId, locale, messages }: Props) {
const [runs, setRuns] = useState([]); const [runs, setRuns] = useState([]);
useEffect(() => { useEffect(() => {
@@ -50,7 +52,7 @@ export default function RunsPage({ projectId, locale }: Props) {
return ( return (
<div className="container mx-auto max-w-3xl pt-6 px-6 flex-grow"> <div className="container mx-auto max-w-3xl pt-6 px-6 flex-grow">
<div className="w-full p-3 flex items-center justify-between"> <div className="w-full p-3 flex items-center justify-between">
<h3 className="font-bold">Runs</h3> <h3 className="font-bold">{messages.runs}</h3>
<div> <div>
<Button <Button
startContent={<Plus size={16} />} startContent={<Plus size={16} />}
@@ -58,7 +60,7 @@ export default function RunsPage({ projectId, locale }: Props) {
color="primary" color="primary"
onClick={onCreateClick} onClick={onCreateClick}
> >
New Run {messages.newRun}
</Button> </Button>
</div> </div>
</div> </div>
@@ -67,6 +69,7 @@ export default function RunsPage({ projectId, locale }: Props) {
projectId={projectId} projectId={projectId}
runs={runs} runs={runs}
onDeleteRun={onDeleteClick} onDeleteRun={onDeleteClick}
messages={messages}
locale={locale} locale={locale}
/> />
</div> </div>

View File

@@ -15,21 +15,14 @@ import {
} from "@nextui-org/react"; } from "@nextui-org/react";
import { Link, NextUiLinkClasses } from "@/src/navigation"; import { Link, NextUiLinkClasses } from "@/src/navigation";
import { MoreVertical } from "lucide-react"; import { MoreVertical } from "lucide-react";
import { RunType } from "@/types/run"; import { RunsMessages, RunType } from "@/types/run";
import dayjs from "dayjs"; import dayjs from "dayjs";
const headerColumns = [
{ name: "ID", uid: "id", sortable: true },
{ name: "Name", uid: "name", sortable: true },
{ name: "Description", uid: "description", sortable: true },
{ name: "Last update", uid: "updatedAt", sortable: true },
{ name: "Actions", uid: "actions" },
];
type Props = { type Props = {
projectId: string; projectId: string;
runs: RunType[]; runs: RunType[];
onDeleteRun: (runId: number) => void; onDeleteRun: (runId: number) => void;
messages: RunsMessages;
locale: string; locale: string;
}; };
@@ -37,8 +30,17 @@ export default function RunsTable({
projectId, projectId,
runs, runs,
onDeleteRun, onDeleteRun,
messages,
locale, locale,
}: Props) { }: Props) {
const headerColumns = [
{ name: messages.id, uid: "id", sortable: true },
{ name: messages.name, uid: "name", sortable: true },
{ name: messages.description, uid: "description", sortable: true },
{ name: messages.lastUpdate, uid: "updatedAt", sortable: true },
{ name: messages.actions, uid: "actions" },
];
const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({ const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({
column: "id", column: "id",
direction: "ascending", direction: "ascending",
@@ -97,7 +99,7 @@ export default function RunsTable({
className="text-danger" className="text-danger"
onClick={() => onDeleteRun(run.id)} onClick={() => onDeleteRun(run.id)}
> >
Delete run {messages.deleteRun}
</DropdownItem> </DropdownItem>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
@@ -146,7 +148,7 @@ export default function RunsTable({
</TableColumn> </TableColumn>
)} )}
</TableHeader> </TableHeader>
<TableBody emptyContent={"No runs found"} items={sortedItems}> <TableBody emptyContent={messages.noRunsFound} items={sortedItems}>
{(item) => ( {(item) => (
<TableRow key={item.id}> <TableRow key={item.id}>
{(columnKey) => ( {(columnKey) => (

View File

@@ -35,7 +35,7 @@ import {
RunCaseType, RunCaseType,
RunCaseInfoType, RunCaseInfoType,
RunStatusCountType, RunStatusCountType,
RunsMessages, RunMessages,
} from "@/types/run"; } from "@/types/run";
import { CaseType } from "@/types/case"; import { CaseType } from "@/types/case";
import { FolderType } from "@/types/folder"; import { FolderType } from "@/types/folder";
@@ -64,11 +64,16 @@ const defaultTestRun = {
type Props = { type Props = {
projectId: string; projectId: string;
runId: string; runId: string;
messages: RunsMessages; messages: RunMessages;
locale: string; locale: string;
}; };
export default function RunEditor({ projectId, runId, messages, locale }: Props) { export default function RunEditor({
projectId,
runId,
messages,
locale,
}: Props) {
const [testRun, setTestRun] = useState<RunType>(defaultTestRun); const [testRun, setTestRun] = useState<RunType>(defaultTestRun);
const [folders, setFolders] = useState([]); const [folders, setFolders] = useState([]);
const [runCases, setRunCases] = useState<RunCaseType[]>([]); const [runCases, setRunCases] = useState<RunCaseType[]>([]);
@@ -218,7 +223,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
<> <>
<div className="border-b-1 dark:border-neutral-700 w-full p-3 flex items-center justify-between"> <div className="border-b-1 dark:border-neutral-700 w-full p-3 flex items-center justify-between">
<div className="flex items-center"> <div className="flex items-center">
<Tooltip content="Back to runs"> <Tooltip content={messages.backToRuns}>
<Button <Button
isIconOnly isIconOnly
size="sm" size="sm"
@@ -243,7 +248,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
setIsUpdating(false); setIsUpdating(false);
}} }}
> >
{isUpdating ? "Updating..." : "Update"} {isUpdating ? messages.updating : messages.update}
</Button> </Button>
</div> </div>
@@ -252,7 +257,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
<div> <div>
<div className="w-96 h-72"> <div className="w-96 h-72">
<div className="flex items-center"> <div className="flex items-center">
<h4 className="font-bold">Progress</h4> <h4 className="font-bold">{messages.progress}</h4>
<Tooltip content="Refresh"> <Tooltip content="Refresh">
<Button <Button
isIconOnly isIconOnly
@@ -273,10 +278,10 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
size="sm" size="sm"
type="text" type="text"
variant="bordered" variant="bordered"
label="Name" label={messages.title}
value={testRun.name} value={testRun.name}
isInvalid={isNameInvalid} isInvalid={isNameInvalid}
errorMessage={isNameInvalid ? "please enter name" : ""} errorMessage={isNameInvalid ? messages.pleaseEnter : ""}
onChange={(e) => { onChange={(e) => {
setTestRun({ ...testRun, name: e.target.value }); setTestRun({ ...testRun, name: e.target.value });
}} }}
@@ -286,8 +291,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
<Textarea <Textarea
size="sm" size="sm"
variant="bordered" variant="bordered"
label="Description" label={messages.description}
placeholder="Test run description"
value={testRun.description} value={testRun.description}
onValueChange={(changeValue) => { onValueChange={(changeValue) => {
setTestRun({ ...testRun, description: changeValue }); setTestRun({ ...testRun, description: changeValue });
@@ -307,12 +311,12 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
); );
setTestRun({ ...testRun, state: index }); setTestRun({ ...testRun, state: index });
}} }}
label="status" label={messages.status}
className="mt-3 max-w-xs" className="mt-3 max-w-xs"
> >
{testRunStatus.map((state, index) => ( {testRunStatus.map((status, index) => (
<SelectItem key={state.uid} value={index}> <SelectItem key={status.uid} value={index}>
{state.name} {messages[status.uid]}
</SelectItem> </SelectItem>
))} ))}
</Select> </Select>
@@ -322,7 +326,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
<Divider className="my-6" /> <Divider className="my-6" />
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h6 className="h-8 font-bold">Select test cases</h6> <h6 className="h-8 font-bold">{messages.selectTestCase}</h6>
<div> <div>
{(selectedKeys.size > 0 || selectedKeys === "all") && ( {(selectedKeys.size > 0 || selectedKeys === "all") && (
<Dropdown> <Dropdown>
@@ -332,7 +336,7 @@ export default function RunEditor({ projectId, runId, messages, locale }: Props)
color="primary" color="primary"
endContent={<ChevronDown size={16} />} endContent={<ChevronDown size={16} />}
> >
Test case selection {messages.testCaseSelection}
</Button> </Button>
</DropdownTrigger> </DropdownTrigger>
<DropdownMenu aria-label="test case select actions"> <DropdownMenu aria-label="test case select actions">

View File

@@ -6,10 +6,22 @@ export default function Page({
}: { }: {
params: { projectId: string; runId: string; locale: string }; params: { projectId: string; runId: string; locale: string };
}) { }) {
const t = useTranslations("Runs"); const t = useTranslations("Run");
const messages = { const messages = {
backToRuns: t("back_to_runs"),
updating: t("updating"),
update: t("update"),
progress: t("progress"),
id: t("id"), id: t("id"),
title: t("title"), title: t("title"),
pleaseEnter: t("please_enter"),
description: t("description"),
new: t("new"),
inProgress: t("inProgress"),
underReview: t("underReview"),
rejected: t("rejected"),
done: t("done"),
closed: t("closed"),
priority: t("priority"), priority: t("priority"),
actions: t("actions"), actions: t("actions"),
status: t("status"), status: t("status"),
@@ -22,6 +34,8 @@ export default function Page({
failed: t("failed"), failed: t("failed"),
retest: t("retest"), retest: t("retest"),
skipped: t("skipped"), skipped: t("skipped"),
selectTestCase: t("select_test_case"),
testCaseSelection: t("test_case_selection"),
includeInRun: t("include_in_run"), includeInRun: t("include_in_run"),
excludeFromRun: t("exclude_from_run"), excludeFromRun: t("exclude_from_run"),
noCasesFound: t("no_cases_found"), noCasesFound: t("no_cases_found"),

View File

@@ -1,13 +1,31 @@
import RunsPage from "./RunsPage"; import RunsPage from "./RunsPage";
import { useTranslations } from "next-intl";
export default function Page({ export default function Page({
params, params,
}: { }: {
params: { projectId: string; locale: string }; params: { projectId: string; locale: string };
}) { }) {
const t = useTranslations("Runs");
const messages = {
runs: t("runs"),
id: t("id"),
name: t("name"),
description: t("description"),
lastUpdate: t("last_update"),
actions: t("actions"),
newRun: t("new_run"),
deleteRun: t("delete_run"),
noRunsFound: t("no_runs_found"),
};
return ( return (
<> <>
<RunsPage projectId={params.projectId} locale={params.locale} /> <RunsPage
projectId={params.projectId}
locale={params.locale}
messages={messages}
/>
</> </>
); );
} }

View File

@@ -26,9 +26,33 @@ type RunStatusCountType = {
count: number; count: number;
}; };
export type RunsMessages = { type RunsMessages = {
runs: string,
id: string;
name: string;
description: string;
lastUpdate: string;
actions: string;
newRun: string;
deleteRun: string;
noRunsFound: string;
};
type RunMessages = {
backToRuns: string,
updating: string;
update: string;
progress: string,
id: string; id: string;
title: string; title: string;
pleaseEnter: string;
description: string;
new: string;
inProgress: string;
underReview: string;
rejected: string;
done: string;
closed: string;
priority: string; priority: string;
status: string; status: string;
actions: string; actions: string;
@@ -41,6 +65,8 @@ export type RunsMessages = {
failed: string; failed: string;
retest: string; retest: string;
skipped: string; skipped: string;
selectTestCase: string;
testCaseSelection: string;
includeInRun: string; includeInRun: string;
excludeFromRun: string; excludeFromRun: string;
noCasesFound: string; noCasesFound: string;
@@ -52,4 +78,5 @@ export {
RunCaseInfoType, RunCaseInfoType,
RunStatusCountType, RunStatusCountType,
RunsMessages, RunsMessages,
RunMessages,
}; };