Browse Source

调整多语言架构;新增繁体中文

tsurumure 3 months ago
parent
commit
f4af0593b2

+ 0 - 17
db/__ai_chat_config.sql

@@ -1,17 +0,0 @@
-# /**
-# Source Server Version: 8.0.31
-# Source Database: backendsys
-# Date: 2023/05/23 17:09:22
-# */
-#
-# DROP TABLE IF EXISTS `ai_chat_config`;
-# CREATE TABLE `ai_chat_config` (
-#     PRIMARY KEY (`id`),
-#     `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
-#     `config_key` VARCHAR(255) COMMENT '配置名称',
-#     `config_value` VARCHAR(255) COMMENT '配置值'
-# ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='AI助手配置表';
-#
-# INSERT INTO ai_chat_config(config_key, config_value) VALUES
-#     ('expired_time', 30)
-# ;

+ 41 - 0
db/__b2c_goods.sql

@@ -0,0 +1,41 @@
+/**
+Source Server Version: 8.0.31
+Source Database: backendsys
+Date: 2023/08/18 12:51:10
+*/
+
+DROP TABLE IF EXISTS `b2c_goods`;
+CREATE TABLE `b2c_goods` (
+    PRIMARY KEY (`id`),
+    `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
+    `category_id` BIGINT NOT NULL COMMENT '商品分类ID',
+    `brand_id` BIGINT COMMENT '商品品牌ID',
+    `unit_id` BIGINT COMMENT '商品单位ID',
+    `good_name` VARCHAR(20) NOT NULL COMMENT '商品名称',
+    `good_description` VARCHAR(200) COMMENT '商品描述',
+    `good_content` TEXT COMMENT '商品内容',
+    `good_thumb` VARCHAR(1000) DEFAULT NULL COMMENT '商品缩略图',
+    `good_images` TEXT DEFAULT NULL COMMENT '商品图片',
+    `meta_keyword` VARCHAR(100) COMMENT 'SEO-Keyword',
+    `meta_description` VARCHAR(200) COMMENT 'SEO-Description',
+    `status` TINYINT(1) DEFAULT '-1' COMMENT '商品状态 (-1下架, 1上架)',
+    `del_flag` TINYINT(1) DEFAULT '-1' COMMENT '删除标志 (-1未删除, 1删除)',
+    `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+    INDEX `idx_good_name` (`good_name`)
+) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
+
+INSERT INTO b2c_goods(category_id, brand_id, unit_id, good_name, good_description, good_content, status) VALUES
+    (1, 1, 1, '测试商品-1', '测试商品描述描述-1', '测试商品详情内容内容内容内容-1', 1),
+    (1, 1, 1, '测试商品-2', '测试商品描述描述-2', '测试商品详情内容内容内容内容-2', -1),
+    (1, 1, 1, '测试商品-3', '测试商品描述描述-3', '测试商品详情内容内容内容内容-3', -1),
+    (1, 1, 1, '测试商品-4', '测试商品描述描述-4', '测试商品详情内容内容内容内容-4', -1),
+    (1, 1, 1, '测试商品-5', '测试商品描述描述-5', '测试商品详情内容内容内容内容-5', -1),
+    (1, 1, 1, '测试商品-6', '测试商品描述描述-6', '测试商品详情内容内容内容内容-6', -1),
+    (1, 1, 1, '测试商品-7', '测试商品描述描述-7', '测试商品详情内容内容内容内容-7', -1),
+    (1, 1, 1, '测试商品-8', '测试商品描述描述-8', '测试商品详情内容内容内容内容-8', -1),
+    (1, 1, 1, '测试商品-9', '测试商品描述描述-9', '测试商品详情内容内容内容内容-9', -1),
+    (1, 1, 1, '测试商品-10', '测试商品描述描述-10', '测试商品详情内容内容内容内容-10', -1),
+    (1, 1, 1, '测试商品-11', '测试商品描述描述-11', '测试商品详情内容内容内容内容-11', -1),
+    (1, 1, 1, '测试商品-12', '测试商品描述描述-12', '测试商品详情内容内容内容内容-12', -1)
+;

+ 0 - 30
db/__ds_chat.sql

@@ -1,30 +0,0 @@
-# /**
-# Source Server Version: 8.0.31
-# Source Database: backendsys
-# Date: 2023/05/23 17:09:22
-# */
-#
-# DROP TABLE IF EXISTS `ds_chat`;
-# CREATE TABLE `ds_chat` (
-#     PRIMARY KEY (`id`),
-#     `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
-#     `model` VARCHAR(255) COMMENT '模型',
-#     `history_code` VARCHAR(64) NOT NULL COMMENT '对话历史记录ID',
-#     `user_id` BIGINT COMMENT '用户ID',
-#     `user_nickname` VARCHAR(255) COMMENT '用户名',
-#     `role` VARCHAR(255) COMMENT '对话角色 (user, assistant, system, tool)',
-#     `content` VARCHAR(5000) NOT NULL COMMENT '对话内容',
-#     `content_type` VARCHAR(255) NOT NULL COMMENT '对话内容类型 (LOADING-加载中, SEARCH-搜索, REPLY-回复, REPLY-回复, REPLY_ABORT-回复中止, THINK-思考, THINK_ABORT-思考中止)',
-#     `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-#     INDEX `idx_history_code` (`history_code`),
-#     INDEX `idx_user_id` (`user_id`),
-#     INDEX `idx_model` (`model`)
-# ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Deepseek对话表';
-#
-# INSERT INTO ds_chat(model, history_code, user_id, user_nickname, role, content_type, content) VALUES
-#     ('deepseek-reasoner', '5670822e-f0f7-4635-b766-c9c61edef0fa', 1, '超人', 'user', 'REPLY', '生成一条关于制作蛋糕的文案,适用于家用,用料是纯天然无添加剂,主打绿色健康美味的理念'),
-#     ('deepseek-reasoner', '5670822e-f0f7-4635-b766-c9c61edef0fa', null, null, null, 'THINK', '让我想想用户说这段话的含义'),
-#     ('deepseek-reasoner', '5670822e-f0f7-4635-b766-c9c61edef0fa', null, null, 'assistant', 'REPLY', '在家也能享受绿色健康美味!用纯天然无添加剂的食材,带给你和家人最纯净的美味。从选购新鲜食材到烘焙出炉,每一步都充满温馨与乐趣。让我们一起回归自然,享受绿色健康的蛋糕时光!'),
-#     ('deepseek-chat', '4e69922c-f0e7-4f82-905d-0b375e094092', 1, '超人', 'user', 'REPLY', '你好'),
-#     ('deepseek-chat', '4e69922c-f0e7-4f82-905d-0b375e094092', null, null, 'assistant', 'REPLY', '你好,朋友')
-# ;

+ 0 - 23
db/__ds_chat_history.sql

@@ -1,23 +0,0 @@
-# /**
-# Source Server Version: 8.0.31
-# Source Database: backendsys
-# Date: 2023/05/23 17:09:22
-# */
-#
-# DROP TABLE IF EXISTS `ds_chat_history`;
-# CREATE TABLE `ds_chat_history` (
-#     PRIMARY KEY (`id`),
-#     `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
-#     `history_code` VARCHAR(36) NOT NULL COMMENT '对话历史记录ID',
-#     `user_id` BIGINT NOT NULL COMMENT '用户ID',
-#     `last_content` VARCHAR(255) NOT NULL COMMENT '最后一次的对话内容',
-#     `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-#     `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-#     INDEX `idx_user_id` (`user_id`)
-# ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Deepseek对话历史记录表';
-#
-# INSERT INTO ds_chat_history(history_code, user_id, last_content) VALUES
-#     ('5670822e-f0f7-4635-b766-c9c61edef0fa', 1, '生成一条关于制作蛋糕的文案,适用于家用,用料是纯天然无添加剂,主打绿色健康美味的理念'),
-#     ('3e69922c-f0e7-4f82-905d-0b375e09409c', 1, '你好'),
-#     ('bd55b4e6-9a4b-4904-99cc-b474bc0a86e4', 2, 'Hello')
-# ;

+ 0 - 27
db/__sys_file.sql

@@ -1,27 +0,0 @@
-# /**
-# Source Server Version: 8.0.31
-# Source Database: backendsys
-# Date: 2023/05/23 17:09:22
-# */
-#
-# DROP TABLE IF EXISTS `sys_file`;
-# CREATE TABLE `sys_file` (
-#     PRIMARY KEY (`id`),
-#     `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
-#     `category_id` BIGINT COMMENT '分类ID',
-#     `user_id` BIGINT COMMENT '拥有者',
-#     `name` VARCHAR(255) NOT NULL COMMENT '文件名称',
-#     `file_local_path` VARCHAR(255) COMMENT '本地路径',
-#     `file_remote_path` VARCHAR(255) COMMENT '远程路径',
-#     `file_remote_path_thumb` VARCHAR(255) COMMENT '远程路径 (缩略图)',
-#     `file_key` VARCHAR(255) COMMENT '腾讯云COS路径',
-#     `size` INT COMMENT '文件大小',
-#     `md5` VARCHAR(255) COMMENT '文件MD5',
-#     `chunk_upload_id` VARCHAR(255) COMMENT '文件分片任务ID',
-#     `chunk_count` INT COMMENT '文件分片数量',
-#     `chunk_current_index` INT COMMENT '当前文件分片索引',
-#     `notes` VARCHAR(255) COMMENT '备注',
-#     `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-#     `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
-# ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='系统文件表';
-#

+ 0 - 21
db/__sys_file_category.sql

@@ -1,21 +0,0 @@
-# /**
-# Source Server Version: 8.0.31
-# Source Database: backendsys
-# Date: 2023/05/23 17:09:22
-# */
-#
-# DROP TABLE IF EXISTS `sys_file_category`;
-# CREATE TABLE `sys_file_category` (
-#     PRIMARY KEY (`id`),
-#     `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
-#     `category_name` VARCHAR(255) NOT NULL COMMENT '分类名称',
-#     `suffix` VARCHAR(1000) NOT NULL COMMENT '文件后缀',
-#     `sort` INT DEFAULT '1' COMMENT '排序',
-#     `status` TINYINT(1) DEFAULT '1' COMMENT '资讯状态 (-1禁用, 1启用)'
-# ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='系统文件分类表';
-#
-# INSERT INTO sys_file_category(category_name, suffix) VALUES
-#     ('图片', 'jpg, jpeg, png, gif, bmp, tiff, webp'),
-#     ('视频', 'mp4, avi, mov, mkv, wmv, flv, webm'),
-#     ('音频', 'mp3, wav, ogg, aac')
-# ;

