This commit is contained in:
2026-02-03 01:45:22 +04:00
parent f53016aeda
commit b2ab5905d0
18 changed files with 18214 additions and 671 deletions

15
.dockerignore Normal file
View File

@@ -0,0 +1,15 @@
node_modules
dist
.astro
.vercel
.git
.gitignore
.env
.env.local
*.log
.vscode
.DS_Store
README.md
LICENSE
docs
screenshots

39
Dockerfile Normal file
View File

@@ -0,0 +1,39 @@
# Stage 1: Build
FROM node:22-alpine AS builder
# Install dependencies for sharp and other native modules
RUN apk add --no-cache \
python3 \
make \
g++ \
libc6-compat
# Set working directory
WORKDIR /app
# Copy package files
COPY package.json package-lock.json* ./
# Install dependencies
RUN npm ci --only=production=false
# Copy source code
COPY . .
# Build the application
RUN npm run build
# Stage 2: Production
FROM nginx:alpine AS production
# Copy built files from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Start nginx
CMD ["nginx", "-g", "daemon off;"]

122
README.md
View File

@@ -1,122 +0,0 @@
<div align = "center">
# Twilight
A CMS integrated static blog template built with Astro framework.
[**🖥️ Live Demo**](https://twilight.spr-aachen.com)
[**📝 Documentation**](https://docs.twilight.spr-aachen.com/en)
[![Bilibili](https://img.shields.io/badge/Bilibili-Intro-blue?logo=Bilibili)](https://space.bilibili.com/359461611/lists/6641229)&nbsp;
[![YouTube](https://img.shields.io/badge/YouTube-Intro-red?logo=YouTube)](https://youtube.com/playlist?list=PLzjq8Hx1SRV7yqZQiACcCJmKPeg5D8JKe&si=Bcz2o0PF8MFvx8ec)
<table style="width: 100%; table-layout: fixed;">
<tr>
<td colspan="5"><img alt="Desktop" src="docs/image/Desktop.jpg" style="max-width: 100%;"></td>
</tr>
<tr>
<td><img alt="Mobile_4" src="docs/image/Mobile_4.jpg" style="max-width: 100%;"></td>
<td><img alt="Mobile_2" src="docs/image/Mobile_2.jpg" style="max-width: 100%;"></td>
<td><img alt="Mobile_1" src="docs/image/Mobile_1.jpg" style="max-width: 100%;"></td>
<td><img alt="Mobile_3" src="docs/image/Mobile_3.jpg" style="max-width: 100%;"></td>
<td><img alt="Mobile_5" src="docs/image/Mobile_5.jpg" style="max-width: 100%;"></td>
</tr>
</table>
</div>
---
<div align = "center">
English | [**中文**](docs/README_ZH.md)
</div>
## ✨ Features
### Content
- **CMS Functionality**: Easy content management with Decap CMS integration
- **Data Visualization**: Visualized personal data like projects, skills etc.
- **Automatic Navigation**: Automatic generation of post navigation
### Components
- **Analytics Support**: Umami analytics integration for visitor insights
- **Comment System**: Twikoo-powered comment functionality
- **Music Player**: Background music support with playlist management
- **PIO Widget**: Interactive live2d character support
### VFX
- **Smooth Transition Animations**: Polished page component transition animations
- **Customizable Theme Colors**: Realtime customizable color schemes
- **Dynamic Wallpaper System**: Carousel support with multiple display modes
- **Immersive Particle Effects**: Highly customizable animated particles
### Compability
- **Modern & Responsive Design**: Fully optimized for desktop and mobile devices
- **Multilingual Capability**: Built-in translation functionality for global accessibility
## 📦 Installation
1. **Clone the repository:**
```bash
git clone https://github.com/Spr-Aachen/Twilight.git
cd Twilight
```
2. **Install dependencies:**
```bash
# Install pnpm if not already installed
npm install -g pnpm
# Install project dependencies
pnpm install
```
3. **Configure your blog:**
- [Customize blog settings](https://docs.twilight.spr-aachen.com/en/config/core) inside `twilight.config.yaml`
- [Support CMS functionality](https://docs.twilight.spr-aachen.com/en/config/cms) inside `.env`
- [Support Umami analytics](https://docs.twilight.spr-aachen.com/en/config/analytics) inside `.env`
- [Manage site content](https://docs.twilight.spr-aachen.com/en/config/content) inside `src/content`
4. **Start the development server:**
```bash
pnpm dev
```
## 🚀 Deployment
Deploy your blog to any static hosting platform
## ⚡ Commands
| Command | Action |
|:----------------------------|:----------------------------|
| `pnpm lint` | Check and fix code issues |
| `pnpm format` | Format code with Biome |
| `pnpm check` | Run Astro error checking |
| `pnpm dev` | Start local dev server |
| `pnpm build` | Build site to `./dist/` |
| `pnpm preview` | Preview build locally |
| `pnpm astro ...` | Run Astro CLI commands |
| `pnpm new-post <filename>` | Create a new blog post |
## 🙏 Acknowledgements
- Prototype - [Fuwari](https://github.com/saicaca/fuwari)
- Inspiration - [Yukina](https://github.com/WhitePaper233/yukina) & [Mizuki](https://github.com/matsuzaka-yuki/Mizuki)
- CMS - [astro-decap-cms-oauth](https://github.com/dorukgezici/astro-decap-cms-oauth)
- Translation - [translate](https://gitee.com/mail_osc/translate)
## 🤝 Support
This project is supported by Alibaba Cloud ESA for accelerated delivery, compute, and protection.
<a href="https://esa.console.aliyun.com/">
<img src="https://img.alicdn.com/imgextra/i3/O1CN01H1UU3i1Cti9lYtFrs_!!6000000000139-2-tps-7534-844.png" alt="Alibaba Cloud ESA Support" style="max-width: 100%; height: auto;">
</a>

View File

@@ -44,7 +44,7 @@ export default defineConfig({
integrations: [
decapCmsOauth({
decapCMSVersion: "3.3.3",
oauthDisabled: true, // Disable it to use oauth, requires .env configuration
oauthDisabled: false, // Disable it to use oauth, requires .env configuration
}),
swup({
theme: false,

59
nginx.conf Normal file
View File

@@ -0,0 +1,59 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Cache control for static assets
location ~* ^/_astro/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
location ~* ^/assets/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
location ~* ^/favicon/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
location ~* ^/pio/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
# CORS headers for RSS/Atom feeds
location ~* ^/(atom|rss)\.xml$ {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET" always;
add_header Access-Control-Max-Age "86400" always;
try_files $uri =404;
}
# Main location - SPA fallback
location / {
try_files $uri $uri/ $uri.html /index.html;
}
# Error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

17683
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,293 +1,157 @@
# 后台系统配置
backend:
name: github
repo: Spr-Aachen/Twilight # 请替换为您的 GitHub 仓库
branch: main # 请替换为您的分支名称
site_domain: twilight.spr-aachen.com # 请替换为您的域名
base_url: https://twilight.spr-aachen.com # 请替换为您的 URL
auth_endpoint: oauth # OAuth 路由由集成提供
# 媒体目录配置
media_folder: "public/images" # 媒体文件存储路径
public_folder: "/images" # 公共访问路径
# 集合管理配置
repo: StepanovPlaton/AboutMe
branch: main
site_domain: stepanovplaton.ru
base_url: https://stepanovplaton.ru
auth_endpoint: oauth
media_folder: "public/images"
public_folder: "/images"
collections:
- # 博客文章集合
# 集合名称
name: "posts"
# 后台显示标签
- name: "posts"
label: "Posts"
# 内容存储目录
folder: "src/content/posts"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{slug}}"
# 字段列表
fields:
- # 标题
{label: "Title", name: "title", widget: "string"}
- # 发布日期
{label: "Published Date", name: "published", widget: "datetime"}
- # 更新日期
{label: "Updated Date", name: "updated", widget: "datetime", required: false}
- # 描述
{label: "Description", name: "description", widget: "text", required: false}
- # 封面图
{label: "Cover", name: "cover", widget: "image", required: false}
- # 标签
{label: "Tags", name: "tags", widget: "list", default: [], required: false}
- # 分类
{label: "Category", name: "category", widget: "string", required: false}
- # 草稿
{label: "Draft", name: "draft", widget: "boolean", default: false}
- # 正文
{label: "Body", name: "body", widget: "markdown"}
- {label: "Title", name: "title", widget: "string"}
- {label: "Published Date", name: "published", widget: "datetime"}
- {label: "Updated Date", name: "updated", widget: "datetime", required: false}
- {label: "Description", name: "description", widget: "text", required: false}
- {label: "Cover", name: "cover", widget: "image", required: false}
- {label: "Tags", name: "tags", widget: "list", default: [], required: false}
- {label: "Category", name: "category", widget: "string", required: false}
- {label: "Draft", name: "draft", widget: "boolean", default: false}
- {label: "Body", name: "body", widget: "markdown"}
- # 项目集合
# 集合名称
name: "projects"
# 后台显示标签
- name: "projects"
label: "Projects"
# 内容存储目录
folder: "src/content/projects"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{slug}}"
# 文件存储格式
format: "json"
# 字段列表
fields:
- # 项目标题
{ label: "Title", name: "title", widget: "string" }
- # 项目描述
{ label: "Description", name: "description", widget: "text" }
- # 项目封面
{ label: "Image", name: "image", widget: "image", required: false }
- # 项目类别
{ label: "Category", name: "category", widget: "select", options: ["library","ai","software","website","game"] }
- # 技术栈
{ label: "Tech Stack", name: "techStack", widget: "list", default: [] }
- # 项目状态
{ label: "Status", name: "status", widget: "select", options: ["completed","in-progress","planned"] }
- # 在线演示
{ label: "Live Demo", name: "liveDemo", widget: "string", required: false }
- # 源代码
{ label: "Source Code", name: "sourceCode", widget: "string", required: false }
- # 开始日期
{ label: "Start Date", name: "startDate", widget: "datetime" }
- # 结束日期
{ label: "End Date", name: "endDate", widget: "datetime", required: false }
- # 是否精选
{ label: "Featured", name: "featured", widget: "boolean", required: false, default: false }
- # 标签
{ label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- { label: "Title", name: "title", widget: "string" }
- { label: "Description", name: "description", widget: "text" }
- { label: "Image", name: "image", widget: "image", required: false }
- { label: "Category", name: "category", widget: "select", options: ["library","ai","software","website","game"] }
- { label: "Tech Stack", name: "techStack", widget: "list", default: [] }
- { label: "Status", name: "status", widget: "select", options: ["completed","in-progress","planned"] }
- { label: "Live Demo", name: "liveDemo", widget: "string", required: false }
- { label: "Source Code", name: "sourceCode", widget: "string", required: false }
- { label: "Start Date", name: "startDate", widget: "datetime" }
- { label: "End Date", name: "endDate", widget: "datetime", required: false }
- { label: "Featured", name: "featured", widget: "boolean", required: false, default: false }
- { label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- # 技能集合
# 集合名称
name: "skills"
# 后台显示标签
- name: "skills"
label: "Skills"
# 内容存储目录
folder: "src/content/skills"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{slug}}"
# 文件存储格式
format: "json"
# 字段列表
fields:
- # 技能名称
{ label: "Name", name: "name", widget: "string" }
- # 技能描述
{ label: "Description", name: "description", widget: "text" }
- # 图标
{ label: "Icon", name: "icon", widget: "string" }
- # 技能类别
{ label: "Category", name: "category", widget: "select", options: ["ai","backend","client","frontend","database","engines","tools","others"] }
- # 熟练程度
{ label: "Level", name: "level", widget: "select", options: ["beginner","intermediate","advanced","expert"] }
- # 经验
label: "Experience"
- { label: "Name", name: "name", widget: "string" }
- { label: "Description", name: "description", widget: "text" }
- { label: "Icon", name: "icon", widget: "string" }
- { label: "Category", name: "category", widget: "select", options: ["ai","backend","client","frontend","database","engines","tools","others"] }
- { label: "Level", name: "level", widget: "select", options: ["beginner","intermediate","advanced","expert"] }
- label: "Experience"
name: "experience"
widget: "object"
fields:
- # 年
{ label: "Years", name: "years", widget: "number", value_type: "int", min: 0 }
- # 月
{ label: "Months", name: "months", widget: "number", value_type: "int", min: 0, max: 11 }
- # 相关项目
{ label: "Projects", name: "projects", widget: "list", required: false, default: [] }
- # 相关认证
{ label: "Certifications", name: "certifications", widget: "list", required: false, default: [] }
- # 主题颜色
{ label: "Color", name: "color", widget: "string", required: false }
- { label: "Years", name: "years", widget: "number", value_type: "int", min: 0 }
- { label: "Months", name: "months", widget: "number", value_type: "int", min: 0, max: 11 }
- { label: "Projects", name: "projects", widget: "list", required: false, default: [] }
- { label: "Certifications", name: "certifications", widget: "list", required: false, default: [] }
- { label: "Color", name: "color", widget: "string", required: false }
- # 时间线集合
# 集合名称
name: "timeline"
# 后台显示标签
- name: "timeline"
label: "Timeline"
# 内容存储目录
folder: "src/content/timeline"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{slug}}"
# 文件存储格式
format: "json"
# 字段列表
fields:
- # 标题
{ label: "Title", name: "title", widget: "string" }
- # 描述
{ label: "Description", name: "description", widget: "text" }
- # 类型
{ label: "Type", name: "type", widget: "select", options: ["education","work","project","achievement"] }
- # 开始日期
{ label: "Start Date", name: "startDate", widget: "datetime" }
- # 结束日期
{ label: "End Date", name: "endDate", widget: "datetime", required: false }
- # 地点
{ label: "Location", name: "location", widget: "string", required: false }
- # 组织/机构
{ label: "Organization", name: "organization", widget: "string", required: false }
- # 职位
{ label: "Position", name: "position", widget: "string", required: false }
- # 相关技能
{ label: "Skills", name: "skills", widget: "list", required: false, default: [] }
- # 相关成就
{ label: "Achievements", name: "achievements", widget: "list", required: false, default: [] }
- # 相关链接
label: "Links"
- { label: "Title", name: "title", widget: "string" }
- { label: "Description", name: "description", widget: "text" }
- { label: "Type", name: "type", widget: "select", options: ["education","work","project","achievement"] }
- { label: "Start Date", name: "startDate", widget: "datetime" }
- { label: "End Date", name: "endDate", widget: "datetime", required: false }
- { label: "Location", name: "location", widget: "string", required: false }
- { label: "Organization", name: "organization", widget: "string", required: false }
- { label: "Position", name: "position", widget: "string", required: false }
- { label: "Skills", name: "skills", widget: "list", required: false, default: [] }
- { label: "Achievements", name: "achievements", widget: "list", required: false, default: [] }
- label: "Links"
name: "links"
widget: "list"
required: false
fields:
- # 链接名称
{ label: "Name", name: "name", widget: "string" }
- # 链接地址
{ label: "URL", name: "url", widget: "string" }
- # 链接类型
{ label: "Type", name: "type", widget: "select", options: ["certificate","project","other"] }
- # 图标
{ label: "Icon", name: "icon", widget: "string", required: false }
- # 主题颜色
{ label: "Color", name: "color", widget: "string", required: false }
- { label: "Name", name: "name", widget: "string" }
- { label: "URL", name: "url", widget: "string" }
- { label: "Type", name: "type", widget: "select", options: ["certificate","project","other"] }
- { label: "Icon", name: "icon", widget: "string", required: false }
- { label: "Color", name: "color", widget: "string", required: false }
- # 日记集合
# 集合名称
name: "diary"
# 后台显示标签
- name: "diary"
label: "Diary"
# 内容存储目录
folder: "src/content/diary"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{year}}-{{month}}-{{day}}-{{hour}}-{{minute}}"
# 文件存储格式
format: "json"
# 字段列表
fields:
- # 日记内容
{ label: "Content", name: "content", widget: "text" }
- # 日记日期
{ label: "Date", name: "date", widget: "datetime" }
- # 图片列表
label: "Images"
- { label: "Content", name: "content", widget: "text" }
- { label: "Date", name: "date", widget: "datetime" }
- label: "Images"
name: "images"
widget: "list"
required: false
default: []
field: { label: "Image", name: "image", widget: "image" }
- # 相册集合
# 集合名称
name: "albums"
# 后台显示标签
- name: "albums"
label: "Albums"
# 内容存储目录
folder: "src/content/albums"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{slug}}"
# 文件存储格式
format: "json"
# 字段列表
fields:
- # 相册标题
{ label: "Title", name: "title", widget: "string" }
- # 相册描述
{ label: "Description", name: "description", widget: "text", required: false }
- # 相册封面
{ label: "Cover", name: "cover", widget: "image" }
- # 日期
{ label: "Date", name: "date", widget: "datetime" }
- # 地点
{ label: "Location", name: "location", widget: "string", required: false }
- # 标签
{ label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- # 布局方式
{ label: "Layout", name: "layout", widget: "select", options: ["grid", "masonry", "list"], default: "grid" }
- # 列数
{ label: "Columns", name: "columns", widget: "number", default: 3, value_type: "int", min: 1, max: 6 }
- # 照片列表
label: "Photos"
- { label: "Title", name: "title", widget: "string" }
- { label: "Description", name: "description", widget: "text", required: false }
- { label: "Cover", name: "cover", widget: "image" }
- { label: "Date", name: "date", widget: "datetime" }
- { label: "Location", name: "location", widget: "string", required: false }
- { label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- { label: "Layout", name: "layout", widget: "select", options: ["grid", "masonry", "list"], default: "grid" }
- { label: "Columns", name: "columns", widget: "number", default: 3, value_type: "int", min: 1, max: 6 }
- label: "Photos"
name: "photos"
widget: "list"
required: false
fields:
- # 图片路径
{ label: "Image", name: "src", widget: "image" }
- # 图片描述
{ label: "Caption", name: "alt", widget: "string", required: false }
- # 图片标题
{ label: "Title", name: "title", widget: "string", required: false }
- # 图片说明
{ label: "Description", name: "description", widget: "text", required: false }
- # 标签
{ label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- # 拍摄日期
{ label: "Date", name: "date", widget: "datetime", required: false }
- # 是否可见
{ label: "Visible", name: "visible", widget: "boolean", default: true, required: false }
- { label: "Image", name: "src", widget: "image" }
- { label: "Caption", name: "alt", widget: "string", required: false }
- { label: "Title", name: "title", widget: "string", required: false }
- { label: "Description", name: "description", widget: "text", required: false }
- { label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- { label: "Date", name: "date", widget: "datetime", required: false }
- { label: "Visible", name: "visible", widget: "boolean", default: true, required: false }
- # 友链集合
# 集合名称
name: "friends"
# 后台显示标签
- name: "friends"
label: "Friends"
# 内容存储目录
folder: "src/content/friends"
# 允许创建新条目
create: true
# 文件命名规则
slug: "{{slug}}"
# 文件存储格式
format: "json"
# 字段列表
fields:
- # 网站名称
{ label: "Title", name: "title", widget: "string" }
- # 头像链接
{ label: "Avatar URL", name: "imgurl", widget: "string" }
- # 网站描述
{ label: "Description", name: "desc", widget: "text" }
- # 网站链接
{ label: "Site URL", name: "siteurl", widget: "string" }
- # 标签
{ label: "Tags", name: "tags", widget: "list", required: false, default: [] }
- { label: "Title", name: "title", widget: "string" }
- { label: "Avatar URL", name: "imgurl", widget: "string" }
- { label: "Description", name: "desc", widget: "text" }
- { label: "Site URL", name: "siteurl", widget: "string" }
- { label: "Tags", name: "tags", widget: "list", required: false, default: [] }
# 编辑器配置
editor:
# 启用预览功能
preview: true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

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

@@ -0,0 +1,274 @@
import Key from "@i18n/i18nKey";
import type { Translation } from "@i18n/translation";
export const ru: 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]: "Backend разработка",
[Key.skillsClient]: "Client разработка",
[Key.skillsFrontend]: "Frontend разработка",
[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]: "RSS (Really 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]: "Переключиться на локальный режим",
[Key.musicSwitchToMeting]: "Переключиться на режим Meting",
[Key.musicProgress]: "Прогресс",
[Key.musicCollapse]: "Свернуть проигрыватель",
[Key.musicVolume]: "Громкость",
[Key.musicExpand]: "Развернуть музыкальный проигрыватель",
};

View File

@@ -2,6 +2,7 @@ import { getResolvedSiteLang } from "@utils/language";
import { en } from "./languages/en";
import { ja } from "./languages/ja";
import { zh } from "./languages/zh";
import { ru } from "./languages/ru";
import type I18nKey from "./i18nKey";
@@ -20,6 +21,8 @@ const map: { [key: string]: Translation } = {
zh_cn: zh,
ja: ja,
ja_jp: ja,
ru: ru,
ru_ru: ru,
};
export function getTranslation(lang: string): Translation {

View File

@@ -1,434 +1,162 @@
# 站点配置
site:
# 站点 URL以斜杠结尾
siteURL: "https://twilight.spr-aachen.com/"
# 站点标题
title: "Twilight"
# 站点副标题
subtitle: "Blog Template"
# 语言配置
lang: "en"
# 翻译配置
siteURL: "https://stepanovplaton.ru/"
title: "Степанов Платон"
subtitle: ""
lang: "ru"
translate:
# 启用翻译功能
enable: true
# 翻译服务
enable: false
service: "client.edge"
# 显示语言选择下拉框
showSelectTag: false
# 自动检测用户语言
autoDiscriminate: true
# 翻译时忽略的 CSS 类名
ignoreClasses:
- "ignore"
- "banner-title"
- "banner-subtitle"
# 翻译时忽略的 HTML 标签
ignoreTags:
- "script"
- "style"
- "code"
- "pre"
# 时区配置
timeZone: 8
# 字体配置
timeZone: 4
font:
# 示例字体配置 - Zen Maru Gothic
"Example - ZenMaruGothic":
# 字体源 (字体 CSS 链接 | 字体文件路径)
src: "https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic&display=swap"
# 字体名 (font-family)
family: "Zen Maru Gothic"
# 主题色配置
themeColor:
# 主题色的默认色相 (范围从 0 到 360。例如红色0青色200蓝绿色250粉色345)
hue: 255
# 默认主题 ("system" 跟随系统 | "light" 浅色 | "dark" 深色)
hue: 55
fixed: true
defaultTheme: "dark"
# 壁纸配置
wallpaper:
# 模式 ("banner" 横幅 | "fullscreen" 全屏 | "none" 纯色)
mode: "banner"
# 图片源配置 (fullscreen 和 banner 模式共享)
mode: "fullscreen"
src:
# 桌面壁纸图片 (相对于 /public 目录; 支持单张图片或图片数组,当数组长度 > 1 时自动启用轮播)
desktop:
- "/assets/images/desktopWallpaper_1.jpg"
- "/assets/images/desktopWallpaper_2.jpg"
- "/assets/images/desktopWallpaper_3.jpg"
# 移动壁纸图片 (相对于 /public 目录; 支持单张图片或图片数组,当数组长度 > 1 时自动启用轮播)
- "/assets/images/banner1.png"
mobile:
- "/assets/images/mobileWallpaper_1.jpg"
- "/assets/images/mobileWallpaper_2.jpg"
# 壁纸位置 ('top' | 'center' | 'bottom')
- "/assets/images/banner1.png"
position: "center"
# 轮播配置 (fullscreen 和 banner 模式共享)
carousel:
# 为多张图片启用轮播,否则随机显示一张图片
enable: true
# 轮播间隔时间 (秒)
interval: 3.6
# 启用 Ken Burns 效果
kenBurns: true
# Banner 模式专属配置
banner:
# 横幅文本配置
homeText:
# 在主页显示文本
enable: true
# 主标题
title: "Twilight"
# 副标题,支持单个字符串或字符串数组
subtitle:
- "Illuminate Our Paths"
# 副标题打字机效果
typewriter:
# 启用副标题打字机效果
enable: true
# 打字速度 (毫秒)
speed: 111
# 删除速度 (毫秒)
deleteSpeed: 51
# 完全显示后的暂停时间 (毫秒)
pauseTime: 3000
# 横幅图片来源文本
credit:
# 显示横幅图片来源文本
enable: false
# 要显示的来源文本
text: "Describe"
# (可选) 原始艺术品或艺术家页面的 URL 链接
url: ""
# 导航栏配置
navbar:
# 导航栏透明模式 ("semi" 半透明加圆角 | "full" 完全透明 | "semifull" 动态透明)
transparentMode: "semifull"
# 水波纹效果配置
waves:
# 启用水波纹效果
title: "Степанов Платон"
subtitle:
- "Программный инженер, разработчик"
typewriter:
enable: true
speed: 111
deleteSpeed: 51
pauseTime: 3000
credit:
enable: false
text: "Describe"
url: ""
navbar:
transparentMode: "semifull"
waves:
enable: true
# 启用性能模式 (简化波浪效果以提升性能)
performanceMode: false
# Fullscreen 模式专属配置
fullscreen:
# 层级
zIndex: -1
# 壁纸透明度0-1之间
opacity: 0.9
# 背景模糊程度 (像素值)
opacity: 0.7
blur: 1
# 导航栏透明模式
navbar:
transparentMode: "semi"
# 加载页配置
loadingOverlay:
# 是否启用加载页
enable: true
# 加载标题配置
title:
# 是否启用加载标题
enable: true
# 加载标题文本
content: "LOADING"
# 动画周期 (s)
content: "Загрузка..."
interval: 1.5
# 加载动画配置
spinner:
# 是否启用加载动画
enable: true
# 动画周期 (s)
interval: 1.5
# favicon 配置
favicon: []
# bangumi 配置
bangumi:
# 用户 ID
userId: "your-bangumi-id"
# OpenGraph 配置
generateOgImages: false
# Umami统计配置
umami:
# 是否显示Umami统计
enabled: false
# UmamiCloudAPI地址
baseUrl: "https://api.umami.is"
# API密钥 (可用环境变量覆盖)
apiKey: ""
# 要插入的Script (可用环境变量覆盖)
scripts: ""
# 导航栏配置
navbar:
# 链接配置 (链接预设位于 src/constants/link-presets.ts 的 LinkPresets)
links:
- # 一级导航链接 - 主页 (预设)
"Home"
- # 一级导航链接 - 归档 (预设)
"Archive"
- # 一级导航链接 - 展览 (自定义)
# 导航名称
name: "Exhibition"
# 导航链接
- "Projects"
- "Skills"
- "Timeline"
- name: "Разное"
url: "/exhibition/"
# 导航图标
icon: "material-symbols:person"
# 导航描述
description: "A collection of my creative works and experiences"
# 子链接
icon: "material-symbols:check-box"
description: ""
children:
- # 二级导航链接 - 项目 (预设)
"Projects"
- # 二级导航链接 - 技能 (预设)
"Skills"
- # 二级导航链接 - 历程 (预设)
"Timeline"
- # 二级导航链接 - 日记 (预设)
"Diary"
- # 二级导航链接 - 相册 (预设)
"Albums"
- # 二级导航链接 - 动画 (预设)
"Anime"
- # 一级导航链接 - 好友 (预设)
"Friends"
- # 一级导航链接 - 关于 (预设)
"About"
- "Diary"
- "Albums"
- "Friends"
- "About"
# 侧边栏配置
sidebar:
# 侧边栏组件配置列表 (侧栏组件预设位于 src/types/config.ts 的 WidgetComponentType)
components:
# 左侧侧边栏
left:
- # 组件 - 资料 (预设)
# 类型
type: "profile"
# 位置策略 ("top" 顶部固定 | "sticky" 粘性)
- type: "profile"
position: "top"
- # 组件 - 公告 (预设)
# 类型
type: "announcement"
# 位置策略 ("top" 顶部固定 | "sticky" 粘性)
position: "top"
- # 组件 - 文章类别 (预设)
# 类型
type: "categories"
# 位置策略 ("top" 顶部固定 | "sticky" 粘性)
#-
# type: "announcement"
# position: "top"
- type: "categories"
position: "sticky"
# 响应式配置
responsive:
# 折叠阈值
collapseThreshold: 5
- # 组件 - 文章标签 (预设)
# 类型
type: "tags"
# 位置策略 ("top" 顶部固定 | "sticky" 粘性)
- type: "tags"
position: "sticky"
# 响应式配置
responsive:
# 折叠阈值
collapseThreshold: 20
# 右侧侧边栏
right:
- # 组件 - 文章目录 (预设)
# 类型
type: "toc"
# 位置策略 ("top" 顶部固定 | "sticky" 粘性)
- type: "toc"
position: "sticky"
# 自定义属性
customProps:
# 目录深度 (1-61 表示只显示 h1 标题2 表示显示 h1 和 h2 标题,依此类推)
depth: 3
- # 组件 - 文章统计 (预设)
# 类型
type: "statistics"
# 位置策略 ("top" 顶部固定 | "sticky" 粘性)
position: "sticky"
# 资料配置
# - type: "statistics"
# position: "sticky"
profile:
# 头像配置 (相对于 /public 目录)
avatar: "/assets/images/avatar.jpg"
# 信息配置
name: "Twilight"
# 简介配置
bio: "Hi"
# 链接配置
name: "Степанов Платон"
bio: ""
links:
- # 链接示例
# 名字
name: "GitHub"
# 图标
- name: "GitHub"
icon: "fa6-brands:github"
# 链接
url: "https://github.com/Spr-Aachen/Twilight"
url: "https://git.stepanovplaton.ru"
- name: "Telegram"
icon: "fa6-brands:telegram"
url: "https://t.me/StepanovPlaton"
# 公告配置
announcement:
# 公告标题
title: "Announcement"
# 公告内容
content: "Welcome to my blog!"
# 允许用户关闭公告
closable: true
# 链接配置
link:
# 启用链接
enable: true
# 链接文本
text: "Learn More"
# 链接 URL
url: "/about/"
# 是否外部链接
external: false
# 文章配置
post:
# 显示“上次编辑”卡片
showLastModified: true
# 在文章内容中显示封面
showCoverInContent: false
# 代码高亮配置
expressiveCode:
# 主题
theme: "github-dark"
# 许可证配置
license:
# 启用许可证
enable: true
# 许可证名称
name: "CC BY-NC-SA 4.0"
# 许可证链接
url: "https://creativecommons.org/licenses/by-nc-sa/4.0/"
# 评论配置
comment:
# 启用评论功能
enable: false
# Twikoo 评论系统配置
post:
showLastModified: true
showCoverInContent: false
expressiveCode:
theme: "github-dark"
license:
enable: true
name: "CC BY-NC-SA 4.0"
url: "https://creativecommons.org/licenses/by-nc-sa/4.0/"
comment:
enable: false
twikoo:
# 环境 ID
envId: "https://twikoo.vercel.app"
# 语言
lang: "en"
# 页脚配置
footer:
# 启用 Footer HTML 注入功能
enable: false
# 自定义 HTML 内容,用于添加备案号等信息
customHtml: ""
# 粒子特效配置
particle:
# 启用粒子特效
enable: true
# 粒子数量
particleNum: 12
# 粒子越界限制次数,-1为无限循环
limitTimes: -1
# 粒子尺寸配置
size:
# 粒子最小尺寸倍数
min: 0.3
# 粒子最大尺寸倍数
max: 0.9
# 粒子透明度配置
opacity:
# 粒子最小不透明度
min: 0.3
# 粒子最大不透明度
max: 0.9
# 粒子移动速度配置
speed:
# 水平移动速度
horizontal:
# 最小值
min: -0.9
# 最大值
max: 0.9
# 垂直移动速度
vertical:
# 最小值
min: 0.15
# 最大值
max: 0.3
# 旋转速度
rotation: 0.12
# 消失速度
fadeSpeed: 0.12
# 粒子层级
zIndex: 100
# 音乐播放器配置
musicPlayer:
# 启用音乐播放器功能
enable: true
# 默认模式 ("meting" API | "local" 本地)
mode: "meting"
# meting 模式专属配置
meting:
# Meting API 地址
meting_api: "https://api.i-meto.com/meting/api"
# 音乐平台
server: "netease"
# 类型 ("playlist" 歌单 | "song" 单曲)
type: "playlist"
# 资源 ID
id: "2161912966"
# local 模式专属配置
local:
# 播放列表
playlist:
- # 列表示例
# 序号
id: 1
# 标题
title: "深海之息"
# 作者
artist: "Youzee Music"
# 封面
cover: "https://p1.music.126.net/PhKOqFtljgHDDpKYM2ADUA==/109951169858309716.jpg"
# 路径
url: "assets/music/深海之息.m4a"
# 时长
duration: 146
# 是否自动播放
autoplay: true
# 看板娘配置
pio:
# 启用看板娘
enable: false
# 模型文件路径
models:
- "/pio/models/pio/model.json"
# 看板娘位置
position: "left"
# 看板娘宽度
width: 280
# 看板娘高度
height: 250
# 展现模式
mode: "draggable"
# 是否在移动设备上隐藏
hiddenOnMobile: true
# 对话框配置
dialog:
# 欢迎词
welcome: "Welcome!"
# 触摸提示
touch:
- "What are you doing?"
- "Stop touching me!"
- "Don't bully me like that!"
- "(。í _ ì。)"
# 首页提示
home: "Click here to go back to homepage!"
# 换装提示
skin:
- "Want to see my new outfit?"
- "The new outfit looks great~"
# 关闭提示
close: "See you next time~"
# 关于链接
link: "https://nav.kungal.org"
musicPlayer:
enable: false
pio:
enable: false