Files
go_blog/i18n/i18n.go
T
2026-06-21 19:29:42 +08:00

263 lines
8.6 KiB
Go

package i18n
import (
"strings"
)
// Lang represents a supported language code.
type Lang string
const (
EN Lang = "en"
ZH Lang = "zh"
)
// translations holds all UI strings keyed by language then translation key.
var translations = map[Lang]map[string]string{
EN: {
// Nav
"site_title": "Go Blog",
"home": "Home",
"login": "Login",
"dashboard": "Dashboard",
"logout": "Logout",
// Home page
"home_welcome": "Welcome to Go Blog",
"home_subtitle": "A simple, fast blog engine built with Go, Gin, and Tailwind CSS.",
"home_sign_in": "Sign In",
"home_to_dash": "Dashboard",
"home_latest": "Latest Posts",
"home_post1_tit": "Getting Started",
"home_post1_dsc": "Welcome to your new blog! This is a placeholder post. Start writing to see your content here.",
"home_post2_tit": "Hello World",
"home_post2_dsc": "Blog posts will appear here once you start publishing from the admin dashboard.",
"home_post3_tit": "Built with Go",
"home_post3_dsc": "This blog engine uses Go, Gin web framework, GORM, and Tailwind CSS for a modern experience.",
"home_no_posts": "No published posts yet.",
// Login page
"login_title": "Sign In",
"login_username": "Username",
"login_password": "Password",
"login_ph_user": "Enter your username",
"login_ph_pass": "Enter your password",
"login_submit": "Sign In",
"login_error": "Invalid username or password.",
"login_required": "Please fill in all fields.",
// Dashboard
"dash_title": "Dashboard",
"dash_welcome": "Welcome back,",
"dash_posts": "Posts",
"dash_pages": "Pages",
"dash_users": "Users",
"dash_mgmt_title": "Blog Management",
"dash_mgmt_desc": "Post management, categories, and settings will appear here in future updates.",
"dash_page_title": "Dashboard",
// Footer
"footer_text": "© 2026 Go Blog. Powered by Go & Gin.",
// Page titles
"page_home": "Home",
"page_login": "Login",
// Language switcher
"lang_switch": "中文",
// Profile dropdown & page
"profile": "Profile",
"admin_panel": "Admin Panel",
"profile_title": "Edit Profile",
"profile_avatar": "Avatar",
"profile_change_avatar": "Change Avatar",
"profile_display_name": "Display Name",
"profile_gender": "Gender",
"profile_birthday": "Birthday",
"profile_email": "Email",
"profile_change_password": "Change Password",
"profile_current_password": "Current Password",
"profile_new_password": "New Password",
"profile_save": "Save Changes",
"profile_saved": "Profile updated.",
"profile_wrong_password": "Current password is incorrect.",
"gender_male": "Male",
"gender_female": "Female",
"gender_other": "Other",
// Avatar cropping
"crop_avatar_title": "Crop Avatar",
"crop_cancel": "Cancel",
"crop_confirm": "Confirm",
"crop_uploading": "Uploading...",
"crop_success": "Avatar updated.",
"crop_error": "Failed to upload avatar. Please try again.",
// Article creation
"article_create_title": "Create Article",
"article_title": "Title",
"article_slug": "Slug",
"article_slug_hint": "Auto-generated from title if empty",
"article_summary": "Summary",
"article_content": "Content",
"article_cover": "Cover Image URL",
"article_status": "Status",
"article_draft": "Draft",
"article_published": "Published",
"article_is_top": "Pin to top",
"article_save_draft": "Save Draft",
"article_publish": "Publish",
"article_created": "Article created successfully.",
"article_error": "Failed to create article.",
"article_new": "New Article",
"article_title_required": "Title is required.",
"article_content_required": "Content is required.",
},
ZH: {
// 导航
"site_title": "Go 博客",
"home": "首页",
"login": "登录",
"dashboard": "后台",
"logout": "退出",
// 首页
"home_welcome": "欢迎来到 Go Blog",
"home_subtitle": "一个使用 Go、Gin 和 Tailwind CSS 构建的简洁快速的博客引擎。",
"home_sign_in": "登录",
"home_to_dash": "后台管理",
"home_latest": "最新文章",
"home_post1_tit": "入门指南",
"home_post1_dsc": "欢迎来到你的新博客!这是一篇占位文章。开始写作后,你的内容将显示在这里。",
"home_post2_tit": "你好,世界",
"home_post2_dsc": "当你从后台管理面板发布文章后,博客文章将显示在这里。",
"home_post3_tit": "使用 Go 构建",
"home_post3_dsc": "此博客引擎使用 Go、Gin Web 框架、GORM 和 Tailwind CSS 构建,提供现代化的体验。",
"home_no_posts": "暂无已发布的文章。",
// 登录页
"login_title": "登录",
"login_username": "用户名",
"login_password": "密码",
"login_ph_user": "请输入用户名",
"login_ph_pass": "请输入密码",
"login_submit": "登录",
"login_error": "用户名或密码错误。",
"login_required": "请填写所有字段。",
// 后台
"dash_title": "后台管理",
"dash_welcome": "欢迎回来,",
"dash_posts": "文章",
"dash_pages": "页面",
"dash_users": "用户",
"dash_mgmt_title": "博客管理",
"dash_mgmt_desc": "文章管理、分类和设置将在后续版本中添加。",
"dash_page_title": "后台管理",
// 页脚
"footer_text": "© 2026 Go Blog。由 Go & Gin 驱动。",
"page_home": "首页",
"page_login": "登录",
// 语言切换
"lang_switch": "English",
// 个人中心下拉菜单 & 页面
"profile": "个人信息",
"admin_panel": "后台管理",
"profile_title": "编辑个人信息",
"profile_avatar": "头像",
"profile_change_avatar": "更换头像",
"profile_display_name": "显示名称",
"profile_gender": "性别",
"profile_birthday": "生日",
"profile_email": "邮箱",
"profile_change_password": "修改密码",
"profile_current_password": "当前密码",
"profile_new_password": "新密码",
"profile_save": "保存修改",
"profile_saved": "个人信息已更新。",
"profile_wrong_password": "当前密码错误。",
"gender_male": "男",
"gender_female": "女",
"gender_other": "其他",
// 头像裁剪
"crop_avatar_title": "裁剪头像",
"crop_cancel": "取消",
"crop_confirm": "确认",
"crop_uploading": "上传中...",
"crop_success": "头像已更新。",
"crop_error": "头像上传失败,请重试。",
// 文章创建
"article_create_title": "新建文章",
"article_title": "标题",
"article_slug": "Slug",
"article_slug_hint": "留空则从标题自动生成",
"article_summary": "摘要",
"article_content": "正文",
"article_cover": "封面图 URL",
"article_status": "状态",
"article_draft": "草稿",
"article_published": "已发布",
"article_is_top": "置顶",
"article_save_draft": "保存草稿",
"article_publish": "发布",
"article_created": "文章创建成功。",
"article_error": "创建文章失败。",
"article_new": "新建文章",
"article_title_required": "标题不能为空。",
"article_content_required": "正文不能为空。",
},
}
// T returns a copy of the translation map for the given language.
// Falls back to English if the language is not supported.
func T(l Lang) map[string]string {
t, ok := translations[l]
if !ok {
t = translations[EN]
}
// Return a shallow copy so callers cannot mutate the original map values.
out := make(map[string]string, len(t))
for k, v := range t {
out[k] = v
}
return out
}
// DetectLang parses the Accept-Language header and returns the best matching
// supported language. Returns EN for unsupported languages.
func DetectLang(acceptHeader string) Lang {
if acceptHeader == "" {
return EN
}
// Accept-Language format: "zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7"
// Split by comma, then extract primary language from each entry.
entries := strings.Split(acceptHeader, ",")
for _, entry := range entries {
// Trim spaces and remove quality values.
entry = strings.TrimSpace(entry)
if idx := strings.Index(entry, ";"); idx != -1 {
entry = entry[:idx]
}
// Extract primary language (before any "-" subtag).
primary := strings.ToLower(entry)
if idx := strings.Index(primary, "-"); idx != -1 {
primary = primary[:idx]
}
switch primary {
case "zh":
return ZH
case "en":
return EN
}
}
return EN
}