Initial commit

This commit is contained in:
2026-02-02 22:47:52 +03:00
committed by GitHub
commit f53016aeda
239 changed files with 84360 additions and 0 deletions

273
src/i18n/i18nKey.ts Normal file
View File

@@ -0,0 +1,273 @@
enum I18nKey {
// 加载
loading = "loading",
// 导航
home = "home",
archive = "archive",
about = "about",
search = "search",
// 文章
tags = "tags",
categories = "categories",
series = "series",
posts = "posts",
recentPosts = "recentPosts",
postList = "postList",
statistics = "statistics",
tableOfContents = "tableOfContents",
// 统计
pageViews = "pageViews",
visitors = "visitors",
statsLoading = "statsLoading",
statsError = "statsError",
// 公告栏
announcement = "announcement",
announcementClose = "announcementClose",
comments = "comments",
untitled = "untitled",
uncategorized = "uncategorized",
noTags = "noTags",
wordCount = "wordCount",
wordsCount = "wordsCount",
minuteCount = "minuteCount",
minutesCount = "minutesCount",
postCount = "postCount",
postsCount = "postsCount",
themeColor = "themeColor",
lightMode = "lightMode",
darkMode = "darkMode",
systemMode = "systemMode",
wallpaperMode = "wallpaperMode",
wallpaperFullscreen = "wallpaperFullscreen",
wallpaperBanner = "wallpaperBanner",
wallpaperNone = "wallpaperNone",
more = "more",
backTo = "backTo",
author = "author",
publishedAt = "publishedAt",
license = "license",
// 404页面
notFound = "notFound",
notFoundTitle = "notFoundTitle",
notFoundDescription = "notFoundDescription",
backToHome = "backToHome",
// 项目展示页面
projects = "projects",
projectsSubtitle = "projectsSubtitle",
projectsAll = "projectsAll",
projectsWeb = "projectsWeb",
projectsMobile = "projectsMobile",
projectsDesktop = "projectsDesktop",
projectsOther = "projectsOther",
projectTechStack = "projectTechStack",
projectLiveDemo = "projectLiveDemo",
projectSourceCode = "projectSourceCode",
projectDescription = "projectDescription",
projectStatus = "projectStatus",
projectStatusCompleted = "projectStatusCompleted",
projectStatusInProgress = "projectStatusInProgress",
projectStatusPlanned = "projectStatusPlanned",
projectsTotal = "projectsTotal",
projectsCompleted = "projectsCompleted",
projectsInProgress = "projectsInProgress",
projectsTechStack = "projectsTechStack",
projectsFeatured = "projectsFeatured",
projectsPlanned = "projectsPlanned",
projectsDemo = "projectsDemo",
projectsSource = "projectsSource",
// 技能展示页面
skills = "skills",
skillsSubtitle = "skillsSubtitle",
skillsAI = "skillsAI",
skillsBackend = "skillsBackend",
skillsClient = "skillsClient",
skillsFrontend = "skillsFrontend",
skillsDatabase = "skillsDatabase",
skillsEngines = "skillsEngines",
skillsTools = "skillsTools",
skillsOthers = "skillsOthers",
skillLevel = "skillLevel",
skillLevelBeginner = "skillLevelBeginner",
skillLevelIntermediate = "skillLevelIntermediate",
skillLevelAdvanced = "skillLevelAdvanced",
skillLevelExpert = "skillLevelExpert",
skillExperience = "skillExperience",
skillYears = "skillYears",
skillMonths = "skillMonths",
skillsTotal = "skillsTotal",
skillsExpert = "skillsExpert",
skillsAdvanced = "skillsAdvanced",
skillsIntermediate = "skillsIntermediate",
skillsBeginner = "skillsBeginner",
skillsAdvancedTitle = "skillsAdvancedTitle",
skillsProjects = "skillsProjects",
skillsDistribution = "skillsDistribution",
skillsByLevel = "skillsByLevel",
skillsByCategory = "skillsByCategory",
// 时间线页面
timeline = "timeline",
timelineSubtitle = "timelineSubtitle",
timelineEducation = "timelineEducation",
timelineWork = "timelineWork",
timelineProject = "timelineProject",
timelineAchievement = "timelineAchievement",
timelinePresent = "timelinePresent",
timelineLocation = "timelineLocation",
timelineDescription = "timelineDescription",
timelineMonths = "timelineMonths",
timelineYears = "timelineYears",
timelineTotal = "timelineTotal",
timelineProjects = "timelineProjects",
timelineExperience = "timelineExperience",
timelineCurrent = "timelineCurrent",
timelineHistory = "timelineHistory",
timelineAchievements = "timelineAchievements",
timelineStatistics = "timelineStatistics",
timelineByType = "timelineByType",
timelineWorkExperience = "timelineWorkExperience",
timelineTotalExperience = "timelineTotalExperience",
timelineWorkPositions = "timelineWorkPositions",
timelineCurrentRole = "timelineCurrentRole",
timelineEmployed = "timelineEmployed",
timelineAvailable = "timelineAvailable",
// 短文页面
diary = "diary",
diarySubtitle = "diarySubtitle",
diaryCount = "diaryCount",
diaryImage = "diaryImage",
diaryReply = "diaryReply",
diaryTips = "diaryTips",
diaryMinutesAgo = "diaryMinutesAgo",
diaryHoursAgo = "diaryHoursAgo",
diaryDaysAgo = "diaryDaysAgo",
// 相册页面
albums = "albums",
albumsSubtitle = "albumsSubtitle",
albumsEmpty = "albumsEmpty",
albumsEmptyDesc = "albumsEmptyDesc",
albumsBackToList = "albumsBackToList",
albumsPhotoCount = "albumsPhotoCount",
albumsPhotosCount = "albumsPhotosCount",
// 番剧页面
anime = "anime",
animeTitle = "animeTitle",
animeSubtitle = "animeSubtitle",
animeList = "animeList",
animeTotal = "animeTotal",
animeWatching = "animeWatching",
animeCompleted = "animeCompleted",
animeAvgRating = "animeAvgRating",
animeStatusWatching = "animeStatusWatching",
animeStatusCompleted = "animeStatusCompleted",
animeStatusPlanned = "animeStatusPlanned",
animeYear = "animeYear",
animeStudio = "animeStudio",
animeEmpty = "animeEmpty",
animeEmptyBangumi = "animeEmptyBangumi",
// 友链页面
friends = "friends",
// RSS页面
rss = "rss",
rssDescription = "rssDescription",
rssSubtitle = "rssSubtitle",
rssLink = "rssLink",
rssCopyToReader = "rssCopyToReader",
rssCopyLink = "rssCopyLink",
rssLatestPosts = "rssLatestPosts",
rssWhatIsRSS = "rssWhatIsRSS",
rssWhatIsRSSDescription = "rssWhatIsRSSDescription",
rssBenefit1 = "rssBenefit1",
rssBenefit2 = "rssBenefit2",
rssBenefit3 = "rssBenefit3",
rssBenefit4 = "rssBenefit4",
rssHowToUse = "rssHowToUse",
rssCopied = "rssCopied",
rssCopyFailed = "rssCopyFailed",
// Atom页面
atom = "atom",
atomDescription = "atomDescription",
atomSubtitle = "atomSubtitle",
atomLink = "atomLink",
atomCopyToReader = "atomCopyToReader",
atomCopyLink = "atomCopyLink",
atomLatestPosts = "atomLatestPosts",
atomWhatIsAtom = "atomWhatIsAtom",
atomWhatIsAtomDescription = "atomWhatIsAtomDescription",
atomBenefit1 = "atomBenefit1",
atomBenefit2 = "atomBenefit2",
atomBenefit3 = "atomBenefit3",
atomBenefit4 = "atomBenefit4",
atomHowToUse = "atomHowToUse",
atomCopied = "atomCopied",
atomCopyFailed = "atomCopyFailed",
// 密码保护
passwordProtected = "passwordProtected",
passwordProtectedTitle = "passwordProtectedTitle",
passwordProtectedDescription = "passwordProtectedDescription",
passwordPlaceholder = "passwordPlaceholder",
passwordUnlock = "passwordUnlock",
passwordUnlocking = "passwordUnlocking",
passwordIncorrect = "passwordIncorrect",
passwordDecryptError = "passwordDecryptError",
passwordRequired = "passwordRequired",
passwordVerifying = "passwordVerifying",
passwordDecryptFailed = "passwordDecryptFailed",
passwordDecryptRetry = "passwordDecryptRetry",
passwordUnlockButton = "passwordUnlockButton",
copyFailed = "copyFailed",
syntaxHighlightFailed = "syntaxHighlightFailed",
autoSyntaxHighlightFailed = "autoSyntaxHighlightFailed",
decryptionError = "decryptionError",
//最后编辑时间卡片
lastModifiedPrefix = "lastModifiedPrefix",
lastModifiedOutdated = "lastModifiedOutdated",
year = "year",
month = "month",
day = "day",
hour = "hour",
minute = "minute",
second = "second",
// 音乐播放器
playlist = "playlist",
musicEmptyPlaylist = "musicEmptyPlaylist",
musicNoSongsAvailable = "musicNoSongsAvailable",
musicPlayFailed = "musicPlayFailed",
musicAutoplayBlocked = "musicAutoplayBlocked",
musicMetingFailed = "musicMetingFailed",
musicUnknownArtist = "musicUnknownArtist",
musicUnknownTrack = "musicUnknownTrack",
musicSwitchToLocal = "musicSwitchToLocal",
musicSwitchToMeting = "musicSwitchToMeting",
musicProgress = "musicProgress",
musicCollapse = "musicCollapse",
musicVolume = "musicVolume",
musicExpand = "musicExpand",
}
export default I18nKey;

