mirror of
https://github.com/KivotosRailway/website.git
synced 2026-11-03 11:06:32 +09:00
修改页面标题路由
This commit is contained in:
+4
-1
@@ -4,7 +4,10 @@ import { SiteFooter } from "@/components/layout/site-footer";
|
||||
import { SiteHeader } from "@/components/layout/site-header";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Kivotos Railway",
|
||||
title: {
|
||||
default: "基沃托斯铁道公团 KivotosRailway",
|
||||
template: "%s | 基沃托斯铁道公团 KivotosRailway",
|
||||
},
|
||||
description: "Kivotos Railway website",
|
||||
icons: {
|
||||
icon: "/icon/icon.svg",
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { getNewsBySlug, markdownToHtml } from "@/data/news";
|
||||
import { PageBreadcrumb } from "@/components/layout/page-breadcrumb";
|
||||
import { NewsShare } from "@/components/news/news-share";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { slug } = await params;
|
||||
const item = await getNewsBySlug(slug);
|
||||
|
||||
return {
|
||||
title: item?.title ?? "新闻",
|
||||
};
|
||||
}
|
||||
|
||||
export default async function NewsDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import Link from "next/link";
|
||||
import type { Metadata } from "next";
|
||||
import { getNewsList } from "@/data/news";
|
||||
import { PageBreadcrumb } from "@/components/layout/page-breadcrumb";
|
||||
import { NewsList } from "@/components/news/news-list";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "新闻",
|
||||
};
|
||||
|
||||
export default async function NewsPage() {
|
||||
const news = await getNewsList();
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import Link from "next/link";
|
||||
import { getLocaleMessages } from "@/lib/i18n";
|
||||
|
||||
export function PageBreadcrumb({ items }: { items: Array<{ label: string; href?: string }> }) {
|
||||
return (
|
||||
<nav className="page-breadcrumb" aria-label="页面位置">
|
||||
<nav className="page-breadcrumb" aria-label={getLocaleMessages("zh-CN").common.pagePosition}>
|
||||
{items.map((item, index) => (
|
||||
<span className="page-breadcrumb-item" key={`${item.label}-${index}`}>
|
||||
{index > 0 && <span className="page-breadcrumb-separator" aria-hidden="true">›</span>}
|
||||
|
||||
@@ -10,7 +10,23 @@ export function SiteHeader() {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const syncLocale = (nextLocale: Locale) => setLocale(nextLocale);
|
||||
const updateDocumentTitle = (nextLocale: Locale) => {
|
||||
const messages = getLocaleMessages(nextLocale);
|
||||
const pathname = window.location.pathname;
|
||||
const currentTitle = document.title.split(" | ")[0];
|
||||
const pageLabel = pathname === "/"
|
||||
? ""
|
||||
: pathname === "/news"
|
||||
? messages.common.news
|
||||
: currentTitle;
|
||||
|
||||
document.title = pageLabel ? `${pageLabel} | ${messages.common.siteTitle}` : messages.common.siteTitle;
|
||||
};
|
||||
|
||||
const syncLocale = (nextLocale: Locale) => {
|
||||
setLocale(nextLocale);
|
||||
updateDocumentTitle(nextLocale);
|
||||
};
|
||||
|
||||
const handleLocaleChange = (event: Event) => {
|
||||
const nextLocale = (event as CustomEvent<{ locale?: Locale }>).detail?.locale ?? getInitialLocale();
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import type { NewsItem } from "@/data/news";
|
||||
import { getInitialLocale, getLocaleMessages, type Locale } from "@/lib/i18n";
|
||||
|
||||
export function NewsList({ news }: { news: NewsItem[] }) {
|
||||
const [activeCategory, setActiveCategory] = useState<string | null>(null);
|
||||
const [locale, setLocale] = useState<Locale>("zh-CN");
|
||||
const messages = getLocaleMessages(locale);
|
||||
|
||||
useEffect(() => {
|
||||
const syncLocale = () => setLocale(getInitialLocale());
|
||||
syncLocale();
|
||||
window.addEventListener("kr-locale-change", syncLocale);
|
||||
window.addEventListener("storage", syncLocale);
|
||||
return () => {
|
||||
window.removeEventListener("kr-locale-change", syncLocale);
|
||||
window.removeEventListener("storage", syncLocale);
|
||||
};
|
||||
}, []);
|
||||
const categories = Array.from(new Set(news.map((item) => item.category).filter(Boolean)));
|
||||
const visibleNews = activeCategory
|
||||
? news.filter((item) => item.category === activeCategory)
|
||||
@@ -20,7 +34,7 @@ export function NewsList({ news }: { news: NewsItem[] }) {
|
||||
className={`news-filter-button${activeCategory === null ? " active" : ""}`}
|
||||
onClick={() => setActiveCategory(null)}
|
||||
>
|
||||
全部
|
||||
{messages.common.all}
|
||||
</button>
|
||||
{categories.map((category) => (
|
||||
<button
|
||||
@@ -34,7 +48,7 @@ export function NewsList({ news }: { news: NewsItem[] }) {
|
||||
))}
|
||||
</div>
|
||||
<div className="news-toolbar-right">
|
||||
<button type="button" className="news-view-toggle" aria-label="列表视图">☰</button>
|
||||
<button type="button" className="news-view-toggle" aria-label={messages.common.listView}>☰</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { getInitialLocale, getLocaleMessages, type Locale } from "@/lib/i18n";
|
||||
|
||||
export function NewsShare({ title }: { title: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [locale, setLocale] = useState<Locale>("zh-CN");
|
||||
const messages = getLocaleMessages(locale);
|
||||
|
||||
useEffect(() => {
|
||||
const syncLocale = () => setLocale(getInitialLocale());
|
||||
syncLocale();
|
||||
window.addEventListener("kr-locale-change", syncLocale);
|
||||
window.addEventListener("storage", syncLocale);
|
||||
return () => {
|
||||
window.removeEventListener("kr-locale-change", syncLocale);
|
||||
window.removeEventListener("storage", syncLocale);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getPageUrl = () => window.location.href;
|
||||
|
||||
@@ -27,13 +41,13 @@ export function NewsShare({ title }: { title: string }) {
|
||||
|
||||
return (
|
||||
<section className="news-share" aria-labelledby="news-share-title">
|
||||
<h2 id="news-share-title">分享</h2>
|
||||
<h2 id="news-share-title">{messages.common.share}</h2>
|
||||
<div className="news-share-actions">
|
||||
<button type="button" className="news-share-button" onClick={copyLink} aria-label="复制链接">
|
||||
{copied ? "已复制" : "复制链接"}
|
||||
<button type="button" className="news-share-button" onClick={copyLink} aria-label={messages.common.copyLink}>
|
||||
{copied ? messages.common.copied : messages.common.copyLink}
|
||||
</button>
|
||||
<button type="button" className="news-share-button news-share-x" onClick={shareOnX} aria-label="分享到 X">X</button>
|
||||
<button type="button" className="news-share-button news-share-qq" onClick={shareOnQq} aria-label="分享到 QQ">QQ</button>
|
||||
<button type="button" className="news-share-button news-share-x" onClick={shareOnX} aria-label={messages.common.shareX}>X</button>
|
||||
<button type="button" className="news-share-button news-share-qq" onClick={shareOnQq} aria-label={messages.common.shareQq}>QQ</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
+15
-1
@@ -5,12 +5,26 @@
|
||||
},
|
||||
"home": {
|
||||
"kicker": "KIVOTOS RAILWAY / MINECRAFT SERVER",
|
||||
"title": ["Connecting every journey", "by rail"],
|
||||
"title": ["Railways", "connect us"],
|
||||
"subtitle": "A Minecraft railway world built and expanded by players together.",
|
||||
"cta": "Explore KivotosRailway",
|
||||
"latest": "Latest News",
|
||||
"more": "View more"
|
||||
},
|
||||
"common": {
|
||||
"siteTitle": "KivotosRailway",
|
||||
"home": "Home",
|
||||
"news": "News",
|
||||
"share": "Share",
|
||||
"copyLink": "Copy link",
|
||||
"copied": "Copied",
|
||||
"shareX": "Share on X",
|
||||
"shareQq": "Share on QQ",
|
||||
"all": "All",
|
||||
"listView": "List view",
|
||||
"pagePosition": "Page position",
|
||||
"backToNews": "Back to news list"
|
||||
},
|
||||
"footer": {
|
||||
"follow": "Follow us",
|
||||
"social": ["Weibo", "WeChat", "X", "LinkedIn", "Video"],
|
||||
|
||||
@@ -11,6 +11,20 @@
|
||||
"latest": "最新ニュース",
|
||||
"more": "もっと見る"
|
||||
},
|
||||
"common": {
|
||||
"siteTitle": "KivotosRailway",
|
||||
"home": "ホーム",
|
||||
"news": "ニュース",
|
||||
"share": "共有",
|
||||
"copyLink": "リンクをコピー",
|
||||
"copied": "コピーしました",
|
||||
"shareX": "Xで共有",
|
||||
"shareQq": "QQで共有",
|
||||
"all": "すべて",
|
||||
"listView": "リスト表示",
|
||||
"pagePosition": "ページの位置",
|
||||
"backToNews": "ニュース一覧へ戻る"
|
||||
},
|
||||
"footer": {
|
||||
"follow": "フォローする",
|
||||
"social": ["Weibo", "WeChat", "X", "LinkedIn", "動画"],
|
||||
|
||||
+15
-1
@@ -11,6 +11,20 @@
|
||||
"latest": "最新资讯",
|
||||
"more": "浏览更多"
|
||||
},
|
||||
"common": {
|
||||
"siteTitle": "基沃托斯铁道公团 KivotosRailway",
|
||||
"home": "首页",
|
||||
"news": "新闻",
|
||||
"share": "分享",
|
||||
"copyLink": "复制链接",
|
||||
"copied": "已复制",
|
||||
"shareX": "分享到 X",
|
||||
"shareQq": "分享到 QQ",
|
||||
"all": "全部",
|
||||
"listView": "列表视图",
|
||||
"pagePosition": "页面位置",
|
||||
"backToNews": "返回新闻列表"
|
||||
},
|
||||
"footer": {
|
||||
"follow": "关注我们",
|
||||
"social": ["微博", "微信", "X", "LinkedIn", "视频"],
|
||||
@@ -22,6 +36,6 @@
|
||||
"legal": ["KR Wiki", "状态监控", "友情链接"],
|
||||
"description": "Minecraft 是 Mojang Studios 的注册商标,基沃托斯铁道公团与 Mojang Studios 及微软公司、网易公司没有从属、授权或合作关系。站内提及的城市、地区、组织、品牌及相关设定,除特别说明外,均为虚构内容,不指向任何现实机构或商业实体。",
|
||||
"copyright": "© 2024 - 2026 基沃托斯铁道公团 KivotosRailway",
|
||||
"icp": "桂ICP备2025054269号-5"
|
||||
"icp": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,20 @@
|
||||
"latest": "最新資訊",
|
||||
"more": "瀏覽更多"
|
||||
},
|
||||
"common": {
|
||||
"siteTitle": "基沃托斯鐵道公團 KivotosRailway",
|
||||
"home": "首頁",
|
||||
"news": "新聞",
|
||||
"share": "分享",
|
||||
"copyLink": "複製連結",
|
||||
"copied": "已複製",
|
||||
"shareX": "分享到 X",
|
||||
"shareQq": "分享到 QQ",
|
||||
"all": "全部",
|
||||
"listView": "列表視圖",
|
||||
"pagePosition": "頁面位置",
|
||||
"backToNews": "返回新聞列表"
|
||||
},
|
||||
"footer": {
|
||||
"follow": "關注我們",
|
||||
"social": ["微博", "微信", "X", "LinkedIn", "影片"],
|
||||
|
||||
Reference in New Issue
Block a user