feat: 精简多语言支持并添加404页面

This commit is contained in:
2026-03-21 15:39:09 +08:00
parent d97e6c66d6
commit 370b421eed
13 changed files with 70 additions and 285 deletions

View File

@@ -32,6 +32,10 @@ enum I18nKey {
author = "author",
publishedAt = "publishedAt",
license = "license",
notFound = "notFound",
notFoundDesc = "notFoundDesc",
backToHome = "backToHome",
}
export default I18nKey;

View File

@@ -35,4 +35,8 @@ export const en: Translation = {
[Key.author]: "Author",
[Key.publishedAt]: "Published at",
[Key.license]: "License",
[Key.notFound]: "Page Not Found",
[Key.notFoundDesc]: "The link is broken, the page has gone missing",
[Key.backToHome]: "Back to Home",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const es: Translation = {
[Key.home]: "Inicio",
[Key.about]: "Sobre mí",
[Key.archive]: "Archivo",
[Key.search]: "Buscar",
[Key.tags]: "Etiquetas",
[Key.categories]: "Categorías",
[Key.recentPosts]: "Publicaciones recientes",
[Key.comments]: "Comentarios",
[Key.untitled]: "Sin título",
[Key.uncategorized]: "Sin categoría",
[Key.noTags]: "Sin etiquetas",
[Key.wordCount]: "palabra",
[Key.wordsCount]: "palabras",
[Key.minuteCount]: "minuto",
[Key.minutesCount]: "minutos",
[Key.postCount]: "publicación",
[Key.postsCount]: "publicaciones",
[Key.themeColor]: "Color del tema",
[Key.lightMode]: "Claro",
[Key.darkMode]: "Oscuro",
[Key.systemMode]: "Sistema",
[Key.more]: "Más",
[Key.author]: "Autor",
[Key.publishedAt]: "Publicado el",
[Key.license]: "Licencia",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const id: Translation = {
[Key.home]: "Beranda",
[Key.about]: "Tentang",
[Key.archive]: "Arsip",
[Key.search]: "Cari",
[Key.tags]: "Tag",
[Key.categories]: "Kategori",
[Key.recentPosts]: "Postingan Terbaru",
[Key.comments]: "Komentar",
[Key.untitled]: "Tanpa Judul",
[Key.uncategorized]: "Tanpa Kategori",
[Key.noTags]: "Tanpa Tag",
[Key.wordCount]: "kata",
[Key.wordsCount]: "kata",
[Key.minuteCount]: "menit",
[Key.minutesCount]: "menit",
[Key.postCount]: "postingan",
[Key.postsCount]: "postingan",
[Key.themeColor]: "Warna Tema",
[Key.lightMode]: "Terang",
[Key.darkMode]: "Gelap",
[Key.systemMode]: "Sistem",
[Key.more]: "Lainnya",
[Key.author]: "Penulis",
[Key.publishedAt]: "Diterbitkan pada",
[Key.license]: "Lisensi",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const ja: Translation = {
[Key.home]: "Home",
[Key.about]: "About",
[Key.archive]: "Archive",
[Key.search]: "検索",
[Key.tags]: "タグ",
[Key.categories]: "カテゴリ",
[Key.recentPosts]: "最近の投稿",
[Key.comments]: "コメント",
[Key.untitled]: "タイトルなし",
[Key.uncategorized]: "カテゴリなし",
[Key.noTags]: "タグなし",
[Key.wordCount]: "文字",
[Key.wordsCount]: "文字",
[Key.minuteCount]: "分",
[Key.minutesCount]: "分",
[Key.postCount]: "件の投稿",
[Key.postsCount]: "件の投稿",
[Key.themeColor]: "テーマカラー",
[Key.lightMode]: "ライト",
[Key.darkMode]: "ダーク",
[Key.systemMode]: "システム",
[Key.more]: "もっと",
[Key.author]: "作者",
[Key.publishedAt]: "公開日",
[Key.license]: "ライセンス",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const ko: Translation = {
[Key.home]: "홈",
[Key.about]: "소개",
[Key.archive]: "아카이브",
[Key.search]: "검색",
[Key.tags]: "태그",
[Key.categories]: "카테고리",
[Key.recentPosts]: "최근 게시물",
[Key.comments]: "댓글",
[Key.untitled]: "제목 없음",
[Key.uncategorized]: "분류되지 않음",
[Key.noTags]: "태그 없음",
[Key.wordCount]: "단어",
[Key.wordsCount]: "단어",
[Key.minuteCount]: "분",
[Key.minutesCount]: "분",
[Key.postCount]: "게시물",
[Key.postsCount]: "게시물",
[Key.themeColor]: "테마 색상",
[Key.lightMode]: "밝은 모드",
[Key.darkMode]: "어두운 모드",
[Key.systemMode]: "시스템 모드",
[Key.more]: "더 보기",
[Key.author]: "저자",
[Key.publishedAt]: "게시일",
[Key.license]: "라이선스",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const th: Translation = {
[Key.home]: "หน้าแรก",
[Key.about]: "เกี่ยวกับ",
[Key.archive]: "คลัง",
[Key.search]: "ค้นหา",
[Key.tags]: "ป้ายกำกับ",
[Key.categories]: "หมวดหมู่",
[Key.recentPosts]: "โพสต์ล่าสุด",
[Key.comments]: "ความคิดเห็น",
[Key.untitled]: "ไม่ได้ตั้งชื่อ",
[Key.uncategorized]: "ไม่ได้จัดหมวดหมู่",
[Key.noTags]: "ไม่มีป้ายกำกับ",
[Key.wordCount]: "คำ",
[Key.wordsCount]: "คำ",
[Key.minuteCount]: "นาที",
[Key.minutesCount]: "นาที",
[Key.postCount]: "โพสต์",
[Key.postsCount]: "โพสต์",
[Key.themeColor]: "สีของธีม",
[Key.lightMode]: "สว่าง",
[Key.darkMode]: "มืด",
[Key.systemMode]: "ตามระบบ",
[Key.more]: "ดูเพิ่ม",
[Key.author]: "ผู้เขียน",
[Key.publishedAt]: "เผยแพร่เมื่อ",
[Key.license]: "สัญญาอนุญาต",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const tr: Translation = {
[Key.home]: "Anasayfa",
[Key.about]: "Hakkında",
[Key.archive]: "Arşiv",
[Key.search]: "Ara",
[Key.tags]: "Taglar",
[Key.categories]: "Katagoriler",
[Key.recentPosts]: "Son Paylaşımlar",
[Key.comments]: "Yorumlar",
[Key.untitled]: "Başlıksız",
[Key.uncategorized]: "Katagorisiz",
[Key.noTags]: "Tag Bulunamadı",
[Key.wordCount]: "kelime",
[Key.wordsCount]: "kelime",
[Key.minuteCount]: "dakika",
[Key.minutesCount]: "dakika",
[Key.postCount]: "gönderi",
[Key.postsCount]: "gönderiler",
[Key.themeColor]: "Tema Rengi",
[Key.lightMode]: "Aydınlık",
[Key.darkMode]: "Koyu",
[Key.systemMode]: "Sistem",
[Key.more]: "Daha Fazla",
[Key.author]: "Yazar",
[Key.publishedAt]: "Yayınlanma:",
[Key.license]: "Lisans",
};

View File

@@ -1,38 +0,0 @@
import Key from "../i18nKey";
import type { Translation } from "../translation";
export const vi: Translation = {
[Key.home]: "Trang chủ",
[Key.about]: "Giới thiệu",
[Key.archive]: "Kho bài",
[Key.search]: "Tìm kiếm",
[Key.tags]: "Thẻ",
[Key.categories]: "Danh mục",
[Key.recentPosts]: "Bài viết mới nhất",
[Key.comments]: "Bình luận",
[Key.untitled]: "Không tiêu đề",
[Key.uncategorized]: "Chưa phân loại",
[Key.noTags]: "Chưa có thẻ",
[Key.wordCount]: "từ",
[Key.wordsCount]: "từ",
[Key.minuteCount]: "phút đọc",
[Key.minutesCount]: "phút đọc",
[Key.postCount]: "bài viết",
[Key.postsCount]: "bài viết",
[Key.themeColor]: "Màu giao diện",
[Key.lightMode]: "Sáng",
[Key.darkMode]: "Tối",
[Key.systemMode]: "Hệ thống",
[Key.more]: "Thêm",
[Key.author]: "Tác giả",
[Key.publishedAt]: "Đăng vào lúc",
[Key.license]: "Giấy phép bản quyền",
};

View File

@@ -35,4 +35,8 @@ export const zh_CN: Translation = {
[Key.author]: "作者",
[Key.publishedAt]: "发布于",
[Key.license]: "许可协议",
[Key.notFound]: "页面未找到",
[Key.notFoundDesc]: "你访问的链接已断开,页面走丢了",
[Key.backToHome]: "返回首页",
};

View File

@@ -35,4 +35,8 @@ export const zh_TW: Translation = {
[Key.author]: "作者",
[Key.publishedAt]: "發佈於",
[Key.license]: "許可協議",
[Key.notFound]: "頁面未找到",
[Key.notFoundDesc]: "你訪問的連結已斷開,頁面走丟了",
[Key.backToHome]: "返回首頁",
};

View File

@@ -1,13 +1,6 @@
import { siteConfig } from "../config";
import type I18nKey from "./i18nKey";
import { en } from "./languages/en";
import { es } from "./languages/es";
import { id } from "./languages/id";
import { ja } from "./languages/ja";
import { ko } from "./languages/ko";
import { th } from "./languages/th";
import { tr } from "./languages/tr";
import { vi } from "./languages/vi";
import { zh_CN } from "./languages/zh_CN";
import { zh_TW } from "./languages/zh_TW";
@@ -18,24 +11,12 @@ export type Translation = {
const defaultTranslation = en;
const map: { [key: string]: Translation } = {
es: es,
en: en,
en_us: en,
en_gb: en,
en_au: en,
zh_cn: zh_CN,
zh_tw: zh_TW,
ja: ja,
ja_jp: ja,
ko: ko,
ko_kr: ko,
th: th,
th_th: th,
vi: vi,
vi_vn: vi,
id: id,
tr: tr,
tr_tr: tr,
};
export function getTranslation(lang: string): Translation {

54
src/pages/404.astro Normal file
View File

@@ -0,0 +1,54 @@
---
import { Icon } from "astro-icon/components";
import I18nKey from "../i18n/i18nKey";
import { i18n } from "../i18n/translation";
import MainGridLayout from "../layouts/MainGridLayout.astro";
import { url } from "../utils/url-utils";
---
<MainGridLayout title={i18n(I18nKey.notFound)}>
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative min-h-[70vh]">
<div class="card-base z-10 px-9 py-6 relative w-full flex flex-col items-center justify-center">
<div class="onload-animation flex flex-col items-center justify-center text-center">
<h2 class="text-2xl md:text-3xl font-bold mb-8 text-90">
{i18n(I18nKey.notFound)}
</h2>
<div class="flex items-center justify-center gap-4 md:gap-6 mb-6">
<div class="relative">
<div class="absolute inset-0 blur-3xl opacity-20 bg-[var(--primary)] rounded-full"></div>
<Icon
name="fa6-solid:link-slash"
class="relative text-[8rem] md:text-[10rem] text-[var(--primary)] opacity-80 dark:opacity-60"
/>
</div>
<h1 class="text-7xl md:text-9xl font-bold text-[var(--primary)] opacity-90">
404
</h1>
</div>
<p class="text-lg text-75 mb-10 max-w-md">
{i18n(I18nKey.notFoundDesc)}
</p>
<a
href={url("/")}
class="btn-regular rounded-xl h-12 px-8 font-bold text-lg active:scale-95 transition
flex items-center hover:gap-3"
>
{i18n(I18nKey.backToHome)}
</a>
</div>
</div>
</div>
</MainGridLayout>
<style>
.btn-regular {
transition: all 200ms ease;
}
.btn-regular:hover {
gap: 0.75rem;
}
</style>