149
src/i18n/language.ts Normal file
View File

@@ -0,0 +1,149 @@
/**
* 统一的语言配置文件
* 所有语言相关的映射和配置都从这里导出
*/
export interface LanguageConfig {
/** 翻译服务使用的语言代码 */
translateCode: string;
/** 语言显示名称 */
displayName: string;
/** Intl.DateTimeFormat 使用的 locale */
locale: string;
/** 语言图标(国旗 emoji */
icon: string;
}
/**
* 支持的语言配置
* 单一数据源,避免重复定义
*/
export const LANGUAGE_CONFIG = {
zh: {
translateCode: "chinese_simplified",
displayName: "中文",
locale: "zh-CN",
icon: "🇨🇳",
},
en: {
translateCode: "english",
displayName: "English",
locale: "en-US",
icon: "🇺🇸",
},
ja: {
translateCode: "japanese",
displayName: "日本語",
locale: "ja-JP",
icon: "🇯🇵",
},
ko: {
translateCode: "korean",
displayName: "한국어",
locale: "ko-KR",
icon: "🇰🇷",
},
es: {
translateCode: "spanish",
displayName: "Español",
locale: "es-ES",
icon: "🇪🇸",
},
th: {
translateCode: "thai",
displayName: "ไทย",
locale: "th-TH",
icon: "🇹🇭",
},
vi: {
translateCode: "vietnamese",
displayName: "Tiếng Việt",
locale: "vi-VN",
icon: "🇻🇳",
},
tr: {
translateCode: "turkish",
displayName: "Türkçe",
locale: "tr-TR",
icon: "🇹🇷",
},
id: {
translateCode: "indonesian",
displayName: "Bahasa Indonesia",
locale: "id-ID",
icon: "🇮🇩",
},
fr: {
translateCode: "french",
displayName: "Français",
locale: "fr-FR",
icon: "🇫🇷",
},
de: {
translateCode: "german",
displayName: "Deutsch",
locale: "de-DE",
icon: "🇩🇪",
},
ru: {
translateCode: "russian",
displayName: "Русский",
locale: "ru-RU",
icon: "🇷🇺",
},
ar: {
translateCode: "arabic",
displayName: "العربية",
locale: "ar-SA",
icon: "🇸🇦",
},
} as const satisfies Record<string, LanguageConfig>;
/** 支持的语言代码列表 */
export const SUPPORTED_LANGUAGES = Object.keys(LANGUAGE_CONFIG) as Array<
keyof typeof LANGUAGE_CONFIG
>;
export type SupportedLanguage = keyof typeof LANGUAGE_CONFIG;
/**
* 配置文件语言代码到翻译服务语言代码的映射
* 自动从 LANGUAGE_CONFIG 生成
*/
export const langToTranslateMap: Record<string, string> = Object.fromEntries(
Object.entries(LANGUAGE_CONFIG).map(([lang, config]) => [
lang,
config.translateCode,
]),
);
/**
* 翻译服务语言代码到配置文件语言代码的映射
* 自动从 LANGUAGE_CONFIG 生成
*/
export const translateToLangMap: Record<string, string> = Object.fromEntries(
Object.entries(LANGUAGE_CONFIG).map(([lang, config]) => [
config.translateCode,
lang,
]),
);
/**
* 语言代码到 locale 的映射
* 自动从 LANGUAGE_CONFIG 生成
*/
export const langToLocaleMap: Record<string, string> = Object.fromEntries(
Object.entries(LANGUAGE_CONFIG).map(([lang, config]) => [lang, config.locale]),
);
/**
* 获取所有支持翻译的语言列表(用于 Translator
*/
export function getSupportedTranslateLanguages() {
return Object.entries(LANGUAGE_CONFIG).map(([code, config]) => ({
code: config.translateCode,
name: config.displayName,
icon: config.icon,
langCode: code,
}));
}