+ 6 - 2
db/cms_article_category_i18n.sql

@@ -16,14 +16,18 @@ CREATE TABLE `cms_article_category_i18n` (
 
 
 INSERT INTO cms_article_category_i18n (article_category_id, language, category_name, category_description) VALUES
 INSERT INTO cms_article_category_i18n (article_category_id, language, category_name, category_description) VALUES
     (1, 'zh', '科技创新', '前沿科技与创新动态'),
     (1, 'zh', '科技创新', '前沿科技与创新动态'),
+    (1, 'zh-tw', '科技創新', '前沿科技與創新動態'),
     (1, 'en', 'Technological Innovation', 'Frontier Technology and Innovation Trends'),
     (1, 'en', 'Technological Innovation', 'Frontier Technology and Innovation Trends'),
     (2, 'zh', '健康生活', '为你解析情感与人际关系'),
     (2, 'zh', '健康生活', '为你解析情感与人际关系'),
+    (2, 'zh-tw', '健康生活', '為你解析情感與人際關係'),
     (2, 'en', 'Healthy life', 'For you to analyze emotions and relationships'),
     (2, 'en', 'Healthy life', 'For you to analyze emotions and relationships'),
     (3, 'zh', '情感关系', '为你解析情感与人际关系'),
     (3, 'zh', '情感关系', '为你解析情感与人际关系'),
+    (3, 'zh-tw', '情感關係', '為你解析情感與人際關係'),
     (3, 'en', 'Emotional Relationships', 'Analyze Emotions and Interpersonal Relationships'),
     (3, 'en', 'Emotional Relationships', 'Analyze Emotions and Interpersonal Relationships'),
     (4, 'zh', '旅行探索', '探索世界各地的旅行分享'),
     (4, 'zh', '旅行探索', '探索世界各地的旅行分享'),
+    (4, 'zh-tw', '旅行探索', '探索世界各地的旅行分享'),
     (4, 'en', 'Travel Exploration', 'Discover Travel Experiences from Around the World'),
     (4, 'en', 'Travel Exploration', 'Discover Travel Experiences from Around the World'),
     (5, 'zh', '美食烹饪', '养眼美食与烹饪技巧'),
     (5, 'zh', '美食烹饪', '养眼美食与烹饪技巧'),
+    (5, 'zh-tw', '美食烹飪', '養眼美食與烹飪技巧'),
     (5, 'en', 'Culinary Delights', 'Eye-pleasing Dishes and Cooking Techniques')
     (5, 'en', 'Culinary Delights', 'Eye-pleasing Dishes and Cooking Techniques')
-;
-
+;

+ 12 - 0
db/cms_article_i18n.sql

@@ -19,27 +19,39 @@ CREATE TABLE `cms_article_i18n` (
 
 
 INSERT INTO cms_article_i18n(article_id, language, title, description, content, meta_keyword, meta_description) VALUES
 INSERT INTO cms_article_i18n(article_id, language, title, description, content, meta_keyword, meta_description) VALUES
     (1, 'zh', '夏日户外露营指南', '如何在户外享受舒适露营', '<h2>夏日户外露营指南</h2><p>夏天是露营的最佳季节,以下是一些实用的露营技巧:</p><ul><li><strong>选择合适的露营地:</strong>选择一个平坦、靠近水源且远离野生动物的地方。</li><li><strong>准备必要的装备:</strong>帐篷、睡袋、防潮垫、头灯、驱蚊剂等。</li><li><strong>注意安全:</strong>在户外要注意防火、防虫、防野生动物。</li></ul><p>希望这些技巧能帮助你在大自然中度过一个愉快的露营之旅!</p>', '露营,户外,指南', '一份全面的户外露营指南,帮助你享受大自然'),
     (1, 'zh', '夏日户外露营指南', '如何在户外享受舒适露营', '<h2>夏日户外露营指南</h2><p>夏天是露营的最佳季节,以下是一些实用的露营技巧:</p><ul><li><strong>选择合适的露营地:</strong>选择一个平坦、靠近水源且远离野生动物的地方。</li><li><strong>准备必要的装备:</strong>帐篷、睡袋、防潮垫、头灯、驱蚊剂等。</li><li><strong>注意安全:</strong>在户外要注意防火、防虫、防野生动物。</li></ul><p>希望这些技巧能帮助你在大自然中度过一个愉快的露营之旅!</p>', '露营,户外,指南', '一份全面的户外露营指南,帮助你享受大自然'),
+    (1, 'zh-tw', '夏日戶外露營指南', '如何在戶外享受舒適露營', '<h2>夏日戶外露營指南</h2><p>夏天是露營的最佳季節,以下是一些實用的露營技巧:</p><ul><li><strong>選擇合適的露營地:</strong>選擇一個平坦、靠近水源且遠離野生動物的地方。</li><li><strong>準備必要的裝備:</strong>帳篷、睡袋、防潮墊、頭燈、驅蚊劑等。</li><li><strong>注意安全:</strong>在戶外要注意防火、防蟲、防野生動物。</li></ul><p>希望這些技巧能幫助你在大自然中度過一個愉快的露營之旅!</p>', '露營,戶外,指南', '一份全面的戶外露營指南,幫助你享受大自然'),
     (1, 'en', 'Summer Camping Guide', 'How to enjoy comfortable camping outdoors', '<h2>Summer Camping Guide</h2><p>Summer is the perfect season for camping. Here are some useful camping tips:</p><ul><li><strong>Choose the right campsite:</strong> Select a flat area near water and away from wildlife.</li><li><strong>Prepare necessary gear:</strong> Tent, sleeping bag, ground pad, headlamp, insect repellent, etc.</li><li><strong>Pay attention to safety:</strong> Be cautious of fire, insects, and wildlife while camping.</li></ul><p>Hope these tips help you enjoy a pleasant camping trip in nature!</p>', 'Camping, outdoors, guide', 'A comprehensive camping guide to help you enjoy nature'),
     (1, 'en', 'Summer Camping Guide', 'How to enjoy comfortable camping outdoors', '<h2>Summer Camping Guide</h2><p>Summer is the perfect season for camping. Here are some useful camping tips:</p><ul><li><strong>Choose the right campsite:</strong> Select a flat area near water and away from wildlife.</li><li><strong>Prepare necessary gear:</strong> Tent, sleeping bag, ground pad, headlamp, insect repellent, etc.</li><li><strong>Pay attention to safety:</strong> Be cautious of fire, insects, and wildlife while camping.</li></ul><p>Hope these tips help you enjoy a pleasant camping trip in nature!</p>', 'Camping, outdoors, guide', 'A comprehensive camping guide to help you enjoy nature'),
     (2, 'zh', '城市夜景摄影技巧', '捕捉城市夜晚的美丽瞬间', '<h2>城市夜景摄影技巧</h2><p>城市夜景摄影可以捕捉到独特的光影效果,以下是一些技巧:</p><ul><li><strong>选择合适的拍摄地点:</strong>高楼大厦的顶部或桥梁是绝佳的拍摄点。</li><li><strong>使用三脚架:</strong>稳定相机,避免手抖影响照片质量。</li><li><strong>调整相机设置:</strong>使用低ISO、小光圈和慢快门,以获得清晰的夜景照片。</li></ul><p>通过这些技巧,你可以拍摄出令人惊叹的城市夜景照片!</p>', '摄影,夜景,技巧', '捕捉城市夜晚的美丽瞬间'),
     (2, 'zh', '城市夜景摄影技巧', '捕捉城市夜晚的美丽瞬间', '<h2>城市夜景摄影技巧</h2><p>城市夜景摄影可以捕捉到独特的光影效果,以下是一些技巧:</p><ul><li><strong>选择合适的拍摄地点:</strong>高楼大厦的顶部或桥梁是绝佳的拍摄点。</li><li><strong>使用三脚架:</strong>稳定相机,避免手抖影响照片质量。</li><li><strong>调整相机设置:</strong>使用低ISO、小光圈和慢快门,以获得清晰的夜景照片。</li></ul><p>通过这些技巧,你可以拍摄出令人惊叹的城市夜景照片!</p>', '摄影,夜景,技巧', '捕捉城市夜晚的美丽瞬间'),
+    (2, 'zh-tw', '城市夜景攝影技巧', '捕捉城市夜晚的美麗瞬間', '<h2>城市夜景攝影技巧</h2><p>城市夜景攝影可以捕捉到獨特的光影效果,以下是一些技巧:</p><ul><li><strong>選擇合適的拍攝地點:</strong>高樓大廈的頂部或橋梁是絕佳的拍攝點。</li><li><strong>使用三腳架:</strong>穩定相機,避免手抖影響照片質量。</li><li><strong>調整相機設置:</strong>使用低ISO、小光圈和慢快門,以獲得清晰的夜景照片。</li></ul><p>通過這些技巧,你可以拍攝出令人驚嘆的城市夜景照片!</p>', '攝影,夜景,技巧', '捕捉城市夜晚的美麗瞬間'),
     (2, 'en', 'Urban Night Photography Tips', 'Capturing the beauty of the city at night', '<h2>Urban Night Photography Tips</h2><p>Capturing the beauty of urban night scenes can produce unique lighting effects. Here are some tips:</p><ul><li><strong>Choose the right shooting location:</strong> The tops of skyscrapers or bridges are excellent spots.</li><li><strong>Use a tripod:</strong> Stabilize the camera to avoid blurry photos due to hand shake.</li><li><strong>Adjust camera settings:</strong> Use low ISO, small aperture, and slow shutter speed for clear night photos.</li></ul><p>With these tips, you can capture amazing urban night photos!</p>', 'Photography, night view, tips', 'Capturing the beauty of the city at night'),
     (2, 'en', 'Urban Night Photography Tips', 'Capturing the beauty of the city at night', '<h2>Urban Night Photography Tips</h2><p>Capturing the beauty of urban night scenes can produce unique lighting effects. Here are some tips:</p><ul><li><strong>Choose the right shooting location:</strong> The tops of skyscrapers or bridges are excellent spots.</li><li><strong>Use a tripod:</strong> Stabilize the camera to avoid blurry photos due to hand shake.</li><li><strong>Adjust camera settings:</strong> Use low ISO, small aperture, and slow shutter speed for clear night photos.</li></ul><p>With these tips, you can capture amazing urban night photos!</p>', 'Photography, night view, tips', 'Capturing the beauty of the city at night'),
     (3, 'zh', '春季赏花好去处', '推荐几个适合赏花的地方', '<h2>春季赏花好去处</h2><p>春天是赏花的好季节,以下是一些国内最美的赏花地点:</p><ul><li><strong>武汉大学樱花大道:</strong>每年三月,樱花盛开,如粉色云霞。</li><li><strong>婺源油菜花田:</strong>金黄的油菜花与古村落相映成趣。</li><li><strong>林芝桃花沟:</strong>桃花盛开时,漫山遍野,如诗如画。</li></ul><p>这些地方不仅能让你欣赏到美丽的花朵,还能感受春天的气息。</p>', '赏花,春季,地点', '推荐几个适合赏花的地方'),
     (3, 'zh', '春季赏花好去处', '推荐几个适合赏花的地方', '<h2>春季赏花好去处</h2><p>春天是赏花的好季节,以下是一些国内最美的赏花地点:</p><ul><li><strong>武汉大学樱花大道:</strong>每年三月,樱花盛开,如粉色云霞。</li><li><strong>婺源油菜花田:</strong>金黄的油菜花与古村落相映成趣。</li><li><strong>林芝桃花沟:</strong>桃花盛开时,漫山遍野,如诗如画。</li></ul><p>这些地方不仅能让你欣赏到美丽的花朵,还能感受春天的气息。</p>', '赏花,春季,地点', '推荐几个适合赏花的地方'),
+    (3, 'zh-tw', '春季賞花好去處', '推薦幾個適合賞花的地方', '<h2>春季賞花好去處</h2><p>春天是賞花的好季節,以下是一些國內最美的賞花地點:</p><ul><li><strong>武漢大學櫻花大道:</strong>每年三月,櫻花盛開,如粉色雲霞。</li><li><strong>婺源油菜花田:</strong>金黃的油菜花與古村落相映成趣。</li><li><strong>林芝桃花溝:</strong>桃花盛開時,漫山遍野,如詩如畫。</li></ul><p>這些地方不僅能讓你欣賞到美麗的花朵,還能感受春天的氣息。</p>', '賞花,春季,地點', '推薦幾個適合賞花的地方'),
     (3, 'en', 'Best Flower Viewing Spots in Spring', 'Recommend some great places for flower viewing', '<h2>Best Flower Viewing Spots in Spring</h2><p>Spring is the perfect season for flower viewing. Here are some of the most beautiful flower viewing spots in the country:</p><ul><li><strong>Wuhan University Cherry Blossom Avenue:</strong> In March every year, the cherry blossoms bloom like pink clouds.</li><li><strong>Wuyuan Rapeseed Flower Fields:</strong> The golden rapeseed flowers contrast beautifully with ancient villages.</li><li><strong>Linzhi Peach Blossom Valley:</strong> When the peach blossoms bloom, the mountains are covered in a picturesque scene.</li></ul><p>These places not only allow you to enjoy beautiful flowers but also let you feel the spring atmosphere.</p>', 'Flower viewing, spring, locations', 'Recommend some great places for flower viewing'),
     (3, 'en', 'Best Flower Viewing Spots in Spring', 'Recommend some great places for flower viewing', '<h2>Best Flower Viewing Spots in Spring</h2><p>Spring is the perfect season for flower viewing. Here are some of the most beautiful flower viewing spots in the country:</p><ul><li><strong>Wuhan University Cherry Blossom Avenue:</strong> In March every year, the cherry blossoms bloom like pink clouds.</li><li><strong>Wuyuan Rapeseed Flower Fields:</strong> The golden rapeseed flowers contrast beautifully with ancient villages.</li><li><strong>Linzhi Peach Blossom Valley:</strong> When the peach blossoms bloom, the mountains are covered in a picturesque scene.</li></ul><p>These places not only allow you to enjoy beautiful flowers but also let you feel the spring atmosphere.</p>', 'Flower viewing, spring, locations', 'Recommend some great places for flower viewing'),
     (4, 'zh', '健身新手入门指南', '如何开始你的健身之旅', '<h2>健身新手入门指南</h2><p>健身可以改善身体素质和健康状况,以下是一些入门建议:</p><ul><li><strong>设定目标:</strong>明确你的健身目标,如增肌、减脂或提高体能。</li><li><strong>制定计划:</strong>根据目标制定合理的训练和饮食计划。</li><li><strong>逐步开始:</strong>从简单的动作开始,逐渐增加难度和强度。</li></ul><p>希望这些指南能帮助你迈出健身的第一步!</p>', '健身,新手,指南', '帮助你开始健身之旅'),
     (4, 'zh', '健身新手入门指南', '如何开始你的健身之旅', '<h2>健身新手入门指南</h2><p>健身可以改善身体素质和健康状况,以下是一些入门建议:</p><ul><li><strong>设定目标:</strong>明确你的健身目标,如增肌、减脂或提高体能。</li><li><strong>制定计划:</strong>根据目标制定合理的训练和饮食计划。</li><li><strong>逐步开始:</strong>从简单的动作开始,逐渐增加难度和强度。</li></ul><p>希望这些指南能帮助你迈出健身的第一步!</p>', '健身,新手,指南', '帮助你开始健身之旅'),
+    (4, 'zh-tw', '健身新手入門指南', '如何開始你的健身之旅', '<h2>健身新手入門指南</h2><p>健身可以改善身體素質和健康狀況,以下是一些入門建議:</p><ul><li><strong>設定目標:</strong>明確你的健身目標,如增肌、減脂或提高體能。</li><li><strong>制定計劃:</strong>根據目標制定合理的訓練和飲食計劃。</li><li><strong>逐步開始:</strong>從簡單的動作開始,逐漸增加難度和強度。</li></ul><p>希望這些指南能幫助你邁出健身的第一步!</p>', '健身,新手,指南', '幫助你開始健身之旅'),
     (4, 'en', 'Fitness Beginner\'s Guide', 'How to start your fitness journey', '<h2>Fitness Beginner\'s Guide</h2><p>Fitness can improve physical fitness and health. Here are some tips for getting started:</p><ul><li><strong>Set goals:</strong> Clarify your fitness goals, such as muscle building, fat loss, or improving physical fitness.</li><li><strong>Make a plan:</strong> Create a reasonable training and diet plan based on your goals.</li><li><strong>Start gradually:</strong> Begin with simple exercises and gradually increase the difficulty and intensity.</li></ul><p>Hope these guides help you take the first step in fitness!</p>', 'Fitness, beginner, guide', 'Help you start your fitness journey'),
     (4, 'en', 'Fitness Beginner\'s Guide', 'How to start your fitness journey', '<h2>Fitness Beginner\'s Guide</h2><p>Fitness can improve physical fitness and health. Here are some tips for getting started:</p><ul><li><strong>Set goals:</strong> Clarify your fitness goals, such as muscle building, fat loss, or improving physical fitness.</li><li><strong>Make a plan:</strong> Create a reasonable training and diet plan based on your goals.</li><li><strong>Start gradually:</strong> Begin with simple exercises and gradually increase the difficulty and intensity.</li></ul><p>Hope these guides help you take the first step in fitness!</p>', 'Fitness, beginner, guide', 'Help you start your fitness journey'),
     (5, 'zh', '冬季滑雪攻略', '如何享受滑雪的乐趣', '<h2>冬季滑雪攻略</h2><p>冬季是滑雪的最佳季节,以下是一些滑雪技巧:</p><ul><li><strong>选择合适的滑雪场:</strong>根据自己的水平选择适合的滑雪场。</li><li><strong>准备必要的装备:</strong>滑雪板、滑雪靴、护具、头盔等。</li><li><strong>注意安全:</strong>遵循滑雪场的规则,避免危险动作。</li></ul><p>希望这些攻略能帮助你在雪地上尽情驰骋!</p>', '滑雪,冬季,攻略', '享受滑雪的乐趣'),
     (5, 'zh', '冬季滑雪攻略', '如何享受滑雪的乐趣', '<h2>冬季滑雪攻略</h2><p>冬季是滑雪的最佳季节,以下是一些滑雪技巧:</p><ul><li><strong>选择合适的滑雪场:</strong>根据自己的水平选择适合的滑雪场。</li><li><strong>准备必要的装备:</strong>滑雪板、滑雪靴、护具、头盔等。</li><li><strong>注意安全:</strong>遵循滑雪场的规则,避免危险动作。</li></ul><p>希望这些攻略能帮助你在雪地上尽情驰骋!</p>', '滑雪,冬季,攻略', '享受滑雪的乐趣'),
+    (5, 'zh-tw', '冬季滑雪攻略', '如何享受滑雪的樂趣', '<h2>冬季滑雪攻略</h2><p>冬季是滑雪的最佳季節,以下是一些滑雪技巧:</p><ul><li><strong>選擇合適的滑雪場:</strong>根據自己的水平選擇適合的滑雪場。</li><li><strong>準備必要的裝備:</strong>滑雪板、滑雪靴、護具、頭盔等。</li><li><strong>注意安全:</strong>遵循滑雪場的規則,避免危險動作。</li></ul><p>希望這些攻略能幫助你在雪地上盡情馳騁!</p>', '滑雪,冬季,攻略', '享受滑雪的樂趣'),
     (5, 'en', 'Winter Skiing Tips', 'How to enjoy skiing', '<h2>Winter Skiing Tips</h2><p>Winter is the perfect season for skiing. Here are some skiing tips:</p><ul><li><strong>Choose the right ski resort:</strong> Select a ski resort suitable for your skill level.</li><li><strong>Prepare necessary gear:</strong> Skis, ski boots, protective gear, helmet, etc.</li><li><strong>Pay attention to safety:</strong> Follow the ski resort rules and avoid dangerous maneuvers.</li></ul><p>Hope these tips help you enjoy skiing on the snow!</p>', 'Skiing, winter, tips', 'Enjoy skiing'),
     (5, 'en', 'Winter Skiing Tips', 'How to enjoy skiing', '<h2>Winter Skiing Tips</h2><p>Winter is the perfect season for skiing. Here are some skiing tips:</p><ul><li><strong>Choose the right ski resort:</strong> Select a ski resort suitable for your skill level.</li><li><strong>Prepare necessary gear:</strong> Skis, ski boots, protective gear, helmet, etc.</li><li><strong>Pay attention to safety:</strong> Follow the ski resort rules and avoid dangerous maneuvers.</li></ul><p>Hope these tips help you enjoy skiing on the snow!</p>', 'Skiing, winter, tips', 'Enjoy skiing'),
     (6, 'zh', '春季养生小贴士', '春季如何保持健康', '<h2>春季养生小贴士</h2><p>春季是万物复苏的季节,也是养生的好时机。以下是一些春季养生的小贴士:</p><ul><li><strong>饮食清淡:</strong>多吃蔬菜水果,少吃油腻食物。</li><li><strong>适当运动:</strong>选择适合自己的运动方式,如散步、慢跑等。</li><li><strong>保持心情舒畅:</strong>避免情绪波动,保持心态平和。</li></ul><p>希望这些小贴士能帮助你度过一个健康的春季!</p>', '春季,养生,健康', '春季养生小贴士,帮助你保持健康'),
     (6, 'zh', '春季养生小贴士', '春季如何保持健康', '<h2>春季养生小贴士</h2><p>春季是万物复苏的季节,也是养生的好时机。以下是一些春季养生的小贴士:</p><ul><li><strong>饮食清淡:</strong>多吃蔬菜水果,少吃油腻食物。</li><li><strong>适当运动:</strong>选择适合自己的运动方式,如散步、慢跑等。</li><li><strong>保持心情舒畅:</strong>避免情绪波动,保持心态平和。</li></ul><p>希望这些小贴士能帮助你度过一个健康的春季!</p>', '春季,养生,健康', '春季养生小贴士,帮助你保持健康'),
+    (6, 'zh-tw', '春季養生小貼士', '春季如何保持健康', '<h2>春季養生小貼士</h2><p>春季是萬物復甦的季節,也是養生的好時機。以下是一些春季養生的小貼士:</p><ul><li><strong>飲食清淡:</strong>多吃蔬菜水果,少吃油膩食物。</li><li><strong>適當運動:</strong>選擇適合自己的運動方式,如散步、慢跑等。</li><li><strong>保持心情舒暢:</strong>避免情緒波動,保持心態平和。</li></ul><p>希望這些小貼士能幫助你度過一個健康的春季!</p>', '春季,養生,健康', '春季養生小貼士,幫助你保持健康'),
     (6, 'en', 'Spring Health Tips', 'How to stay healthy in spring', '<h2>Spring Health Tips</h2><p>Spring is the season of renewal and a great time for health maintenance. Here are some tips for staying healthy in spring:</p><ul><li><strong>Eat lightly:</strong> Focus on vegetables and fruits, and avoid greasy foods.</li><li><strong>Exercise moderately:</strong> Choose activities like walking or jogging.</li><li><strong>Stay in good spirits:</strong> Avoid emotional fluctuations and maintain a peaceful mindset.</li></ul><p>Hope these tips help you have a healthy spring!</p>', 'Spring, health, tips', 'Spring health tips to keep you in good shape'),
     (6, 'en', 'Spring Health Tips', 'How to stay healthy in spring', '<h2>Spring Health Tips</h2><p>Spring is the season of renewal and a great time for health maintenance. Here are some tips for staying healthy in spring:</p><ul><li><strong>Eat lightly:</strong> Focus on vegetables and fruits, and avoid greasy foods.</li><li><strong>Exercise moderately:</strong> Choose activities like walking or jogging.</li><li><strong>Stay in good spirits:</strong> Avoid emotional fluctuations and maintain a peaceful mindset.</li></ul><p>Hope these tips help you have a healthy spring!</p>', 'Spring, health, tips', 'Spring health tips to keep you in good shape'),
     (7, 'zh', '家庭园艺入门指南', '如何打造自己的小花园', '<h2>家庭园艺入门指南</h2><p>园艺不仅能美化环境,还能带来乐趣。以下是一些家庭园艺的入门建议:</p><ul><li><strong>选择合适的植物:</strong>根据光照条件选择适合的植物。</li><li><strong>准备基本工具:</strong>铲子、喷壶、花盆等。</li><li><strong>定期浇水和施肥:</strong>保持土壤湿润,适时补充养分。</li></ul><p>希望这些指南能帮助你打造一个美丽的小花园!</p>', '园艺,家庭,入门', '家庭园艺入门指南,打造你的小花园'),
     (7, 'zh', '家庭园艺入门指南', '如何打造自己的小花园', '<h2>家庭园艺入门指南</h2><p>园艺不仅能美化环境,还能带来乐趣。以下是一些家庭园艺的入门建议:</p><ul><li><strong>选择合适的植物:</strong>根据光照条件选择适合的植物。</li><li><strong>准备基本工具:</strong>铲子、喷壶、花盆等。</li><li><strong>定期浇水和施肥:</strong>保持土壤湿润,适时补充养分。</li></ul><p>希望这些指南能帮助你打造一个美丽的小花园!</p>', '园艺,家庭,入门', '家庭园艺入门指南,打造你的小花园'),
+    (7, 'zh-tw', '家庭園藝入門指南', '如何打造自己的小花園', '<h2>家庭園藝入門指南</h2><p>園藝不仅能美化環境,還能帶來樂趣。以下是一些家庭園藝的入門建議:</p><ul><li><strong>選擇合適的植物:</strong>根據光照條件選擇適合的植物。</li><li><strong>準備基本工具:</strong>鏟子、噴壺、花盆等。</li><li><strong>定期澆水和施肥:</strong>保持土壤濕潤,適時補充養分。</li></ul><p>希望這些指南能幫助你打造一個美麗的小花園!</p>', '園藝,家庭,入門', '家庭園藝入門指南,打造你的小花園'),
     (7, 'en', 'Home Gardening Beginner\'s Guide', 'How to create your own little garden', '<h2>Home Gardening Beginner\'s Guide</h2><p>Gardening not only beautifies the environment but also brings joy. Here are some tips for getting started with home gardening:</p><ul><li><strong>Choose the right plants:</strong> Select plants based on your light conditions.</li><li><strong>Prepare basic tools:</strong> Trowel, watering can, pots, etc.</li><li><strong>Water and fertilize regularly:</strong> Keep the soil moist and add nutrients as needed.</li></ul><p>Hope these guides help you create a beautiful little garden!</p>', 'Gardening, home, beginner', 'Home gardening guide to create your own garden'),
     (7, 'en', 'Home Gardening Beginner\'s Guide', 'How to create your own little garden', '<h2>Home Gardening Beginner\'s Guide</h2><p>Gardening not only beautifies the environment but also brings joy. Here are some tips for getting started with home gardening:</p><ul><li><strong>Choose the right plants:</strong> Select plants based on your light conditions.</li><li><strong>Prepare basic tools:</strong> Trowel, watering can, pots, etc.</li><li><strong>Water and fertilize regularly:</strong> Keep the soil moist and add nutrients as needed.</li></ul><p>Hope these guides help you create a beautiful little garden!</p>', 'Gardening, home, beginner', 'Home gardening guide to create your own garden'),
     (8, 'zh', '夏季防晒全攻略', '如何有效防晒', '<h2>夏季防晒全攻略</h2><p>夏季阳光强烈,防晒至关重要。以下是一些防晒建议:</p><ul><li><strong>选择合适的防晒霜:</strong>SPF 30 以上,PA+++ 为佳。</li><li><strong>定时补涂:</strong>每 2-3 小时补涂一次。</li><li><strong>避免长时间暴晒:</strong>尽量减少在紫外线最强时段外出。</li></ul><p>希望这些攻略能帮助你有效防晒,享受夏日阳光!</p>', '防晒,夏季,攻略', '夏季防晒全攻略,保护你的皮肤'),
     (8, 'zh', '夏季防晒全攻略', '如何有效防晒', '<h2>夏季防晒全攻略</h2><p>夏季阳光强烈,防晒至关重要。以下是一些防晒建议:</p><ul><li><strong>选择合适的防晒霜:</strong>SPF 30 以上,PA+++ 为佳。</li><li><strong>定时补涂:</strong>每 2-3 小时补涂一次。</li><li><strong>避免长时间暴晒:</strong>尽量减少在紫外线最强时段外出。</li></ul><p>希望这些攻略能帮助你有效防晒,享受夏日阳光!</p>', '防晒,夏季,攻略', '夏季防晒全攻略,保护你的皮肤'),
+    (8, 'zh-tw', '夏季防曬全攻略', '如何有效防曬', '<h2>夏季防曬全攻略</h2><p>夏季陽光強烈,防曬至關重要。以下是一些防曬建議:</p><ul><li><strong>選擇合適的防曬霜:</strong>SPF 30 以上,PA+++ 為佳。</li><li><strong>定時補塗:</strong>每 2-3 小時補塗一次。</li><li><strong>避免長時間暴曬:</strong>盡量減少在紫外線最強時段外出。</li></ul><p>希望這些攻略能幫助你有效防曬,享受夏日陽光!</p>', '防曬,夏季,攻略', '夏季防曬全攻略,保護你的皮膚'),
     (8, 'en', 'Summer Sun Protection Guide', 'How to protect your skin from the sun', '<h2>Summer Sun Protection Guide</h2><p>With intense summer sun, sun protection is essential. Here are some tips:</p><ul><li><strong>Choose the right sunscreen:</strong> SPF 30 or higher, PA+++ is recommended.</li><li><strong>Reapply regularly:</strong> Every 2-3 hours.</li><li><strong>Avoid prolonged exposure:</strong> Minimize outdoor activities during peak UV hours.</li></ul><p>Hope these tips help you enjoy the summer sun while staying protected!</p>', 'Sun protection, summer, guide', 'Summer sun protection guide to keep your skin safe'),
     (8, 'en', 'Summer Sun Protection Guide', 'How to protect your skin from the sun', '<h2>Summer Sun Protection Guide</h2><p>With intense summer sun, sun protection is essential. Here are some tips:</p><ul><li><strong>Choose the right sunscreen:</strong> SPF 30 or higher, PA+++ is recommended.</li><li><strong>Reapply regularly:</strong> Every 2-3 hours.</li><li><strong>Avoid prolonged exposure:</strong> Minimize outdoor activities during peak UV hours.</li></ul><p>Hope these tips help you enjoy the summer sun while staying protected!</p>', 'Sun protection, summer, guide', 'Summer sun protection guide to keep your skin safe'),
     (9, 'zh', '秋季美食推荐', '秋季不可错过的美食', '<h2>秋季美食推荐</h2><p>秋季是丰收的季节,有许多美味的食物值得一试:</p><ul><li><strong>大闸蟹:</strong>肉质鲜美,营养丰富。</li><li><strong>栗子:</strong>香甜可口,适合烤制或煮食。</li><li><strong>南瓜:</strong>口感软糯,可做多种菜肴。</li></ul><p>这些美食不仅能满足味蕾,还能补充营养,让你享受秋季的丰收喜悦!</p>', '美食,秋季,推荐', '秋季美食推荐,享受丰收的美味'),
     (9, 'zh', '秋季美食推荐', '秋季不可错过的美食', '<h2>秋季美食推荐</h2><p>秋季是丰收的季节,有许多美味的食物值得一试:</p><ul><li><strong>大闸蟹:</strong>肉质鲜美,营养丰富。</li><li><strong>栗子:</strong>香甜可口,适合烤制或煮食。</li><li><strong>南瓜:</strong>口感软糯,可做多种菜肴。</li></ul><p>这些美食不仅能满足味蕾,还能补充营养,让你享受秋季的丰收喜悦!</p>', '美食,秋季,推荐', '秋季美食推荐,享受丰收的美味'),
+    (9, 'zh-tw', '秋季美食推薦', '秋季不可錯過的美食', '<h2>秋季美食推薦</h2><p>秋季是豐收的季節,有許多美味的食物值得一試:</p><ul><li><strong>大閘蟹:</strong>肉質鮮美,營養豐富。</li><li><strong>栗子:</strong>香甜可口,適合烤制或煮食。</li><li><strong>南瓜:</strong>口感軟糯,可做多種菜肴。</li></ul><p>這些美食不僅能滿足味蕾,還能補充營養,讓你享受秋季的豐收喜悅!</p>', '美食,秋季,推薦', '秋季美食推薦,享受豐收的美味'),
     (9, 'en', 'Autumn Food Recommendations', 'Delicious foods to enjoy in autumn', '<h2>Autumn Food Recommendations</h2><p>Autumn is the season of harvest, with many delicious foods to try:</p><ul><li><strong>Crab:</strong> Tender and nutritious.</li><li><strong>Chestnuts:</strong> Sweet and delicious, perfect for roasting or boiling.</li><li><strong>Pumpkin:</strong> Soft and versatile, great for various dishes.</li></ul><p>These foods not only satisfy your taste buds but also provide nutrition, letting you enjoy the joy of autumn harvest!</p>', 'Food, autumn, recommendations', 'Autumn food recommendations to enjoy the harvest'),
     (9, 'en', 'Autumn Food Recommendations', 'Delicious foods to enjoy in autumn', '<h2>Autumn Food Recommendations</h2><p>Autumn is the season of harvest, with many delicious foods to try:</p><ul><li><strong>Crab:</strong> Tender and nutritious.</li><li><strong>Chestnuts:</strong> Sweet and delicious, perfect for roasting or boiling.</li><li><strong>Pumpkin:</strong> Soft and versatile, great for various dishes.</li></ul><p>These foods not only satisfy your taste buds but also provide nutrition, letting you enjoy the joy of autumn harvest!</p>', 'Food, autumn, recommendations', 'Autumn food recommendations to enjoy the harvest'),
     (10, 'zh', '冬季保暖小妙招', '如何在寒冷中保持温暖', '<h2>冬季保暖小妙招</h2><p>冬季寒冷,保暖很重要。以下是一些保暖小妙招:</p><ul><li><strong>穿多层衣物:</strong>增加保暖效果。</li><li><strong>戴帽子和围巾:</strong>减少头部热量散失。</li><li><strong>保持室内温暖:</strong>使用暖气或电热毯。</li></ul><p>希望这些小妙招能帮助你在寒冷的冬季保持温暖!</p>', '保暖,冬季,小妙招', '冬季保暖小妙招,让你温暖过冬'),
     (10, 'zh', '冬季保暖小妙招', '如何在寒冷中保持温暖', '<h2>冬季保暖小妙招</h2><p>冬季寒冷,保暖很重要。以下是一些保暖小妙招:</p><ul><li><strong>穿多层衣物:</strong>增加保暖效果。</li><li><strong>戴帽子和围巾:</strong>减少头部热量散失。</li><li><strong>保持室内温暖:</strong>使用暖气或电热毯。</li></ul><p>希望这些小妙招能帮助你在寒冷的冬季保持温暖!</p>', '保暖,冬季,小妙招', '冬季保暖小妙招,让你温暖过冬'),
+    (10, 'zh-tw', '冬季保暖小妙招', '如何在寒冷中保持溫暖', '<h2>冬季保暖小妙招</h2><p>冬季寒冷,保暖很重要。以下是一些保暖小妙招:</p><ul><li><strong>穿多層衣物:</strong>增加保暖效果。</li><li><strong>戴帽子和圍巾:</strong>減少頭部熱量散失。</li><li><strong>保持室內溫暖:</strong>使用暖氣或電熱毯。</li></ul><p>希望這些小妙招能幫助你在寒冷的冬季保持溫暖!</p>', '保暖,冬季,小妙招', '冬季保暖小妙招,讓你溫暖過冬'),
     (10, 'en', 'Winter Warmth Tips', 'How to stay warm in the cold', '<h2>Winter Warmth Tips</h2><p>Winter is cold, and staying warm is crucial. Here are some tips:</p><ul><li><strong>Wear multiple layers:</strong> Enhance warmth.</li><li><strong>Wear hats and scarves:</strong> Reduce heat loss from the head.</li><li><strong>Keep indoor warmth:</strong> Use heating or electric blankets.</li></ul><p>Hope these tips help you stay warm in the cold winter!</p>', 'Warmth, winter, tips', 'Winter warmth tips to keep you cozy'),
     (10, 'en', 'Winter Warmth Tips', 'How to stay warm in the cold', '<h2>Winter Warmth Tips</h2><p>Winter is cold, and staying warm is crucial. Here are some tips:</p><ul><li><strong>Wear multiple layers:</strong> Enhance warmth.</li><li><strong>Wear hats and scarves:</strong> Reduce heat loss from the head.</li><li><strong>Keep indoor warmth:</strong> Use heating or electric blankets.</li></ul><p>Hope these tips help you stay warm in the cold winter!</p>', 'Warmth, winter, tips', 'Winter warmth tips to keep you cozy'),
     (11, 'zh', '春季户外徒步指南', '如何享受徒步的乐趣', '<h2>春季户外徒步指南</h2><p>春季是徒步的好季节,以下是一些徒步建议:</p><ul><li><strong>选择合适的路线:</strong>根据自己的体力选择合适的徒步路线。</li><li><strong>准备必要的装备:</strong>舒适的徒步鞋、背包、水和食物。</li><li><strong>注意安全:</strong>告知他人你的行程,避免独自前往危险区域。</li></ul><p>希望这些指南能帮助你享受徒步的乐趣!</p>', '徒步,春季,指南', '春季户外徒步指南,享受徒步的乐趣'),
     (11, 'zh', '春季户外徒步指南', '如何享受徒步的乐趣', '<h2>春季户外徒步指南</h2><p>春季是徒步的好季节,以下是一些徒步建议:</p><ul><li><strong>选择合适的路线:</strong>根据自己的体力选择合适的徒步路线。</li><li><strong>准备必要的装备:</strong>舒适的徒步鞋、背包、水和食物。</li><li><strong>注意安全:</strong>告知他人你的行程,避免独自前往危险区域。</li></ul><p>希望这些指南能帮助你享受徒步的乐趣!</p>', '徒步,春季,指南', '春季户外徒步指南,享受徒步的乐趣'),
+    (11, 'zh-tw', '春季戶外徒步指南', '如何享受徒步的樂趣', '<h2>春季戶外徒步指南</h2><p>春季是徒步的好季節,以下是一些徒步建議:</p><ul><li><strong>選擇合適的路線:</strong>根據自己的體力選擇合適的徒步路線。</li><li><strong>準備必要的裝備:</strong>舒適的徒步鞋、背包、水和食物。</li><li><strong>注意安全:</strong>告知他人你的行程,避免獨自前往危險區域。</li></ul><p>希望這些指南能幫助你享受徒步的樂趣!</p>', '徒步,春季,指南', '春季戶外徒步指南,享受徒步的樂趣'),
     (11, 'en', 'Spring Hiking Guide', 'How to enjoy hiking', '<h2>Spring Hiking Guide</h2><p>Spring is a great season for hiking. Here are some tips:</p><ul><li><strong>Choose the right trail:</strong> Select a trail based on your physical condition.</li><li><strong>Prepare necessary gear:</strong> Comfortable hiking shoes, backpack, water, and food.</li><li><strong>Pay attention to safety:</strong> Inform someone of your itinerary and avoid dangerous areas alone.</li></ul><p>Hope these guides help you enjoy hiking!</p>', 'Hiking, spring, guide', 'Spring hiking guide to enjoy the outdoors'),
     (11, 'en', 'Spring Hiking Guide', 'How to enjoy hiking', '<h2>Spring Hiking Guide</h2><p>Spring is a great season for hiking. Here are some tips:</p><ul><li><strong>Choose the right trail:</strong> Select a trail based on your physical condition.</li><li><strong>Prepare necessary gear:</strong> Comfortable hiking shoes, backpack, water, and food.</li><li><strong>Pay attention to safety:</strong> Inform someone of your itinerary and avoid dangerous areas alone.</li></ul><p>Hope these guides help you enjoy hiking!</p>', 'Hiking, spring, guide', 'Spring hiking guide to enjoy the outdoors'),
     (12, 'zh', '家居收纳技巧大全', '如何打造整洁有序的家', '<h2>家居收纳技巧大全</h2><p>一个整洁有序的家能让人感到舒适和放松。以下是一些实用的家居收纳技巧:</p><ul><li><strong>分类整理:</strong>将物品按照类别进行分类,方便查找。</li><li><strong>利用收纳工具:</strong>如收纳盒、挂钩、置物架等。</li><li><strong>定期清理:</strong>定期检查并清理不需要的物品。</li></ul><p>希望这些技巧能帮助你打造一个整洁有序的家!</p>', '家居,收纳,技巧', '家居收纳技巧大全,打造整洁有序的家'),
     (12, 'zh', '家居收纳技巧大全', '如何打造整洁有序的家', '<h2>家居收纳技巧大全</h2><p>一个整洁有序的家能让人感到舒适和放松。以下是一些实用的家居收纳技巧:</p><ul><li><strong>分类整理:</strong>将物品按照类别进行分类,方便查找。</li><li><strong>利用收纳工具:</strong>如收纳盒、挂钩、置物架等。</li><li><strong>定期清理:</strong>定期检查并清理不需要的物品。</li></ul><p>希望这些技巧能帮助你打造一个整洁有序的家!</p>', '家居,收纳,技巧', '家居收纳技巧大全,打造整洁有序的家'),
+    (12, 'zh-tw', '家居收納技巧大全', '如何打造整潔有序的家', '<h2>家居收納技巧大全</h2><p>一個整潔有序的家能讓人感到舒適和放鬆。以下是一些實用的家居收納技巧:</p><ul><li><strong>分類整理:</strong>將物品按照類別進行分類,方便查找。</li><li><strong>利用收納工具:</strong>如收納盒、掛鉤、置物架等。</li><li><strong>定期清理:</strong>定期檢查並清理不需要的物品。</li></ul><p>希望這些技巧能幫助你打造一個整潔有序的家!</p>', '家居,收納,技巧', '家居收納技巧大全,打造整潔有序的家'),
     (12, 'en', 'Home Organization Tips', 'How to create a tidy and organized home', '<h2>Home Organization Tips</h2><p>A tidy and organized home can bring comfort and relaxation. Here are some practical tips for home organization:</p><ul><li><strong>Sort and categorize:</strong> Organize items by category for easy access.</li><li><strong>Use storage tools:</strong> Such as storage boxes, hooks, and shelves.</li><li><strong>Regular decluttering:</strong> Periodically check and remove items you no longer need.</li></ul><p>Hope these tips help you create a tidy and organized home!</p>', 'Home, organization, tips', 'Home organization tips to keep your space tidy')
     (12, 'en', 'Home Organization Tips', 'How to create a tidy and organized home', '<h2>Home Organization Tips</h2><p>A tidy and organized home can bring comfort and relaxation. Here are some practical tips for home organization:</p><ul><li><strong>Sort and categorize:</strong> Organize items by category for easy access.</li><li><strong>Use storage tools:</strong> Such as storage boxes, hooks, and shelves.</li><li><strong>Regular decluttering:</strong> Periodically check and remove items you no longer need.</li></ul><p>Hope these tips help you create a tidy and organized home!</p>', 'Home, organization, tips', 'Home organization tips to keep your space tidy')
 ;
 ;

+ 2 - 1
db/cms_banner_i18n.sql

@@ -17,6 +17,7 @@ CREATE TABLE `cms_banner_i18n` (
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='幻灯片表 (翻译)';
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='幻灯片表 (翻译)';
 
 
 INSERT INTO cms_banner_i18n(banner_id, language, title, link, image, image_thumb) VALUES
 INSERT INTO cms_banner_i18n(banner_id, language, title, link, image, image_thumb) VALUES
-    (1, 'zh', '枯在斯柯达欠妥', '/PageDao/index/index', '/uploads/banners/banners.1680162484582.png', '/uploads/banners/banners.1680162484582.png'),
+    (1, 'zh', '幻灯片-A', '/PageDao/index/index', '/uploads/banners/banners.1680162484582.png', '/uploads/banners/banners.1680162484582.png'),
+    (1, 'zh-tw', '幻燈片-A', '/PageDao/index/index', '/uploads/banners/banners.1680162484582.png', '/uploads/banners/banners.1680162484582.png'),
     (1, 'en', 'aaaadfqwea', '/PageDao/index/index', '/uploads/banners/banners.1680162484582.png', '/uploads/banners/banners.1680162484582.png')
     (1, 'en', 'aaaadfqwea', '/PageDao/index/index', '/uploads/banners/banners.1680162484582.png', '/uploads/banners/banners.1680162484582.png')
 ;
 ;

+ 29 - 25
db/cms_navigation_i18n.sql

@@ -1,27 +1,31 @@
-/**
-Source Server Version: 8.0.31
-Source Database: backendsys
-Date: 2023/05/23 17:09:22
-*/
+    /**
+    Source Server Version: 8.0.31
+    Source Database: backendsys
+    Date: 2023/05/23 17:09:22
+    */
 
 
-DROP TABLE IF EXISTS `cms_navigation_i18n`;
-CREATE TABLE `cms_navigation_i18n` (
-    PRIMARY KEY (`id`),
-    `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
-    `navigation_id` BIGINT NOT NULL COMMENT '导航ID',
-    `language` VARCHAR(10) NOT NULL COMMENT '语种',
-    `navigation_name` VARCHAR(255) NOT NULL COMMENT '菜单名称',
-    `link` VARCHAR(1000) COMMENT '链接',
-    `link_start_with` text COMMENT '链接匹配路径'
-) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='导航翻译表';
+    DROP TABLE IF EXISTS `cms_navigation_i18n`;
+    CREATE TABLE `cms_navigation_i18n` (
+        PRIMARY KEY (`id`),
+        `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
+        `navigation_id` BIGINT NOT NULL COMMENT '导航ID',
+        `language` VARCHAR(10) NOT NULL COMMENT '语种',
+        `navigation_name` VARCHAR(255) NOT NULL COMMENT '菜单名称',
+        `link` VARCHAR(1000) COMMENT '链接',
+        `link_start_with` text COMMENT '链接匹配路径'
+    ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='导航翻译表';
 
 
-INSERT INTO cms_navigation_i18n(navigation_id, language, navigation_name, link, link_start_with) VALUES
-    (1, 'zh', '首页', '/', null),
-    (1, 'en', 'Home', '/', null),
-    (2, 'zh', '关于我们', '/page/about', null),
-    (2, 'en', 'About', '/page/about', null),
-    (3, 'zh', '资讯中心', '/article/list', '/article'),
-    (3, 'en', 'Article', '/article/list', '/article'),
-    (3, 'zh', '联系我们', '/page/contact', null),
-    (3, 'en', 'Concat us', '/page/contact', null)
-;
+    INSERT INTO cms_navigation_i18n(navigation_id, language, navigation_name, link, link_start_with) VALUES
+        (1, 'zh', '首页', '/', null),
+        (1, 'zh-tw', '首頁', '/', null),
+        (1, 'en', 'Home', '/', null),
+        (2, 'zh', '关于我们', '/page/about', null),
+        (2, 'zh-tw', '關於我們', '/page/about', null),
+        (2, 'en', 'About', '/page/about', null),
+        (3, 'zh', '资讯中心', '/article/list', '/article'),
+        (3, 'zh-tw', '資訊中心', '/article/list', '/article'),
+        (3, 'en', 'Article', '/article/list', '/article'),
+        (3, 'zh', '联系我们', '/page/contact', null),
+        (3, 'zh-tw', '聯絡我們', '/page/contact', null),
+        (3, 'en', 'Concat us', '/page/contact', null)
+    ;

+ 2 - 0
db/cms_page_i18n.sql

@@ -14,7 +14,9 @@ CREATE TABLE `cms_page_i18n` (
 
 
 INSERT INTO cms_page_i18n(page_sign, language, title, description, content) VALUES
 INSERT INTO cms_page_i18n(page_sign, language, title, description, content) VALUES
     ('about', 'zh', '关于我们', '一家致力于为用户提供智能生活解决方案的科技公司', '是一家致力于为用户提供智能生活解决方案的科技公司。我们的使命是利用最先进的人工智能技术,使每个人都能享受更智能、更便捷的生活体验。无论是通过我们的智能助手或者其他创新产品,我们都致力于为大家提供优质的服务和技术。'),
     ('about', 'zh', '关于我们', '一家致力于为用户提供智能生活解决方案的科技公司', '是一家致力于为用户提供智能生活解决方案的科技公司。我们的使命是利用最先进的人工智能技术,使每个人都能享受更智能、更便捷的生活体验。无论是通过我们的智能助手或者其他创新产品,我们都致力于为大家提供优质的服务和技术。'),
+    ('about', 'zh-tw', '關於我們', '一家致力於為用戶提供智慧生活解決方案的科技公司', '是一家致力於為用戶提供智慧生活解決方案的科技公司。我們的使命是運用最先進的人工智慧技術,讓每個人都能享受更智慧、更便捷的生活體驗。無論是透過我們的智慧助手或其他創新產品,我們都致力於為大家提供優質的服務與技術。'),
     ('about', 'en', 'About us', 'A technology company dedicated to providing intelligent lifestyle solutions for users', 'WeTab is a technology company dedicated to providing intelligent lifestyle solutions for users. Our mission is to leverage cutting-edge artificial intelligence technology to enable everyone to enjoy a smarter and more convenient life experience. Whether through our smart assistant or other innovative products, we are committed to providing high-quality service and technology.'),
     ('about', 'en', 'About us', 'A technology company dedicated to providing intelligent lifestyle solutions for users', 'WeTab is a technology company dedicated to providing intelligent lifestyle solutions for users. Our mission is to leverage cutting-edge artificial intelligence technology to enable everyone to enjoy a smarter and more convenient life experience. Whether through our smart assistant or other innovative products, we are committed to providing high-quality service and technology.'),
     ('contact', 'zh', '联系我们', '', '<p>联系电话:+1234567890</p><p>邮箱地址:info@WeTab.com</p><p>企业地址:XXXX街道,XX城市,XX国家</p>'),
     ('contact', 'zh', '联系我们', '', '<p>联系电话:+1234567890</p><p>邮箱地址:info@WeTab.com</p><p>企业地址:XXXX街道,XX城市,XX国家</p>'),
+    ('contact', 'zh-tw', '聯絡我們', '', '<p>聯繫電話:+1234567890</p><p>郵箱地址:info@WeTab.com</p><p>企業地址:XXXX街道,XX城市,XX國家</p>'),
     ('contact', 'en', 'Contact us', '', '<p>Phone:+1234567890</p><p>Email:info@WeTab.com</p><p>Address: XXXX Street, XX City, XX Country</p>')
     ('contact', 'en', 'Contact us', '', '<p>Phone:+1234567890</p><p>Email:info@WeTab.com</p><p>Address: XXXX Street, XX City, XX Country</p>')
 ;
 ;

+ 1 - 0
db/cms_site_info.sql

@@ -20,6 +20,7 @@ CREATE TABLE `cms_site_info` (
 
 
 INSERT INTO cms_site_info(language, name, meta_keyword, meta_description, copyright, icp) VALUES
 INSERT INTO cms_site_info(language, name, meta_keyword, meta_description, copyright, icp) VALUES
     ('zh', '示例网站', '示例网站, 网页设计, 网络技术, 用户体验', '这是一个示例网站,专注于网页设计和网络技术,致力于提供优质的用户体验。欢迎来到示例网站,探索我们的服务和创意。', 'Copyright &copy; 2024 示例网站. 保留所有权利.', '备案号: 京ICP备12345678号'),
     ('zh', '示例网站', '示例网站, 网页设计, 网络技术, 用户体验', '这是一个示例网站,专注于网页设计和网络技术,致力于提供优质的用户体验。欢迎来到示例网站,探索我们的服务和创意。', 'Copyright &copy; 2024 示例网站. 保留所有权利.', '备案号: 京ICP备12345678号'),
+    ('zh-tw', '示例網站', '示例網站, 網頁設計, 網路技術, 使用體驗', '這是一個示例網站,專注於網頁設計和網路技術,致力於提供優質的使用體驗。歡迎來到示例網站,探索我們的服務和創意。', 'Copyright &copy; 2024 示例網站. 保留所有權利.', '備案號: 京ICP備12345678號'),
     ('en', 'Example Website', 'Example Website, Web Design, Web Technology, User Experience', 'This is an example website, focusing on web design and web technology. We are committed to providing a high-quality user experience. Welcome to Example Website, explore our services and creativity.', 'Copyright © 2024 Example Website. All rights reserved.', 'Record number: Beijing ICP No. 12345678')
     ('en', 'Example Website', 'Example Website, Web Design, Web Technology, User Experience', 'This is an example website, focusing on web design and web technology. We are committed to providing a high-quality user experience. Welcome to Example Website, explore our services and creativity.', 'Copyright © 2024 Example Website. All rights reserved.', 'Record number: Beijing ICP No. 12345678')
 ;
 ;
 
 

+ 2 - 1
db/sys_language.sql

@@ -15,6 +15,7 @@ CREATE TABLE `sys_language` (
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='系统语言表';
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='系统语言表';
 
 
 INSERT INTO sys_language(language, name, is_default, status) VALUES
 INSERT INTO sys_language(language, name, is_default, status) VALUES
-    ('zh', '中文', 1, 1),
+    ('zh', '简体中文', 1, 1),
+    ('zh-tw', '繁體中文', -1, 1),
     ('en', 'English', -1, 1)
     ('en', 'English', -1, 1)
 ;
 ;

+ 1 - 1
src/main/java/com/backendsys/modules/cms/template/ArticleViewController.java → src/main/java/com/backendsys/modules/cms/views/ArticleViewController.java

@@ -1,4 +1,4 @@
-package com.backendsys.modules.cms.template;
+package com.backendsys.modules.cms.views;
 
 
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.convert.Convert;
 import com.backendsys.modules.cms.article.entity.Article;
 import com.backendsys.modules.cms.article.entity.Article;

+ 1 - 1
src/main/java/com/backendsys/modules/cms/template/IndexViewController.java → src/main/java/com/backendsys/modules/cms/views/IndexViewController.java

@@ -1,4 +1,4 @@
-package com.backendsys.modules.cms.template;
+package com.backendsys.modules.cms.views;
 
 
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.convert.Convert;
 import com.backendsys.modules.common.aspect.Pages;
 import com.backendsys.modules.common.aspect.Pages;

+ 1 - 5
src/main/java/com/backendsys/modules/cms/template/PageViewController.java → src/main/java/com/backendsys/modules/cms/views/PageViewController.java

@@ -1,20 +1,16 @@
-package com.backendsys.modules.cms.template;
+package com.backendsys.modules.cms.views;
 
 
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.convert.Convert;
-import com.backendsys.modules.cms.article.entity.Article;
 import com.backendsys.modules.cms.page.entity.Page;
 import com.backendsys.modules.cms.page.entity.Page;
 import com.backendsys.modules.cms.page.service.PageService;
 import com.backendsys.modules.cms.page.service.PageService;
 import com.backendsys.modules.common.aspect.Pages;
 import com.backendsys.modules.common.aspect.Pages;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
 import org.springframework.stereotype.Controller;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PathVariable;
 
 
-import java.util.Locale;
-
 @Controller
 @Controller
 public class PageViewController {
 public class PageViewController {
 
 

+ 23 - 14
src/main/java/com/backendsys/modules/common/aspect/PagesAspect.java

@@ -6,8 +6,10 @@ import com.backendsys.modules.cms.navigation.entity.Navigation;
 import com.backendsys.modules.cms.navigation.service.NavigationService;
 import com.backendsys.modules.cms.navigation.service.NavigationService;
 import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
 import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
 import com.backendsys.modules.common.utils.CookieUtil;
 import com.backendsys.modules.common.utils.CookieUtil;
+import com.backendsys.modules.system.service.SysLanguageService;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.servlet.http.HttpServletResponse;
+import org.aspectj.lang.annotation.AfterThrowing;
 import org.aspectj.lang.reflect.MethodSignature;
 import org.aspectj.lang.reflect.MethodSignature;
 import org.springframework.ui.Model;
 import org.springframework.ui.Model;
 import com.backendsys.modules.cms.siteinfo.entity.SiteInfo;
 import com.backendsys.modules.cms.siteinfo.entity.SiteInfo;
@@ -21,6 +23,7 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.method.HandlerMethod;
 import org.springframework.web.method.HandlerMethod;
 
 
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Method;
 import java.util.List;
 import java.util.List;
 
 
@@ -33,17 +36,19 @@ public class PagesAspect {
 
 
 	@Autowired
 	@Autowired
 	private HttpRequestUtil httpRequestUtil;
 	private HttpRequestUtil httpRequestUtil;
+
+	@Autowired
+	private SysLanguageService sysLanguageService;
 	@Autowired
 	@Autowired
 	private SiteInfoService siteInfoService;
 	private SiteInfoService siteInfoService;
 	@Autowired
 	@Autowired
 	private NavigationService navigationService;
 	private NavigationService navigationService;
 
 
-
-
 	@Before("@annotation(org.springframework.web.bind.annotation.GetMapping) && @annotation(pages)")
 	@Before("@annotation(org.springframework.web.bind.annotation.GetMapping) && @annotation(pages)")
-	public void beforeGet(JoinPoint joinPoint, Pages pages) {
+	public void beforeGet(JoinPoint joinPoint, Pages pages) throws IOException {
 
 
 		HttpServletRequest request = httpRequestUtil.getRequest();
 		HttpServletRequest request = httpRequestUtil.getRequest();
+		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
 
 
 		// 从 JoinPoint 获取控制器方法的参数
 		// 从 JoinPoint 获取控制器方法的参数
 		Object[] args = joinPoint.getArgs();
 		Object[] args = joinPoint.getArgs();
@@ -52,28 +57,32 @@ public class PagesAspect {
 				Model model = (Model) arg;
 				Model model = (Model) arg;
 
 
 				// [Cookie] 获取/设置默认语言 (默认是:中文)
 				// [Cookie] 获取/设置默认语言 (默认是:中文)
-				String lang = CookieUtil.getCookie("lang", request);
-				String default_lang = "zh";
-				if (StrUtil.isEmpty(lang)) {
-					lang = default_lang;
-					CookieUtil.setCookie("lang", lang);
-				}
-				request.setAttribute("lang", lang);
-
+				String lang = CookieUtil.getCurrentLang(request);
 				model.addAttribute("lang", lang);
 				model.addAttribute("lang", lang);
 
 
+				// [Get] 获取系统语言列表
+				model.addAttribute("sysLanguage", sysLanguageService.selectLanguageList());
+
 				// [Get] 获取站点信息
 				// [Get] 获取站点信息
+				SiteInfo siteInfo = siteInfoService.selectSiteInfo(lang);
+				if (siteInfo == null) {
+					request.setAttribute("errorMessage", "站点信息不存在 " + "(" + lang + ")");
+					response.sendRedirect(request.getContextPath() + "/error");
+				}
 				model.addAttribute("siteInfo", siteInfoService.selectSiteInfo(lang));
 				model.addAttribute("siteInfo", siteInfoService.selectSiteInfo(lang));
+
 				// [Get] 获取导航
 				// [Get] 获取导航
 				model.addAttribute("navigation", navigationService.selectNavigationTemplate(lang));
 				model.addAttribute("navigation", navigationService.selectNavigationTemplate(lang));
+
 				// 其他信息
 				// 其他信息
-				model.addAttribute("timestamp", DateUtil.current());			// 当前时间戳
-				model.addAttribute("request_uri", request.getRequestURI());				// 当前访问路径
-				model.addAttribute("request_query_string", request.getQueryString());	// 当前访问路径参数
+				model.addAttribute("timestamp", DateUtil.current());            			// 当前时间戳
+				model.addAttribute("request_uri", request.getRequestURI());                 // 当前访问路径
+				model.addAttribute("request_query_string", request.getQueryString());    	// 当前访问路径参数
 
 
 				break;
 				break;
 			}
 			}
 		}
 		}
+
 	}
 	}
 
 
 }
 }

+ 24 - 7
src/main/java/com/backendsys/modules/common/config/security/filter/JwtAuthenticationFilter.java

@@ -2,6 +2,8 @@ package com.backendsys.modules.common.config.security.filter;
 
 
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ArrayUtil;
 import com.backendsys.modules.common.config.security.annotations.AnonymousProperties;
 import com.backendsys.modules.common.config.security.annotations.AnonymousProperties;
+import com.backendsys.modules.common.utils.CookieUtil;
+import com.backendsys.utils.response.ResultEnumService;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.backendsys.utils.response.Result;
 import com.backendsys.utils.response.Result;
 import com.backendsys.utils.response.ResultEnum;
 import com.backendsys.utils.response.ResultEnum;
@@ -22,6 +24,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.filter.OncePerRequestFilter;
 import org.springframework.web.filter.OncePerRequestFilter;
 
 
 import java.io.IOException;
 import java.io.IOException;
@@ -53,6 +57,9 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
      */
      */
     private final UserDetailsService userDetailsService; // 从ApplicationConfig中创建的Bean对象获取
     private final UserDetailsService userDetailsService; // 从ApplicationConfig中创建的Bean对象获取
 
 
+    @Autowired
+    private ResultEnumService resultEnumService;
+
     @Value("#{'${whitelist.static}'.split(',')}")
     @Value("#{'${whitelist.static}'.split(',')}")
     private final String[] STATIC_WHITELIST;
     private final String[] STATIC_WHITELIST;
     @Value("#{'${whitelist.jwt}'.split(',')}")
     @Value("#{'${whitelist.jwt}'.split(',')}")
@@ -109,7 +116,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
         final String authHeader = request.getHeader("Authorization");
         final String authHeader = request.getHeader("Authorization");
         if(authHeader == null || !authHeader.startsWith("Bearer ")) {
         if(authHeader == null || !authHeader.startsWith("Bearer ")) {
             // [TOKEN_EMPTY_ERROR: 请先登录获取有效的Token]
             // [TOKEN_EMPTY_ERROR: 请先登录获取有效的Token]
-            handleError(response, ResultEnum.TOKEN_EMPTY_ERROR);
+            handleError(request, response, ResultEnum.TOKEN_EMPTY_ERROR);
             return;
             return;
         }
         }
 
 
@@ -139,7 +146,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
                 Boolean isTokenValid = (stringRedisTemplate.opsForValue().get(redisKey) != null);
                 Boolean isTokenValid = (stringRedisTemplate.opsForValue().get(redisKey) != null);
                 if (!isTokenValid) {
                 if (!isTokenValid) {
                     // [TOKEN_INVALID: Token已失效,请重新登录]
                     // [TOKEN_INVALID: Token已失效,请重新登录]
-                    handleError(response, ResultEnum.TOKEN_INVALID);
+                    handleError(request, response, ResultEnum.TOKEN_INVALID);
                     return ;
                     return ;
                 }
                 }
 
 
@@ -163,19 +170,29 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
 
 
         } catch (MalformedJwtException e) {
         } catch (MalformedJwtException e) {
             // [TOKEN_FORMAT_EXCEPTION: Token格式异常]
             // [TOKEN_FORMAT_EXCEPTION: Token格式异常]
-            handleError(response, ResultEnum.TOKEN_FORMAT_EXCEPTION);
+            handleError(request, response, ResultEnum.TOKEN_FORMAT_EXCEPTION);
         } catch (ExpiredJwtException e) {
         } catch (ExpiredJwtException e) {
             // [TOKEN_EXPIRED: Token过期]
             // [TOKEN_EXPIRED: Token过期]
-            handleError(response, ResultEnum.TOKEN_EXPIRED);
+            handleError(request, response, ResultEnum.TOKEN_EXPIRED);
         } catch (SignatureException e) {
         } catch (SignatureException e) {
             // [TOKEN_FORMAT_INCORRECT: Token格式不正确]
             // [TOKEN_FORMAT_INCORRECT: Token格式不正确]
-            handleError(response, ResultEnum.TOKEN_FORMAT_INCORRECT);
+            handleError(request, response, ResultEnum.TOKEN_FORMAT_INCORRECT);
         }
         }
 
 
     }
     }
 
 
-    private void handleError(HttpServletResponse response, ResultEnum error) throws IOException {
-        Result result = Result.error(error.getCode(), error.getMessage());
+    private void handleError(HttpServletRequest request, HttpServletResponse response, ResultEnum resultEnum) throws IOException {
+
+//        String lang = CookieUtil.getCookie("lang", request);
+//        System.out.println("(handleError) lang = " + lang);
+//
+//        String message = resultEnumService.getMessage(resultEnum, lang);
+//        System.out.println("message = " + message);
+//
+//        Result result = Result.error(resultEnum.getCode(), message);
+
+        Result result = Result.error(resultEnum.getCode(), resultEnum.getMessage());
+
         response.setContentType("application/json;charset=utf-8");
         response.setContentType("application/json;charset=utf-8");
         response.getWriter().write(new ObjectMapper().writeValueAsString(result));
         response.getWriter().write(new ObjectMapper().writeValueAsString(result));
     }
     }

+ 15 - 0
src/main/java/com/backendsys/modules/common/utils/CookieUtil.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.common.utils;
 package com.backendsys.modules.common.utils;
 
 
+import cn.hutool.core.util.StrUtil;
 import jakarta.servlet.http.Cookie;
 import jakarta.servlet.http.Cookie;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.servlet.http.HttpServletResponse;
@@ -32,6 +33,20 @@ public class CookieUtil {
         return value;
         return value;
     }
     }
 
 
