i18n by next-intl
This commit is contained in:
@@ -1,13 +0,0 @@
|
|||||||
export default function DocsLayout({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<section className="flex flex-col items-center justify-center gap-4 py-8 md:py-10">
|
|
||||||
<div className="inline-block max-w-lg text-center justify-center">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { title } from "@/components/primitives";
|
|
||||||
|
|
||||||
export default function DocsPage() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1 className={title()}>Docs</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
Navbar as NextUINavbar,
|
Navbar as NextUINavbar,
|
||||||
NavbarContent,
|
NavbarContent,
|
||||||
NavbarMenu,
|
|
||||||
NavbarMenuToggle,
|
NavbarMenuToggle,
|
||||||
NavbarBrand,
|
NavbarBrand,
|
||||||
NavbarItem,
|
NavbarItem,
|
||||||
NavbarMenuItem,
|
|
||||||
Kbd,
|
Kbd,
|
||||||
Link,
|
Link as NextUiLink,
|
||||||
Input,
|
Input,
|
||||||
link as linkStyles,
|
|
||||||
} from "@nextui-org/react";
|
} from "@nextui-org/react";
|
||||||
|
import { Link } from "@/src/navigation";
|
||||||
import { siteConfig } from "@/config/site";
|
import { siteConfig } from "@/config/site";
|
||||||
import NextLink from "next/link";
|
|
||||||
|
|
||||||
import { ThemeSwitch } from "@/components/theme-switch";
|
import { ThemeSwitch } from "@/components/theme-switch";
|
||||||
import { GithubIcon, SearchIcon } from "@/components/icons";
|
import { GithubIcon, SearchIcon } from "@/components/icons";
|
||||||
|
|
||||||
@@ -46,7 +41,7 @@ export const Navbar = () => {
|
|||||||
<NextUINavbar maxWidth="xl" position="sticky" className="bg-inherit">
|
<NextUINavbar maxWidth="xl" position="sticky" className="bg-inherit">
|
||||||
<NavbarContent className="basis-1/5 sm:basis-full" justify="start">
|
<NavbarContent className="basis-1/5 sm:basis-full" justify="start">
|
||||||
<NavbarBrand as="li" className="gap-3 max-w-fit">
|
<NavbarBrand as="li" className="gap-3 max-w-fit">
|
||||||
<NextLink className="flex justify-start items-center gap-1" href="/">
|
<Link className="flex justify-start items-center gap-1" href="/">
|
||||||
<Image
|
<Image
|
||||||
src="/favicon/android-chrome-192x192.png"
|
src="/favicon/android-chrome-192x192.png"
|
||||||
width={32}
|
width={32}
|
||||||
@@ -54,17 +49,17 @@ export const Navbar = () => {
|
|||||||
alt="Logo"
|
alt="Logo"
|
||||||
/>
|
/>
|
||||||
<p className="font-bold text-inherit">Test Case Manager</p>
|
<p className="font-bold text-inherit">Test Case Manager</p>
|
||||||
</NextLink>
|
</Link>
|
||||||
</NavbarBrand>
|
</NavbarBrand>
|
||||||
<ul className="hidden lg:flex gap-4 justify-start ml-2">
|
<ul className="hidden lg:flex gap-4 justify-start ml-2">
|
||||||
{siteConfig.navItems.map((item) => (
|
{siteConfig.navItems.map((item) => (
|
||||||
<NavbarItem key={item.href}>
|
<NavbarItem key={item.href}>
|
||||||
<NextLink
|
<Link
|
||||||
className="data-[active=true]:text-primary data-[active=true]:font-medium"
|
className="data-[active=true]:text-primary data-[active=true]:font-medium"
|
||||||
href={item.href}
|
href={item.href}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</NextLink>
|
</Link>
|
||||||
</NavbarItem>
|
</NavbarItem>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -75,62 +70,29 @@ export const Navbar = () => {
|
|||||||
justify="end"
|
justify="end"
|
||||||
>
|
>
|
||||||
<NavbarItem className="hidden sm:flex gap-2">
|
<NavbarItem className="hidden sm:flex gap-2">
|
||||||
{/* <Link isExternal href={siteConfig.links.twitter} aria-label="Twitter">
|
<NextUiLink
|
||||||
<TwitterIcon className="text-default-500" />
|
isExternal
|
||||||
</Link> */}
|
href={siteConfig.links.github}
|
||||||
{/* <Link isExternal href={siteConfig.links.discord} aria-label="Discord">
|
aria-label="Github"
|
||||||
<DiscordIcon className="text-default-500" />
|
>
|
||||||
</Link> */}
|
|
||||||
<Link isExternal href={siteConfig.links.github} aria-label="Github">
|
|
||||||
<GithubIcon className="text-default-500" />
|
<GithubIcon className="text-default-500" />
|
||||||
</Link>
|
</NextUiLink>
|
||||||
<ThemeSwitch />
|
<ThemeSwitch />
|
||||||
</NavbarItem>
|
</NavbarItem>
|
||||||
<NavbarItem className="hidden lg:flex">{searchInput}</NavbarItem>
|
<NavbarItem className="hidden lg:flex">{searchInput}</NavbarItem>
|
||||||
{/* <NavbarItem className="hidden md:flex">
|
|
||||||
<Button
|
|
||||||
isExternal
|
|
||||||
as={Link}
|
|
||||||
className="text-sm font-normal text-default-600 bg-default-100"
|
|
||||||
href={siteConfig.links.sponsor}
|
|
||||||
startContent={<HeartFilledIcon className="text-danger" />}
|
|
||||||
variant="flat"
|
|
||||||
>
|
|
||||||
Sponsor
|
|
||||||
</Button>
|
|
||||||
</NavbarItem> */}
|
|
||||||
</NavbarContent>
|
</NavbarContent>
|
||||||
|
|
||||||
<NavbarContent className="sm:hidden basis-1 pl-4" justify="end">
|
<NavbarContent className="sm:hidden basis-1 pl-4" justify="end">
|
||||||
<Link isExternal href={siteConfig.links.github} aria-label="Github">
|
<NextUiLink
|
||||||
|
isExternal
|
||||||
|
href={siteConfig.links.github}
|
||||||
|
aria-label="Github"
|
||||||
|
>
|
||||||
<GithubIcon className="text-default-500" />
|
<GithubIcon className="text-default-500" />
|
||||||
</Link>
|
</NextUiLink>
|
||||||
<ThemeSwitch />
|
<ThemeSwitch />
|
||||||
<NavbarMenuToggle />
|
<NavbarMenuToggle />
|
||||||
</NavbarContent>
|
</NavbarContent>
|
||||||
|
|
||||||
<NavbarMenu>
|
|
||||||
{searchInput}
|
|
||||||
<div className="mx-4 mt-2 flex flex-col gap-2">
|
|
||||||
{siteConfig.navMenuItems.map((item, index) => (
|
|
||||||
<NavbarMenuItem key={`${item}-${index}`}>
|
|
||||||
<Link
|
|
||||||
color={
|
|
||||||
index === 2
|
|
||||||
? "primary"
|
|
||||||
: index === siteConfig.navMenuItems.length - 1
|
|
||||||
? "danger"
|
|
||||||
: "foreground"
|
|
||||||
}
|
|
||||||
href="#"
|
|
||||||
size="lg"
|
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
</Link>
|
|
||||||
</NavbarMenuItem>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</NavbarMenu>
|
|
||||||
</NextUINavbar>
|
</NextUINavbar>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
9
frontend/messages/en.json
Normal file
9
frontend/messages/en.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Index": {
|
||||||
|
"title": "Hello world!"
|
||||||
|
},
|
||||||
|
"ProjectPage": {
|
||||||
|
"projects": "Projects",
|
||||||
|
"newProject": "New Project"
|
||||||
|
}
|
||||||
|
}
|
||||||
9
frontend/messages/ja.json
Normal file
9
frontend/messages/ja.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Index": {
|
||||||
|
"title": "はろー"
|
||||||
|
},
|
||||||
|
"ProjectPage": {
|
||||||
|
"projects": "プロジェクト",
|
||||||
|
"newProject": "プロジェクトの作成"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
const createNextIntlPlugin = require("next-intl/plugin");
|
||||||
|
const withNextIntl = createNextIntlPlugin();
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
typescript: {
|
typescript: {
|
||||||
@@ -7,6 +10,6 @@ const nextConfig = {
|
|||||||
// !! WARN !!
|
// !! WARN !!
|
||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = withNextIntl(nextConfig);
|
||||||
|
|||||||
104
frontend/package-lock.json
generated
104
frontend/package-lock.json
generated
@@ -24,6 +24,7 @@
|
|||||||
"intl-messageformat": "^10.5.0",
|
"intl-messageformat": "^10.5.0",
|
||||||
"lucide-react": "^0.372.0",
|
"lucide-react": "^0.372.0",
|
||||||
"next": "14.0.2",
|
"next": "14.0.2",
|
||||||
|
"next-intl": "^3.12.0",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"postcss": "8.4.31",
|
"postcss": "8.4.31",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
@@ -5204,6 +5205,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/negotiator": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/next": {
|
"node_modules/next": {
|
||||||
"version": "14.0.2",
|
"version": "14.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/next/-/next-14.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/next/-/next-14.0.2.tgz",
|
||||||
@@ -5249,6 +5258,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/next-intl": {
|
||||||
|
"version": "3.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.12.0.tgz",
|
||||||
|
"integrity": "sha512-N3DHT6ce6K4VHVA3y2p3U7wfBx4c31qEgQSTFCFJuNnE7XYzy49O576ewEz7/k2YaB/U5bfxaWWaMMkskofwoQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/amannn"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@formatjs/intl-localematcher": "^0.2.32",
|
||||||
|
"negotiator": "^0.6.3",
|
||||||
|
"use-intl": "^3.12.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next-intl/node_modules/@formatjs/intl-localematcher": {
|
||||||
|
"version": "0.2.32",
|
||||||
|
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.32.tgz",
|
||||||
|
"integrity": "sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/next-themes": {
|
"node_modules/next-themes": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz",
|
||||||
@@ -6683,6 +6720,73 @@
|
|||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-intl": {
|
||||||
|
"version": "3.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-3.12.0.tgz",
|
||||||
|
"integrity": "sha512-tTJBSaxpVF1ZHqJ5+1JOaBsPmvBPscXHR0soMNQFWIURZspOueLaMXx1XHNdBv9KZGwepBju5aWXkJ0PM6ztXg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@formatjs/ecma402-abstract": "^1.11.4",
|
||||||
|
"intl-messageformat": "^9.3.18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/use-intl/node_modules/@formatjs/ecma402-abstract": {
|
||||||
|
"version": "1.11.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz",
|
||||||
|
"integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@formatjs/intl-localematcher": "0.2.25",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/use-intl/node_modules/@formatjs/fast-memoize": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/use-intl/node_modules/@formatjs/icu-messageformat-parser": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@formatjs/ecma402-abstract": "1.11.4",
|
||||||
|
"@formatjs/icu-skeleton-parser": "1.3.6",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/use-intl/node_modules/@formatjs/icu-skeleton-parser": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@formatjs/ecma402-abstract": "1.11.4",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/use-intl/node_modules/@formatjs/intl-localematcher": {
|
||||||
|
"version": "0.2.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz",
|
||||||
|
"integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/use-intl/node_modules/intl-messageformat": {
|
||||||
|
"version": "9.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz",
|
||||||
|
"integrity": "sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@formatjs/ecma402-abstract": "1.11.4",
|
||||||
|
"@formatjs/fast-memoize": "1.2.1",
|
||||||
|
"@formatjs/icu-messageformat-parser": "2.1.0",
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/use-isomorphic-layout-effect": {
|
"node_modules/use-isomorphic-layout-effect": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"intl-messageformat": "^10.5.0",
|
"intl-messageformat": "^10.5.0",
|
||||||
"lucide-react": "^0.372.0",
|
"lucide-react": "^0.372.0",
|
||||||
"next": "14.0.2",
|
"next": "14.0.2",
|
||||||
|
"next-intl": "^3.12.0",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"postcss": "8.4.31",
|
"postcss": "8.4.31",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ export const metadata: Metadata = {
|
|||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
|
params: {locale}
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
params: {locale: string};
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang={locale} suppressHydrationWarning>
|
||||||
<head />
|
<head />
|
||||||
<body
|
<body
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
import { Link, button as buttonStyles } from "@nextui-org/react";
|
import { button as buttonStyles } from "@nextui-org/react";
|
||||||
import { title, subtitle } from "@/components/primitives";
|
import { title, subtitle } from "@/components/primitives";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Link } from "@/src/navigation";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
const t = useTranslations("Index");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex flex-col items-center justify-center gap-4 py-8 md:py-10">
|
<section className="flex flex-col items-center justify-center gap-4 py-8 md:py-10">
|
||||||
<div className="inline-block max-w-lg text-center justify-center">
|
<div className="inline-block max-w-lg text-center justify-center">
|
||||||
@@ -13,6 +17,8 @@ export default function Home() {
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h1>{t("title")}</h1>
|
||||||
|
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<Link
|
<Link
|
||||||
href="/projects"
|
href="/projects"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
"use client";
|
// "use client";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Button } from "@nextui-org/react";
|
import { Button } from "@nextui-org/react";
|
||||||
import { Plus } from "lucide-react";
|
import { Plus } from "lucide-react";
|
||||||
@@ -11,8 +11,10 @@ import {
|
|||||||
updateProject,
|
updateProject,
|
||||||
deleteProject,
|
deleteProject,
|
||||||
} from "./projectsControl";
|
} from "./projectsControl";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export default function ProjectsPage() {
|
export default function ProjectsPage() {
|
||||||
|
const t = useTranslations("ProjectsPage");
|
||||||
const [projects, setProjects] = useState([]);
|
const [projects, setProjects] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -78,7 +80,7 @@ export default function ProjectsPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-3xl pt-16 px-6 flex-grow">
|
<div className="container mx-auto max-w-3xl pt-16 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">Projects</h3>
|
<h3 className="font-bold">{t("project.project")}</h3>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
startContent={<Plus size={16} />}
|
startContent={<Plus size={16} />}
|
||||||
@@ -86,7 +88,7 @@ export default function ProjectsPage() {
|
|||||||
color="primary"
|
color="primary"
|
||||||
onClick={openDialogForCreate}
|
onClick={openDialogForCreate}
|
||||||
>
|
>
|
||||||
New Project
|
{t("newProject")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Image, Button, Tooltip, Card, CardBody } from "@nextui-org/react";
|
import { Image, Button, Tooltip, Card, CardBody } from "@nextui-org/react";
|
||||||
import { AttachmentType } from "../../../../../../../types/case";
|
import { AttachmentType } from "../../../../../../../../types/case";
|
||||||
import { Trash, ArrowDownToLine } from "lucide-react";
|
import { Trash, ArrowDownToLine } from "lucide-react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Textarea, Button, Tooltip } from "@nextui-org/react";
|
import { Textarea, Button, Tooltip } from "@nextui-org/react";
|
||||||
import { StepType } from "../../../../../../../types/case";
|
import { StepType } from "../../../../../../../../types/case";
|
||||||
import { Plus, Trash } from "lucide-react";
|
import { Plus, Trash } from "lucide-react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
12
frontend/src/i18n.ts
Normal file
12
frontend/src/i18n.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { notFound } from "next/navigation";
|
||||||
|
import { getRequestConfig } from "next-intl/server";
|
||||||
|
|
||||||
|
const locales = ["en", "ja"];
|
||||||
|
|
||||||
|
export default getRequestConfig(async ({ locale }) => {
|
||||||
|
if (!locales.includes(locale as any)) notFound();
|
||||||
|
|
||||||
|
return {
|
||||||
|
messages: (await import(`../messages/${locale}.json`)).default,
|
||||||
|
};
|
||||||
|
});
|
||||||
12
frontend/src/middleware.ts
Normal file
12
frontend/src/middleware.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import createMiddleware from "next-intl/middleware";
|
||||||
|
import { locales, localePrefix } from "./navigation";
|
||||||
|
|
||||||
|
export default createMiddleware({
|
||||||
|
defaultLocale: "en",
|
||||||
|
localePrefix,
|
||||||
|
locales,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: ["/", "/(ja|en)/:path*"],
|
||||||
|
};
|
||||||
7
frontend/src/navigation.ts
Normal file
7
frontend/src/navigation.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { createSharedPathnamesNavigation } from "next-intl/navigation";
|
||||||
|
|
||||||
|
export const locales = ["en", "ja"] as const;
|
||||||
|
export const localePrefix = "always";
|
||||||
|
|
||||||
|
export const { Link, redirect, usePathname, useRouter } =
|
||||||
|
createSharedPathnamesNavigation({ locales, localePrefix });
|
||||||
Reference in New Issue
Block a user