274
src/i18n/languages/en.ts Normal file
View File

@@ -0,0 +1,274 @@
import Key from "@i18n/i18nKey";
import type { Translation } from "@i18n/translation";
export const en: Translation = {
// Loading Overlay
[Key.loading]: "LOADING",
// Navigations
[Key.home]: "Home",
[Key.archive]: "Archive",
[Key.about]: "About",
[Key.search]: "Search",
// Posts
[Key.tags]: "Tags",
[Key.categories]: "Categories",
[Key.series]: "Series",
[Key.posts]: "Posts",
[Key.recentPosts]: "Recent Posts",
[Key.postList]: "Post List",
[Key.statistics]: "Statistics",
[Key.tableOfContents]: "Table of Contents",
// Page Stats
[Key.pageViews]: "Views",
[Key.visitors]: "Visitors",
[Key.statsLoading]: "Loading stats...",
[Key.statsError]: "Stats unavailable",
// Announcement
[Key.announcement]: "Announcement",
[Key.announcementClose]: "Close",
[Key.comments]: "Comments",
[Key.untitled]: "Untitled",
[Key.uncategorized]: "Uncategorized",
[Key.noTags]: "No Tags",
[Key.wordCount]: "word",
[Key.wordsCount]: "words",
[Key.minuteCount]: "minute",
[Key.minutesCount]: "minutes",
[Key.postCount]: "post",
[Key.postsCount]: "posts",
[Key.themeColor]: "Theme Color",
[Key.lightMode]: "Light",
[Key.darkMode]: "Dark",
[Key.systemMode]: "System",
[Key.wallpaperMode]: "Wallpaper Mode",
[Key.wallpaperFullscreen]: "Fullscreen",
[Key.wallpaperBanner]: "Banner",
[Key.wallpaperNone]: "None",
[Key.more]: "More",
[Key.backTo]: "Back to",
[Key.author]: "Author",
[Key.publishedAt]: "Published at",
[Key.license]: "License",
// 404 Page
[Key.notFound]: "404",
[Key.notFoundTitle]: "Page Not Found",
[Key.notFoundDescription]: "Sorry, the page you visited does not exist or has been moved.",
[Key.backToHome]: "Back to Home",
// Projects Page
[Key.projects]: "Projects",
[Key.projectsSubtitle]: "My development project portfolio",
[Key.projectsAll]: "All",
[Key.projectsWeb]: "Web Applications",
[Key.projectsMobile]: "Mobile Applications",
[Key.projectsDesktop]: "Desktop Applications",
[Key.projectsOther]: "Other",
[Key.projectTechStack]: "Tech Stack",
[Key.projectLiveDemo]: "Live Demo",
[Key.projectSourceCode]: "Source Code",
[Key.projectDescription]: "Project Description",
[Key.projectStatus]: "Status",
[Key.projectStatusCompleted]: "Completed",
[Key.projectStatusInProgress]: "In Progress",
[Key.projectStatusPlanned]: "Planned",
[Key.projectsTotal]: "Total Projects",
[Key.projectsCompleted]: "Completed",
[Key.projectsInProgress]: "In Progress",
[Key.projectsTechStack]: "Tech Stack Statistics",
[Key.projectsFeatured]: "Featured Projects",
[Key.projectsPlanned]: "Planned",
[Key.projectsDemo]: "Live Demo",
[Key.projectsSource]: "Source Code",
// Skills Page
[Key.skills]: "Skills",
[Key.skillsSubtitle]: "My technical skills and expertise",
[Key.skillsAI]: "AI Development",
[Key.skillsBackend]: "Backend Development",
[Key.skillsClient]: "Client Development",
[Key.skillsFrontend]: "Frontend Development",
[Key.skillsDatabase]: "Database",
[Key.skillsEngines]: "Engines",
[Key.skillsTools]: "Development Tools",
[Key.skillsOthers]: "Other Skills",
[Key.skillLevel]: "Proficiency",
[Key.skillLevelBeginner]: "Beginner",
[Key.skillLevelIntermediate]: "Intermediate",
[Key.skillLevelAdvanced]: "Advanced",
[Key.skillLevelExpert]: "Expert",
[Key.skillExperience]: "Experience",
[Key.skillYears]: "years",
[Key.skillMonths]: "months",
[Key.skillsTotal]: "Total Skills",
[Key.skillsExpert]: "Expert Level",
[Key.skillsAdvanced]: "Advanced",
[Key.skillsIntermediate]: "Intermediate",
[Key.skillsBeginner]: "Beginner",
[Key.skillsAdvancedTitle]: "Professional Skills",
[Key.skillsProjects]: "Related Projects",
[Key.skillsDistribution]: "Skill Distribution",
[Key.skillsByLevel]: "Distribution by Level",
[Key.skillsByCategory]: "Distribution by Category",
// Timeline Page
[Key.timeline]: "Timeline",
[Key.timelineSubtitle]: "My growth journey and important milestones",
[Key.timelineEducation]: "Education",
[Key.timelineWork]: "Work Experience",
[Key.timelineProject]: "Project Experience",
[Key.timelineAchievement]: "Achievements",
[Key.timelinePresent]: "Present",
[Key.timelineLocation]: "Location",
[Key.timelineDescription]: "Detailed Description",
[Key.timelineMonths]: "months",
[Key.timelineYears]: "years",
[Key.timelineTotal]: "Total",
[Key.timelineProjects]: "Projects",
[Key.timelineExperience]: "Work Experience",
[Key.timelineCurrent]: "Current Status",
[Key.timelineHistory]: "History",
[Key.timelineAchievements]: "Achievements",
[Key.timelineStatistics]: "Statistics",
[Key.timelineByType]: "Grouped by Type",
[Key.timelineWorkExperience]: "Work Experience",
[Key.timelineTotalExperience]: "Total Work Experience",
[Key.timelineWorkPositions]: "Work Positions",
[Key.timelineCurrentRole]: "Current Status",
[Key.timelineEmployed]: "Employed",
[Key.timelineAvailable]: "Available",
// Diary Page
[Key.diary]: "Diary",
[Key.diarySubtitle]: "Share life anytime, anywhere",
[Key.diaryCount]: "diary entries",
[Key.diaryImage]: "Image",
[Key.diaryReply]: "Reply",
[Key.diaryTips]: "Only show the latest 30 diary entries",
[Key.diaryMinutesAgo]: "minutes ago",
[Key.diaryHoursAgo]: "hours ago",
[Key.diaryDaysAgo]: "days ago",
// Albums Page
[Key.albums]: "Albums",
[Key.albumsSubtitle]: "Record beautiful moments in life",
[Key.albumsEmpty]: "No content",
[Key.albumsEmptyDesc]: "No albums have been created yet. Go add some beautiful memories!",
[Key.albumsBackToList]: "Back to Albums",
[Key.albumsPhotoCount]: "photo",
[Key.albumsPhotosCount]: "photos",
// Anime Page
[Key.anime]: "Anime",
[Key.animeTitle]: "My Anime List",
[Key.animeSubtitle]: "Record my anime journey",
[Key.animeList]: "Anime List",
[Key.animeTotal]: "Total",
[Key.animeWatching]: "Watching",
[Key.animeCompleted]: "Completed",
[Key.animeAvgRating]: "Average Rating",
[Key.animeStatusWatching]: "Watching",
[Key.animeStatusCompleted]: "Completed",
[Key.animeStatusPlanned]: "Planned",
[Key.animeYear]: "Year",
[Key.animeStudio]: "Studio",
[Key.animeEmpty]: "No anime data",
[Key.animeEmptyBangumi]: "Please check Bangumi configuration or network connection",
// Friends Page
[Key.friends]: "Friends",
// RSS Page
[Key.rss]: "RSS Feed",
[Key.rssDescription]: "Subscribe to get latest updates",
[Key.rssSubtitle]: "Subscribe via RSS to get the latest articles and updates imediately",
[Key.rssLink]: "RSS Link",
[Key.rssCopyToReader]: "Copy link to your RSS reader",
[Key.rssCopyLink]: "Copy Link",
[Key.rssLatestPosts]: "Latest Posts",
[Key.rssWhatIsRSS]: "What is RSS?",
[Key.rssWhatIsRSSDescription]: "RSS (Really Simple Syndication) is a standard format for publishing frequently updated content. With RSS, you can:",
[Key.rssBenefit1]: "Get the latest website content in time without manually visiting",
[Key.rssBenefit2]: "Manage subscriptions to multiple websites in one place",
[Key.rssBenefit3]: "Avoid missing important updates and articles",
[Key.rssBenefit4]: "Enjoy an ad-free, clean reading experience",
[Key.rssHowToUse]: "It is recommended to use Feedly, Inoreader or other RSS readers to subscribe to this site.",
[Key.rssCopied]: "RSS link copied to clipboard!",
[Key.rssCopyFailed]: "Copy failed, please copy the link manually",
// Atom Page
[Key.atom]: "Atom Feed",
[Key.atomDescription]: "Subscribe to get latest updates",
[Key.atomSubtitle]: "Subscribe via Atom to get the latest articles and updates immediately",
[Key.atomLink]: "Atom Link",
[Key.atomCopyToReader]: "Copy link to your Atom reader",
[Key.atomCopyLink]: "Copy Link",
[Key.atomLatestPosts]: "Latest Posts",
[Key.atomWhatIsAtom]: "What is Atom?",
[Key.atomWhatIsAtomDescription]: "Atom (Atom Syndication Format) is an XML-based standard for describing feeds and their items. With Atom, you can:",
[Key.atomBenefit1]: "Get the latest website content in time without manually visiting",
[Key.atomBenefit2]: "Manage subscriptions to multiple websites in one place",
[Key.atomBenefit3]: "Avoid missing important updates and articles",
[Key.atomBenefit4]: "Enjoy an ad-free, clean reading experience",
[Key.atomHowToUse]: "It is recommended to use Feedly, Inoreader or other Atom readers to subscribe to this site.",
[Key.atomCopied]: "Atom link copied to clipboard!",
[Key.atomCopyFailed]: "Copy failed, please copy the link manually",
// Password Protection
[Key.passwordProtected]: "Password Protected",
[Key.passwordProtectedTitle]: "This content is password protected",
[Key.passwordProtectedDescription]: "Please enter the password to view the protected content",
[Key.passwordPlaceholder]: "Enter password",
[Key.passwordUnlock]: "Unlock",
[Key.passwordUnlocking]: "Unlocking...",
[Key.passwordIncorrect]: "Incorrect password, please try again",
[Key.passwordDecryptError]: "Decryption failed, please check if the password is correct",
[Key.passwordRequired]: "Please enter the password",
[Key.passwordVerifying]: "Verifying...",
[Key.passwordDecryptFailed]: "Decryption failed, please check the password",
[Key.passwordDecryptRetry]: "Decryption failed, please try again",
[Key.passwordUnlockButton]: "Unlock",
[Key.copyFailed]: "Copy failed:",
[Key.syntaxHighlightFailed]: "Syntax highlighting failed:",
[Key.autoSyntaxHighlightFailed]: "Automatic syntax highlighting also failed:",
[Key.decryptionError]: "An error occurred during decryption:",
// Last Modified Time Card
[Key.lastModifiedPrefix]: "Time since last edit: ",
[Key.lastModifiedOutdated]: "Some information may be outdated",
[Key.year]: "year",
[Key.month]: "month",
[Key.day]: "day",
[Key.hour]: "hour",
[Key.minute]: "minute",
[Key.second]: "second",
// Music Player
[Key.playlist]: "Playlist",
[Key.musicEmptyPlaylist]: "Local playlist is empty",
[Key.musicNoSongsAvailable]: "No songs available in playlist",
[Key.musicPlayFailed]: "Failed to play \"{0}\", trying next...",
[Key.musicAutoplayBlocked]: "Autoplay blocked",
[Key.musicMetingFailed]: "Failed to fetch Meting playlist",
[Key.musicUnknownArtist]: "Unknown Artist",
[Key.musicUnknownTrack]: "Unknown Track",
[Key.musicSwitchToLocal]: "Switch to Local mode",
[Key.musicSwitchToMeting]: "Switch to Meting mode",
[Key.musicProgress]: "Progress",
[Key.musicCollapse]: "Collapse player",
[Key.musicVolume]: "Volume",
[Key.musicExpand]: "Expand music player",
};