+    /**
+     * [Cookie] 获取/设置默认语言 (默认是:中文)
+     */
+    public static String getCurrentLang(HttpServletRequest request) {
+        String lang = CookieUtil.getCookie("lang", request);
+        String default_lang = "zh";
+        if (StrUtil.isEmpty(lang)) {
+            lang = default_lang;
+            CookieUtil.setCookie("lang", lang);
+        }
+        request.setAttribute("lang", lang);
+        return lang;
+    }
+
     /**
     /**
      * 设置 Cookie 的值
      * 设置 Cookie 的值
      * @param name Cookie 名称
      * @param name Cookie 名称

+ 11 - 1
src/main/java/com/backendsys/utils/response/ResultEnum.java

@@ -26,7 +26,8 @@ public enum ResultEnum {
     HTTP_BODY_EMPTY(420, "请求体参数不能为空"),
     HTTP_BODY_EMPTY(420, "请求体参数不能为空"),
     HTTP_METHOD_ERROR(421, "请求方法不支持"),
     HTTP_METHOD_ERROR(421, "请求方法不支持"),
 
 
-    TOKEN_EXPIRED(440, "Token已过期,请重新登录"),
+    TOKEN_EXPIRED(440, "Token已过期,请重新登录", "result.token.invalid"),
+
     TOKEN_INVALID(441, "Token已失效,请重新登录"),
     TOKEN_INVALID(441, "Token已失效,请重新登录"),
     TOKEN_FORMAT_EXCEPTION(442, "Token格式异常"),
     TOKEN_FORMAT_EXCEPTION(442, "Token格式异常"),
     TOKEN_FORMAT_INCORRECT(443, "Token格式不正确"),
     TOKEN_FORMAT_INCORRECT(443, "Token格式不正确"),
@@ -46,6 +47,7 @@ public enum ResultEnum {
 
 
     private int code;
     private int code;
     private String message;
     private String message;
+    private String message_key;
 
 
 
 
     public int getCode() {
     public int getCode() {
@@ -54,9 +56,17 @@ public enum ResultEnum {
     public String getMessage() {
     public String getMessage() {
         return this.message;
         return this.message;
     }
     }
+    public String getMessageKey() {
+        return this.message_key;
+    }
 
 
     ResultEnum(int code, String message) {
     ResultEnum(int code, String message) {
         this.code = code;
         this.code = code;
         this.message = message;
         this.message = message;
     }
     }
+    ResultEnum(int code, String message, String message_key) {
+        this.code = code;
+        this.message = message;
+        this.message_key = message_key;
+    }
 }
 }

+ 23 - 0
src/main/java/com/backendsys/utils/response/ResultEnumService.java

@@ -0,0 +1,23 @@
+package com.backendsys.utils.response;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.stereotype.Service;
+
+import java.util.Locale;
+
+/**
+ * 定义 ResultEnumService 获取国际化消息
+ */
+@Service
+public class ResultEnumService {
+
+    @Autowired
+    private MessageSource messageSource;
+
+    public String getMessage(ResultEnum resultEnum, String lang) {
+        return messageSource.getMessage(resultEnum.getMessageKey(), null, new Locale(lang));
+    }
+
+}

