diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 5ea95c8..72dacf0 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -111,7 +111,6 @@ "your_projects": "Your Projects", "public": "Public", "private": "Private", - "no_projects_found": "No projects found", "not_own_any_projects": "You don't own any projects.", "find_projects": "Find projects" }, @@ -134,7 +133,7 @@ "at_least": "At least one administrator is required" }, "Projects": { - "projectList": "Project List", + "project_list": "Project List", "new_project": "New Project", "id": "ID", "publicity": "Publicity", @@ -146,6 +145,7 @@ "no_projects_found": "No projects found" }, "Project": { + "project": "Project", "home": "Home", "test_cases": "Test Cases", "test_runs": "Test Runs", @@ -153,6 +153,7 @@ "settings": "Settings" }, "Home": { + "home": "Home", "Folders": "Folders", "test_cases": "Test Cases", "test_runs": "Test Runs", diff --git a/frontend/messages/ja.json b/frontend/messages/ja.json index a347664..dabd405 100644 --- a/frontend/messages/ja.json +++ b/frontend/messages/ja.json @@ -134,7 +134,7 @@ "at_least": "最低1人以上の管理者が必要です。" }, "Projects": { - "projectList": "プロジェクト一覧", + "project_list": "プロジェクト一覧", "new_project": "新規プロジェクト", "id": "ID", "publicity": "公開", @@ -146,6 +146,7 @@ "no_projects_found": "プロジェクトがありません" }, "Project": { + "project": "プロジェクト", "home": "ホーム", "test_cases": "テストケース", "test_runs": "テストラン", @@ -153,6 +154,7 @@ "settings": "設定" }, "Home": { + "home": "ホーム", "Folders": "フォルダー", "test_cases": "テストケース", "test_runs": "テストラン", diff --git a/frontend/src/app/[locale]/account/layout.tsx b/frontend/src/app/[locale]/account/layout.tsx index d36d148..e03958b 100644 --- a/frontend/src/app/[locale]/account/layout.tsx +++ b/frontend/src/app/[locale]/account/layout.tsx @@ -1,3 +1,14 @@ +import { LocaleCodeType } from '@/types/locale'; +import { getTranslations } from 'next-intl/server'; + +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Auth' }); + return { + title: `${t('account')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function AuthLayout({ children }: { children: React.ReactNode }) { return ( <> diff --git a/frontend/src/app/[locale]/account/page.tsx b/frontend/src/app/[locale]/account/page.tsx index 20e4a57..46dce8e 100644 --- a/frontend/src/app/[locale]/account/page.tsx +++ b/frontend/src/app/[locale]/account/page.tsx @@ -9,7 +9,6 @@ export default function Page({ params }: PageType) { yourProjects: t('your_projects'), public: t('public'), private: t('private'), - noProjectsFound: t('no_projects_found'), notOwnAnyProjects: t('not_own_any_projects'), findProjects: t('find_projects'), }; diff --git a/frontend/src/app/[locale]/account/signin/page.tsx b/frontend/src/app/[locale]/account/signin/page.tsx index c169a12..92da2f5 100644 --- a/frontend/src/app/[locale]/account/signin/page.tsx +++ b/frontend/src/app/[locale]/account/signin/page.tsx @@ -1,8 +1,17 @@ import { PageType } from '@/types/base'; import AuthPage from '../authPage'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import { LocaleCodeType } from '@/types/locale'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Auth' }); + return { + title: `${t('signin')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: PageType) { const t = useTranslations('Auth'); const messages = { diff --git a/frontend/src/app/[locale]/account/signup/page.tsx b/frontend/src/app/[locale]/account/signup/page.tsx index 495247c..eec62e2 100644 --- a/frontend/src/app/[locale]/account/signup/page.tsx +++ b/frontend/src/app/[locale]/account/signup/page.tsx @@ -1,8 +1,17 @@ import { PageType } from '@/types/base'; import AuthPage from '../authPage'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import { LocaleCodeType } from '@/types/locale'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Auth' }); + return { + title: `${t('signup')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: PageType) { const t = useTranslations('Auth'); const messages = { diff --git a/frontend/src/app/[locale]/admin/page.tsx b/frontend/src/app/[locale]/admin/page.tsx index dab73bd..b47bf46 100644 --- a/frontend/src/app/[locale]/admin/page.tsx +++ b/frontend/src/app/[locale]/admin/page.tsx @@ -1,9 +1,18 @@ +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import AdminPage from './AdminPage'; import { PageType } from '@/types/base'; import { LocaleCodeType } from '@/types/locale'; import { AdminMessages } from '@/types/user'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Admin' }); + return { + title: `${t('user_management')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: PageType) { const t = useTranslations('Admin'); const messages: AdminMessages = { diff --git a/frontend/src/app/[locale]/layout.tsx b/frontend/src/app/[locale]/layout.tsx index a478ad9..2512e37 100644 --- a/frontend/src/app/[locale]/layout.tsx +++ b/frontend/src/app/[locale]/layout.tsx @@ -6,17 +6,26 @@ import clsx from 'clsx'; import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import { LocaleCodeType } from '@/types/locale'; +import { headers } from 'next/headers'; export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const headersList = headers(); + const host = headersList.get('host'); + const isOfficialDomain = host === 'unittcms.org' ? true : false; const t = await getTranslations({ locale, namespace: 'Header' }); + return { - title: t('title'), + title: `${t('title')} | UnitTCMS`, description: t('description'), icons: { icon: '/favicon/favicon.ico', shortcut: '/favicon/favicon-16x16.png', apple: '/favicon/apple-touch-icon.png', }, + alternates: { + canonical: `https://www.unittcms.org/${locale}`, + }, + robots: isOfficialDomain ? { index: true, follow: true } : { index: false, follow: true }, }; } diff --git a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx index 9247666..e301459 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/folders/[folderId]/cases/page.tsx @@ -1,8 +1,17 @@ import { PriorityMessages } from '@/types/priority'; import CasesPane from './CasesPane'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import { LocaleCodeType } from '@/types/locale'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Cases' }); + return { + title: `${t('test_case_list')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: { params: { projectId: string; folderId: string; locale: string } }) { const t = useTranslations('Cases'); const messages = { diff --git a/frontend/src/app/[locale]/projects/[projectId]/home/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/home/page.tsx index dc862f8..f15bb83 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/home/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/home/page.tsx @@ -1,4 +1,6 @@ +import { LocaleCodeType } from '@/types/locale'; import { ProjectHome } from './ProjectHome'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import { PriorityMessages } from '@/types/priority'; import { TestTypeMessages } from '@/types/testType'; @@ -14,6 +16,14 @@ export type HomeMessages = { byPriority: string; }; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Home' }); + return { + title: `${t('home')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: { params: { projectId: string } }) { const t = useTranslations('Home'); const messages = { diff --git a/frontend/src/app/[locale]/projects/[projectId]/members/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/members/page.tsx index 620f001..465daaa 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/members/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/members/page.tsx @@ -1,6 +1,16 @@ +import { LocaleCodeType } from '@/types/locale'; import MembersPage from './MembersPage'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Members' }); + return { + title: `${t('member_management')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: { params: { projectId: string; locale: string } }) { const t = useTranslations('Members'); const messages = { diff --git a/frontend/src/app/[locale]/projects/[projectId]/runs/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/runs/page.tsx index 35855cf..7ab5f70 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/runs/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/runs/page.tsx @@ -1,7 +1,16 @@ import { LocaleCodeType } from '@/types/locale'; import RunsPage from './RunsPage'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Runs' }); + return { + title: `${t('run_list')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: { params: { projectId: string; locale: string } }) { const t = useTranslations('Runs'); const messages = { diff --git a/frontend/src/app/[locale]/projects/[projectId]/settings/page.tsx b/frontend/src/app/[locale]/projects/[projectId]/settings/page.tsx index 87f2b53..0a34a7b 100644 --- a/frontend/src/app/[locale]/projects/[projectId]/settings/page.tsx +++ b/frontend/src/app/[locale]/projects/[projectId]/settings/page.tsx @@ -1,8 +1,18 @@ +import { LocaleCodeType } from '@/types/locale'; import { ProjectDialogMessages } from '@/types/project'; import SettingsPage from './SettingsPage'; +import { getTranslations } from 'next-intl/server'; import { useTranslations } from 'next-intl'; import { SettingsMessages } from '@/types/settings'; +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Settings' }); + return { + title: `${t('project_management')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function Page({ params }: { params: { projectId: string; locale: string } }) { const t = useTranslations('Settings'); const messages: SettingsMessages = { diff --git a/frontend/src/app/[locale]/projects/layout.tsx b/frontend/src/app/[locale]/projects/layout.tsx index 9ed1a3f..e82e979 100644 --- a/frontend/src/app/[locale]/projects/layout.tsx +++ b/frontend/src/app/[locale]/projects/layout.tsx @@ -1,3 +1,14 @@ +import { LocaleCodeType } from '@/types/locale'; +import { getTranslations } from 'next-intl/server'; + +export async function generateMetadata({ params: { locale } }: { params: { locale: LocaleCodeType } }) { + const t = await getTranslations({ locale, namespace: 'Projects' }); + return { + title: `${t('project_list')} | UnitTCMS`, + robots: { index: false, follow: false }, + }; +} + export default function ProjectsLayout({ children }: { children: React.ReactNode }) { return <>{children}; } diff --git a/frontend/src/app/[locale]/projects/page.tsx b/frontend/src/app/[locale]/projects/page.tsx index 24e264f..2c64d5d 100644 --- a/frontend/src/app/[locale]/projects/page.tsx +++ b/frontend/src/app/[locale]/projects/page.tsx @@ -7,7 +7,7 @@ import { ProjectDialogMessages, ProjectsMessages } from '@/types/project'; export default function Page({ params }: PageType) { const t = useTranslations('Projects'); const messages: ProjectsMessages = { - projectList: t('projectList'), + projectList: t('project_list'), newProject: t('new_project'), id: t('id'), publicity: t('publicity'),