274
src/i18n/languages/ja.ts Normal file
View File

@@ -0,0 +1,274 @@
import Key from "@i18n/i18nKey";
import type { Translation } from "@i18n/translation";
export const ja: Translation = {
// 加載遮罩
[Key.loading]: "読み込み中",
// ナビゲーション
[Key.home]: "ホーム",
[Key.archive]: "アーカイブ",
[Key.about]: "について",
[Key.search]: "検索",
// 投稿
[Key.tags]: "タグ",
[Key.categories]: "カテゴリ",
[Key.series]: "シリーズ",
[Key.posts]: "投稿",
[Key.recentPosts]: "最近の投稿",
[Key.postList]: "投稿リスト",
[Key.statistics]: "統計",
[Key.tableOfContents]: "目次",
// 統計
[Key.pageViews]: "閲覧数",
[Key.visitors]: "訪問者",
[Key.statsLoading]: "統計を読み込み中...",
[Key.statsError]: "統計を利用できません",
// お知らせ
[Key.announcement]: "お知らせ",
[Key.announcementClose]: "閉じる",
[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.wallpaperMode]: "壁紙モード",
[Key.wallpaperFullscreen]: "全画面",
[Key.wallpaperBanner]: "バナー",
[Key.wallpaperNone]: "なし",
[Key.more]: "もっと",
[Key.backTo]: "戻る",
[Key.author]: "著者",
[Key.publishedAt]: "公開日",
[Key.license]: "ライセンス",
// 404ページ
[Key.notFound]: "404",
[Key.notFoundTitle]: "ページが見つかりません",
[Key.notFoundDescription]: "申し訳ありませんが、アクセスしたページは存在しないか、移動されています。",
[Key.backToHome]: "ホームに戻る",
// プロジェクトページ
[Key.projects]: "プロジェクト",
[Key.projectsSubtitle]: "私の開発プロジェクトポートフォリオ",
[Key.projectsAll]: "すべて",
[Key.projectsWeb]: "ウェブアプリケーション",
[Key.projectsMobile]: "モバイルアプリケーション",
[Key.projectsDesktop]: "デスクトップアプリケーション",
[Key.projectsOther]: "その他",
[Key.projectTechStack]: "技術スタック",
[Key.projectLiveDemo]: "ライブデモ",
[Key.projectSourceCode]: "ソースコード",
[Key.projectDescription]: "プロジェクト説明",
[Key.projectStatus]: "ステータス",
[Key.projectStatusCompleted]: "完了",
[Key.projectStatusInProgress]: "進行中",
[Key.projectStatusPlanned]: "予定",
[Key.projectsTotal]: "プロジェクト合計",
[Key.projectsCompleted]: "完了",
[Key.projectsInProgress]: "進行中",
[Key.projectsTechStack]: "技術スタック統計",
[Key.projectsFeatured]: "注目プロジェクト",
[Key.projectsPlanned]: "予定",
[Key.projectsDemo]: "ライブデモ",
[Key.projectsSource]: "ソースコード",
// スキルページ
[Key.skills]: "スキル",
[Key.skillsSubtitle]: "私の技術スキルと専門知識",
[Key.skillsAI]: "AI開発",
[Key.skillsBackend]: "バックエンド開発",
[Key.skillsClient]: "クライアント開発",
[Key.skillsFrontend]: "フロントエンド開発",
[Key.skillsDatabase]: "データベース",
[Key.skillsEngines]: "エンジン",
[Key.skillsTools]: "開発ツール",
[Key.skillsOthers]: "その他のスキル",
[Key.skillLevel]: "熟練度",
[Key.skillLevelBeginner]: "初心者",
[Key.skillLevelIntermediate]: "中級者",
[Key.skillLevelAdvanced]: "上級者",
[Key.skillLevelExpert]: "エキスパート",
[Key.skillExperience]: "経験",
[Key.skillYears]: "年",
[Key.skillMonths]: "ヶ月",
[Key.skillsTotal]: "スキル合計",
[Key.skillsExpert]: "エキスパートレベル",
[Key.skillsAdvanced]: "上級者",
[Key.skillsIntermediate]: "中級者",
[Key.skillsBeginner]: "初心者",
[Key.skillsAdvancedTitle]: "専門スキル",
[Key.skillsProjects]: "関連プロジェクト",
[Key.skillsDistribution]: "スキル分布",
[Key.skillsByLevel]: "レベル別分布",
[Key.skillsByCategory]: "カテゴリ別分布",
// タイムラインページ
[Key.timeline]: "タイムライン",
[Key.timelineSubtitle]: "私の成長の旅と重要なマイルストーン",
[Key.timelineEducation]: "教育",
[Key.timelineWork]: "職歴",
[Key.timelineProject]: "プロジェクト経験",
[Key.timelineAchievement]: "実績",
[Key.timelinePresent]: "現在",
[Key.timelineLocation]: "場所",
[Key.timelineDescription]: "詳細説明",
[Key.timelineMonths]: "ヶ月",
[Key.timelineYears]: "年",
[Key.timelineTotal]: "合計",
[Key.timelineProjects]: "プロジェクト",
[Key.timelineExperience]: "職歴",
[Key.timelineCurrent]: "現在の状態",
[Key.timelineHistory]: "履歴",
[Key.timelineAchievements]: "実績",
[Key.timelineStatistics]: "統計",
[Key.timelineByType]: "タイプ別グループ化",
[Key.timelineWorkExperience]: "職歴",
[Key.timelineTotalExperience]: "総職歴",
[Key.timelineWorkPositions]: "職位数",
[Key.timelineCurrentRole]: "現在の状態",
[Key.timelineEmployed]: "在職中",
[Key.timelineAvailable]: "入社可能",
// 日記ページ
[Key.diary]: "日記",
[Key.diarySubtitle]: "いつでもどこでも、生活を共有する",
[Key.diaryCount]: "日記エントリ",
[Key.diaryImage]: "画像",
[Key.diaryReply]: "返信",
[Key.diaryTips]: "最新の30件の日記エントリのみを表示",
[Key.diaryMinutesAgo]: "分前",
[Key.diaryHoursAgo]: "時間前",
[Key.diaryDaysAgo]: "日前",
// アルバムページ
[Key.albums]: "アルバム",
[Key.albumsSubtitle]: "生活の美しい瞬間を記録する",
[Key.albumsEmpty]: "コンテンツなし",
[Key.albumsEmptyDesc]: "アルバムがまだ作成されていません。美しい思い出を追加してください!",
[Key.albumsBackToList]: "アルバムに戻る",
[Key.albumsPhotoCount]: "写真",
[Key.albumsPhotosCount]: "写真",
// アニメページ
[Key.anime]: "アニメ",
[Key.animeTitle]: "私のアニメリスト",
[Key.animeSubtitle]: "私の二次元の旅を記録する",
[Key.animeList]: "アニメリスト",
[Key.animeTotal]: "合計",
[Key.animeWatching]: "視聴中",
[Key.animeCompleted]: "完了",
[Key.animeAvgRating]: "平均評価",
[Key.animeStatusWatching]: "視聴中",
[Key.animeStatusCompleted]: "完了",
[Key.animeStatusPlanned]: "予定",
[Key.animeYear]: "年",
[Key.animeStudio]: "スタジオ",
[Key.animeEmpty]: "アニメデータなし",
[Key.animeEmptyBangumi]: "Bangumiの設定またはネットワーク接続を確認してください",
// 友達ページ
[Key.friends]: "友達",
// RSSページ
[Key.rss]: "RSSフィード",
[Key.rssDescription]: "最新の更新を購読する",
[Key.rssSubtitle]: "RSSで購読して、最新の記事と更新を第一时间で取得する",
[Key.rssLink]: "RSSリンク",
[Key.rssCopyToReader]: "RSSリンクをリーダーにコピー",
[Key.rssCopyLink]: "リンクをコピー",
[Key.rssLatestPosts]: "最新の投稿",
[Key.rssWhatIsRSS]: "RSSとは",
[Key.rssWhatIsRSSDescription]: "RSSReally Simple Syndicationは、頻繁に更新されるコンテンツを公開するための標準形式です。RSSを使用すると",
[Key.rssBenefit1]: "手動で訪問することなく、最新のウェブサイトコンテンツを及时に取得",
[Key.rssBenefit2]: "1か所で複数のウェブサイトの購読を管理",
[Key.rssBenefit3]: "重要な更新や記事を見逃すことを回避",
[Key.rssBenefit4]: "広告なしのクリーンな読書体験を楽しむ",
[Key.rssHowToUse]: "Feedly、Inoreaderまたは他のRSSリーダーを使用してこのサイトを購読することを推奨します。",
[Key.rssCopied]: "RSSリンクがクリップボードにコピーされました",
[Key.rssCopyFailed]: "コピーに失敗しました。手動でリンクをコピーしてください",
// Atomページ
[Key.atom]: "Atomフィード",
[Key.atomDescription]: "最新の更新を購読する",
[Key.atomSubtitle]: "Atomで購読して、最新の記事と更新を第一时间で取得する",
[Key.atomLink]: "Atomリンク",
[Key.atomCopyToReader]: "Atomリンクをリーダーにコピー",
[Key.atomCopyLink]: "リンクをコピー",
[Key.atomLatestPosts]: "最新の投稿",
[Key.atomWhatIsAtom]: "Atomとは",
[Key.atomWhatIsAtomDescription]: "Atom連合フォーマットAtom Syndication Formatは、フィードとそのアイテムを記述するためのXMLベースの標準です。Atomを使用すると",
[Key.atomBenefit1]: "手動で訪問することなく、最新のウェブサイトコンテンツを及时に取得",
[Key.atomBenefit2]: "1か所で複数のウェブサイトの購読を管理",
[Key.atomBenefit3]: "重要な更新や記事を見逃すことを回避",
[Key.atomBenefit4]: "広告なしのクリーンな読書体験を楽しむ",
[Key.atomHowToUse]: "Feedly、Inoreaderまたは他のAtomリーダーを使用してこのサイトを購読することを推奨します。",
[Key.atomCopied]: "Atomリンクがクリップボードにコピーされました",
[Key.atomCopyFailed]: "コピーに失敗しました。手動でリンクをコピーしてください",
// パスワード保護
[Key.passwordProtected]: "パスワード保護",
[Key.passwordProtectedTitle]: "このコンテンツはパスワードで保護されています",
[Key.passwordProtectedDescription]: "保護されたコンテンツを表示するにはパスワードを入力してください",
[Key.passwordPlaceholder]: "パスワードを入力",
[Key.passwordUnlock]: "ロック解除",
[Key.passwordUnlocking]: "ロック解除中...",
[Key.passwordIncorrect]: "パスワードが間違っています。再試行してください",
[Key.passwordDecryptError]: "復号化に失敗しました。パスワードが正しいか確認してください",
[Key.passwordRequired]: "パスワードを入力してください",
[Key.passwordVerifying]: "検証中...",
[Key.passwordDecryptFailed]: "復号化に失敗しました。パスワードを確認してください",
[Key.passwordDecryptRetry]: "復号化に失敗しました。再試行してください",
[Key.passwordUnlockButton]: "ロック解除",
[Key.copyFailed]: "コピーに失敗しました:",
[Key.syntaxHighlightFailed]: "構文ハイライトに失敗しました:",
[Key.autoSyntaxHighlightFailed]: "自動構文ハイライトにも失敗しました:",
[Key.decryptionError]: "復号化中にエラーが発生しました:",
// 最終更新時間カード
[Key.lastModifiedPrefix]: "最終編集からの時間:",
[Key.lastModifiedOutdated]: "一部の情報は古くなっている可能性があります",
[Key.year]: "年",
[Key.month]: "月",
[Key.day]: "日",
[Key.hour]: "時間",
[Key.minute]: "分",
[Key.second]: "秒",
// 音楽プレイヤー
[Key.playlist]: "プレイリスト",
[Key.musicEmptyPlaylist]: "ローカルプレイリストが空です",
[Key.musicNoSongsAvailable]: "プレイリストに利用可能な曲がありません",
[Key.musicPlayFailed]: "\"{0}\" の再生に失敗しました。次を試行しています...",
[Key.musicAutoplayBlocked]: "自動再生がブロックされました",
[Key.musicMetingFailed]: "Meting プレイリストの取得に失敗しました",
[Key.musicUnknownArtist]: "未知のアーティスト",
[Key.musicUnknownTrack]: "未知の曲",
[Key.musicSwitchToLocal]: "ローカルモードに切り替え",
[Key.musicSwitchToMeting]: "Metingモードに切り替え",
[Key.musicProgress]: "再生の進捗",
[Key.musicCollapse]: "プレイヤーを閉じる",
[Key.musicVolume]: "音量調節",
[Key.musicExpand]: "音楽プレイヤーを展開",
};