+ 3 - 1
src/main/resources/i18n/locale_en.properties

@@ -1,3 +1,5 @@
+result.token.invalid = Token is invalid, please log in again
+
 all = All
 all = All
 more = More
 more = More
 settop = Top
 settop = Top
@@ -26,4 +28,4 @@ footer.menu.wechat = Wechat
 footer.menu.wechatinfo.text1 = Long press the QR code to add WeChat for contact.
 footer.menu.wechatinfo.text1 = Long press the QR code to add WeChat for contact.
 footer.menu.wechatinfo.text2 = Wechat
 footer.menu.wechatinfo.text2 = Wechat
 
 
-search.input.placeholder = Enter the keyword to explore the ideal watch in your heart...
+search.input.placeholder = Enter the keyword to search...

+ 31 - 0
src/main/resources/i18n/locale_zh-tw.properties

@@ -0,0 +1,31 @@
+result.token.invalid = Token已失效,請重新登入
+
+all = 全部
+more = 更多
+settop = 置頂
+viewdetail = 查看詳情
+category = 分類
+back = 返回
+
+top.welcome = 歡迎諮詢,微信號:
+
+index.section1.title = 最新評測
+index.section2.title = 熱門評測
+
+index.title = 首頁
+article.title = 資訊中心
+articleDetail.title = 資訊詳情
+page.title = 內容中心
+
+sub.sider.title.nav = 導航
+
+footer.menu.home = 首頁
+footer.menu.product = 產品
+footer.menu.video = 視頻
+footer.menu.ce = 測評
+footer.menu.wechat = 微信
+
+footer.menu.wechatinfo.text1 = 長按二維碼添加微信諮詢
+footer.menu.wechatinfo.text2 = 微信號
+
+search.input.placeholder = 輸入關鍵字進行評測...

+ 3 - 1
src/main/resources/i18n/locale_zh.properties

@@ -1,3 +1,5 @@
+result.token.invalid = Token已失效,请重新登录
+
 all = 全部
 all = 全部
 more = 更多
 more = 更多
 settop = 置顶
 settop = 置顶
@@ -26,4 +28,4 @@ footer.menu.wechat = 微信
 footer.menu.wechatinfo.text1 = 长按二维码添加微信咨询
 footer.menu.wechatinfo.text1 = 长按二维码添加微信咨询
 footer.menu.wechatinfo.text2 = 微信号
 footer.menu.wechatinfo.text2 = 微信号
 
 
-search.input.placeholder = 输入关键字,探索您心中的理想手表..
+search.input.placeholder = 输入关键字进行搜索..

+ 27 - 7
src/main/resources/templates/components/language.html

@@ -1,16 +1,36 @@
 <div th:fragment="language">
 <div th:fragment="language">
 
 
   <ul class="flex items-center">
   <ul class="flex items-center">
-    <li class="ml-4">
-      <a href="javascript:;" onclick="setLangAndRefresh('zh');"
-         th:classappend="${lang} == 'zh' ? 'font-bold' : ''">中文</a>
-    </li>
-    <li class="ml-4">
-      <a href="javascript:;" onclick="setLangAndRefresh('en');"
-         th:classappend="${lang} == 'en' ? 'font-bold' : ''">English</a>
+
+    <li th:each="sysLang, iterStat : ${sysLanguage}" class="ml-4">
+      <a href="javascript:;"
+         th:data-lang="${sysLang.language}"
+         th:classappend="(${lang} == ${sysLang.language} ? 'font-bold' : '')"
+         th:text="${sysLang.name}">
+      </a>
     </li>
     </li>