274
src/i18n/languages/zh.ts Normal file
View File

@@ -0,0 +1,274 @@
import Key from "@i18n/i18nKey";
import type { Translation } from "@i18n/translation";
export const zh: Translation = {
// 加载遮罩
[Key.loading]: "加载中",
// 导航
[Key.home]: "主页",
[Key.archive]: "归档",
[Key.about]: "关于",
[Key.search]: "搜索",
// 文章
[Key.tags]: "标签",
[Key.categories]: "分类",
[Key.series]: "系列",
[Key.posts]: "文章",
[Key.recentPosts]: "最新文章",
[Key.postList]: "文章列表",
[Key.statistics]: "统计",
[Key.tableOfContents]: "目录",
// 统计
[Key.pageViews]: "浏览量",
[Key.visitors]: "访客",
[Key.statsLoading]: "统计加载中...",
[Key.statsError]: "统计不可用",
// 公告栏
[Key.announcement]: "公告",
[Key.announcementClose]: "关闭",
[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.wallpaperMode]: "壁纸模式",
[Key.wallpaperFullscreen]: "全屏壁纸",
[Key.wallpaperBanner]: "横幅壁纸",
[Key.wallpaperNone]: "纯色背景",
[Key.more]: "更多",
[Key.backTo]: "返回",
[Key.author]: "作者",
[Key.publishedAt]: "发布于",
[Key.license]: "许可协议",
// 404页面
[Key.notFound]: "404",
[Key.notFoundTitle]: "页面未找到",
[Key.notFoundDescription]: "抱歉,您访问的页面不存在或已被移动。",
[Key.backToHome]: "返回首页",
// 项目展示页面
[Key.projects]: "项目展示",
[Key.projectsSubtitle]: "我的开发项目作品集",
[Key.projectsAll]: "全部",
[Key.projectsWeb]: "网页应用",
[Key.projectsMobile]: "移动应用",
[Key.projectsDesktop]: "桌面应用",
[Key.projectsOther]: "其他",
[Key.projectTechStack]: "技术栈",
[Key.projectLiveDemo]: "在线演示",
[Key.projectSourceCode]: "源代码",
[Key.projectDescription]: "项目描述",
[Key.projectStatus]: "状态",
[Key.projectStatusCompleted]: "已完成",
[Key.projectStatusInProgress]: "进行中",
[Key.projectStatusPlanned]: "计划中",
[Key.projectsTotal]: "项目总数",
[Key.projectsCompleted]: "已完成",
[Key.projectsInProgress]: "进行中",
[Key.projectsTechStack]: "技术栈统计",
[Key.projectsFeatured]: "精选项目",
[Key.projectsPlanned]: "计划中",
[Key.projectsDemo]: "在线演示",
[Key.projectsSource]: "源代码",
// 技能展示页面
[Key.skills]: "技能展示",
[Key.skillsSubtitle]: "我的技术技能和专业知识",
[Key.skillsAI]: "AI 开发",
[Key.skillsBackend]: "后端开发",
[Key.skillsClient]: "客户端开发",
[Key.skillsFrontend]: "前端开发",
[Key.skillsDatabase]: "数据库",
[Key.skillsEngines]: "引擎",
[Key.skillsTools]: "开发工具",
[Key.skillsOthers]: "其他技能",
[Key.skillLevel]: "熟练度",
[Key.skillLevelBeginner]: "初学者",
[Key.skillLevelIntermediate]: "中级",
[Key.skillLevelAdvanced]: "高级",
[Key.skillLevelExpert]: "专家",
[Key.skillExperience]: "经验",
[Key.skillYears]: "年",
[Key.skillMonths]: "个月",
[Key.skillsTotal]: "总技能数",
[Key.skillsExpert]: "专家级",
[Key.skillsAdvanced]: "高级",
[Key.skillsIntermediate]: "中级",
[Key.skillsBeginner]: "初级",
[Key.skillsAdvancedTitle]: "专业技能",
[Key.skillsProjects]: "相关项目",
[Key.skillsDistribution]: "技能分布",
[Key.skillsByLevel]: "按等级分布",
[Key.skillsByCategory]: "按分类分布",
// 时间线页面
[Key.timeline]: "时间线",
[Key.timelineSubtitle]: "我的成长历程和重要里程碑",
[Key.timelineEducation]: "教育经历",
[Key.timelineWork]: "工作经历",
[Key.timelineProject]: "项目经历",
[Key.timelineAchievement]: "成就荣誉",
[Key.timelinePresent]: "至今",
[Key.timelineLocation]: "地点",
[Key.timelineDescription]: "详细描述",
[Key.timelineMonths]: "个月",
[Key.timelineYears]: "年",
[Key.timelineTotal]: "总计",
[Key.timelineProjects]: "项目数",
[Key.timelineExperience]: "工作经验",
[Key.timelineCurrent]: "当前状态",
[Key.timelineHistory]: "历史记录",
[Key.timelineAchievements]: "成就荣誉",
[Key.timelineStatistics]: "统计信息",
[Key.timelineByType]: "按类型分组",
[Key.timelineWorkExperience]: "工作经验",
[Key.timelineTotalExperience]: "总工作经验",
[Key.timelineWorkPositions]: "工作岗位数",
[Key.timelineCurrentRole]: "当前状态",
[Key.timelineEmployed]: "在职",
[Key.timelineAvailable]: "可入职",
// 短文页面
[Key.diary]: "日记",
[Key.diarySubtitle]: "随时随地,分享生活",
[Key.diaryCount]: "条短文",
[Key.diaryImage]: "图片",
[Key.diaryReply]: "回复",
[Key.diaryTips]: "只展示最近30条日记",
[Key.diaryMinutesAgo]: "分钟前",
[Key.diaryHoursAgo]: "小时前",
[Key.diaryDaysAgo]: "天前",
// 相册页面
[Key.albums]: "相册",
[Key.albumsSubtitle]: "记录生活中的美好瞬间",
[Key.albumsEmpty]: "暂无内容",
[Key.albumsEmptyDesc]: "还没有创建任何相册,快去添加一些美好的回忆吧!",
[Key.albumsBackToList]: "返回相册",
[Key.albumsPhotoCount]: "张照片",
[Key.albumsPhotosCount]: "张照片",
// 番剧页面
[Key.anime]: "追番",
[Key.animeTitle]: "我的追番记录",
[Key.animeSubtitle]: "记录我的二次元之旅",
[Key.animeList]: "追番列表",
[Key.animeTotal]: "总数",
[Key.animeWatching]: "追番中",
[Key.animeCompleted]: "已追完",
[Key.animeAvgRating]: "平均评分",
[Key.animeStatusWatching]: "追番中",
[Key.animeStatusCompleted]: "已追完",
[Key.animeStatusPlanned]: "计划中",
[Key.animeYear]: "年份",
[Key.animeStudio]: "制作",
[Key.animeEmpty]: "暂无追番数据",
[Key.animeEmptyBangumi]: "请检查 Bangumi 配置或网络连接",
// 友链页面
[Key.friends]: "友链",
// RSS页面
[Key.rss]: "RSS 订阅",
[Key.rssDescription]: "订阅获取最新更新",
[Key.rssSubtitle]: "通过 RSS 订阅,第一时间获取最新文章和动态",
[Key.rssLink]: "RSS 链接",
[Key.rssCopyToReader]: "复制链接到你的 RSS 阅读器",
[Key.rssCopyLink]: "复制链接",
[Key.rssLatestPosts]: "最新文章",
[Key.rssWhatIsRSS]: "什么是 RSS",
[Key.rssWhatIsRSSDescription]: "RSSReally Simple Syndication是一种用于发布经常更新内容的标准格式。通过 RSS你可以",
[Key.rssBenefit1]: "及时获取网站最新内容,无需手动访问",
[Key.rssBenefit2]: "在一个地方管理多个网站的订阅",
[Key.rssBenefit3]: "避免错过重要更新和文章",
[Key.rssBenefit4]: "享受无广告的纯净阅读体验",
[Key.rssHowToUse]: "推荐使用 Feedly、Inoreader 或其他 RSS 阅读器来订阅本站。",
[Key.rssCopied]: "RSS 链接已复制到剪贴板!",
[Key.rssCopyFailed]: "复制失败,请手动复制链接",
//Atom 页面
[Key.atom]: "Atom 订阅",
[Key.atomDescription]: "订阅获取最新更新",
[Key.atomSubtitle]: "通过 Atom 订阅,第一时间获取最新文章和动态",
[Key.atomLink]: "Atom 链接",
[Key.atomCopyToReader]: "复制链接到你的 Atom 阅读器",
[Key.atomCopyLink]: "复制链接",
[Key.atomLatestPosts]: "最新文章",
[Key.atomWhatIsAtom]: "什么是 Atom",
[Key.atomWhatIsAtomDescription]: "Atom联合格式Atom Syndication Format是一个基于XML的标准用于描述订阅源及其信息项。通过 Atom你可以",
[Key.atomBenefit1]: "及时获取网站最新内容,无需手动访问",
[Key.atomBenefit2]: "在一个地方管理多个网站的订阅",
[Key.atomBenefit3]: "避免错过重要更新和文章",
[Key.atomBenefit4]: "享受无广告的纯净阅读体验",
[Key.atomHowToUse]: "推荐使用 Feedly、Inoreader 或其他 Atom 阅读器来订阅本站。",
[Key.atomCopied]: "Atom 链接已复制到剪贴板!",
[Key.atomCopyFailed]: "复制失败,请手动复制链接",
// 密码保护
[Key.passwordProtected]: "密码保护",
[Key.passwordProtectedTitle]: "此内容受密码保护",
[Key.passwordProtectedDescription]: "请输入密码以查看受保护的内容",
[Key.passwordPlaceholder]: "请输入密码",
[Key.passwordUnlock]: "解锁",
[Key.passwordUnlocking]: "解锁中...",
[Key.passwordIncorrect]: "密码错误,请重试",
[Key.passwordDecryptError]: "解密失败,请检查密码是否正确",
[Key.passwordRequired]: "请输入密码",
[Key.passwordVerifying]: "验证中...",
[Key.passwordDecryptFailed]: "解密失败,请检查密码",
[Key.passwordDecryptRetry]: "解密失败,请重试",
[Key.passwordUnlockButton]: "解锁",
[Key.copyFailed]: "复制失败:",
[Key.syntaxHighlightFailed]: "语法高亮失败:",
[Key.autoSyntaxHighlightFailed]: "自动语法高亮也失败:",
[Key.decryptionError]: "解密过程中发生错误:",
//最后编辑时间卡片
[Key.lastModifiedPrefix]: "距离上次编辑: ",
[Key.lastModifiedOutdated]: "部分信息可能已经过时",
[Key.year]: "年",
[Key.month]: "月",
[Key.day]: "天",
[Key.hour]: "小时",
[Key.minute]: "分",
[Key.second]: "秒",
// 音乐播放器
[Key.playlist]: "播放列表",
[Key.musicEmptyPlaylist]: "本地播放列表为空",
[Key.musicNoSongsAvailable]: "播放列表中没有可用的歌曲",
[Key.musicPlayFailed]: "无法播放 \"{0}\", 正在尝试下一首...",
[Key.musicAutoplayBlocked]: "自动播放被拦截",
[Key.musicMetingFailed]: "Meting 歌单获取失败",
[Key.musicUnknownArtist]: "未知艺术家",
[Key.musicUnknownTrack]: "未知歌曲",
[Key.musicSwitchToLocal]: "切换到 Local 模式",
[Key.musicSwitchToMeting]: "切换到 Meting 模式",
[Key.musicProgress]: "播放进度",
[Key.musicCollapse]: "折叠播放器",
[Key.musicVolume]: "音量控制",
[Key.musicExpand]: "展开音乐播放器",
};

32
src/i18n/translation.ts Normal file
View File

@@ -0,0 +1,32 @@
import { getResolvedSiteLang } from "@utils/language";
import { en } from "./languages/en";
import { ja } from "./languages/ja";
import { zh } from "./languages/zh";
import type I18nKey from "./i18nKey";
export type Translation = {
[K in I18nKey]: string;
};
const defaultTranslation = en;
const map: { [key: string]: Translation } = {
en: en,
en_us: en,
en_gb: en,
en_au: en,
zh: zh,
zh_cn: zh,
ja: ja,
ja_jp: ja,
};
export function getTranslation(lang: string): Translation {
return map[lang.toLowerCase()] || defaultTranslation;
}
export function i18n(key: I18nKey): string {
const lang = getResolvedSiteLang();
return getTranslation(lang)[key];
}