+
+<!--    <li class="ml-4">-->
+<!--      <a href="javascript:;" onclick="setLangAndRefresh('zh');"-->
+<!--         th:classappend="${lang} == 'zh' ? 'font-bold' : ''">中文</a>-->
+<!--    </li>-->
+<!--    <li class="ml-4">-->
+<!--      <a href="javascript:;" onclick="setLangAndRefresh('en');"-->
+<!--         th:classappend="${lang} == 'en' ? 'font-bold' : ''">English</a>-->
+<!--    </li>-->
   </ul>
   </ul>
   <script>
   <script>
+
+      document.addEventListener("DOMContentLoaded", function () {
+          const langLinks = document.querySelectorAll("a[data-lang]");
+          langLinks.forEach(link => {
+              // 监听导航栏语言点击事件
+              link.addEventListener("click", function () {
+                  setLangAndRefresh(this.dataset.lang)
+              });
+          });
+      });
+      // 设置语言Cookie,刷新页面
       function setLangAndRefresh(lang) {
       function setLangAndRefresh(lang) {
           document.cookie = "lang=" + lang + ";max-age=2592000;path=/"
           document.cookie = "lang=" + lang + ";max-age=2592000;path=/"
           location.reload()
           location.reload()

File diff suppressed because it is too large
+ 1 - 0
src/main/resources/templates/error.html


Some files were not shown because too many files changed in this diff