{/* 模式设置 */}
-
+
= ({
onUpdate,
onDelete,
}) => {
+ const t = useTranslations("workbench.basicPanel");
+
return (
= ({
label: value,
})
}
- placeholder="标签"
+ placeholder={t("customFields.placeholders.label")}
className={cn(
"bg-neutral-50 dark:bg-neutral-900",
"border-neutral-200 dark:border-neutral-700",
@@ -87,7 +90,7 @@ const CustomField: React.FC = ({
value: value,
})
}
- placeholder="值"
+ placeholder={t("customFields.placeholders.value")}
className={cn(
"bg-neutral-50 dark:bg-neutral-900",
"border-neutral-200 dark:border-neutral-700",
@@ -142,6 +145,7 @@ const BasicPanel: React.FC = () => {
visible: field.visible ?? true,
}));
});
+ const t = useTranslations("workbench.basicPanel");
const handleBasicReorder = (newOrder: BasicFieldType[]) => {
setBasicFields(newOrder);
@@ -205,6 +209,7 @@ const BasicPanel: React.FC = () => {
customFields: newOrder,
});
};
+
const renderBasicField = (field: BasicFieldType) => {
const selectedIcon = basic?.icons?.[field.key] || "User";
@@ -258,7 +263,7 @@ const BasicPanel: React.FC = () => {
/>
)}
- {field.label}
+ {t(`basicFields.${field.key}`)}
{
- 基本字段
+ {t("basicField")}
{
- 自定义字段
+ {t("customField")}
{
>
@@ -367,7 +372,7 @@ const BasicPanel: React.FC = () => {
>
- Github 贡献图
+ {t("githubContributions")}
= ({
education,
onSave,
}) => {
+ const t = useTranslations("workbench.educationItem");
const handleChange = (field: keyof Education, value: string) => {
onSave({
...education,
@@ -37,40 +39,40 @@ const EducationEditor: React.FC = ({
handleChange("school", value)}
- placeholder="学校名称"
+ placeholder={t("placeholders.school")}
required
/>
handleChange("location", value)}
- placeholder="城市"
+ placeholder={t("placeholders.location")}
/>
handleChange("major", value)}
- placeholder="专业名称"
+ placeholder={t("placeholders.major")}
required
/>
handleChange("degree", value)}
- placeholder="学历"
+ placeholder={t("placeholders.degree")}
required
/>
handleChange("startDate", value)}
type="date"
@@ -78,7 +80,7 @@ const EducationEditor: React.FC = ({
required
/>
handleChange("endDate", value)}
type="date"
@@ -88,18 +90,18 @@ const EducationEditor: React.FC = ({
handleChange("gpa", value)}
- placeholder="选填"
+ placeholder={t("placeholders.gpa")}
/>
handleChange("description", value)}
type="editor"
- placeholder="描述你的在校表现、获奖经历等..."
+ placeholder={t("placeholders.description")}
/>
diff --git a/apps/fronted/src/components/editor/education/EducationPanel.tsx b/apps/fronted/src/components/editor/education/EducationPanel.tsx
index 68f8f41..3ab721d 100644
--- a/apps/fronted/src/components/editor/education/EducationPanel.tsx
+++ b/apps/fronted/src/components/editor/education/EducationPanel.tsx
@@ -3,20 +3,22 @@ import { cn } from "@/lib/utils";
import { useResumeStore } from "@/store/useResumeStore";
import { Reorder } from "framer-motion";
import { PlusCircle } from "lucide-react";
+import { useTranslations } from "next-intl";
import { Button } from "@/components/ui/button";
import EducationItem from "./EducationItem";
import { Education } from "@/types/resume";
const EducationPanel = () => {
+ const t = useTranslations('workbench.educationPanel');
const { activeResume, updateEducation, updateEducationBatch } =
useResumeStore();
const { education = [] } = activeResume || {};
const handleCreateProject = () => {
const newEducation: Education = {
id: crypto.randomUUID(),
- school: "家里蹲大学",
- major: "",
- degree: "",
+ school: t('defaultProject.school'),
+ major: t('defaultProject.major'),
+ degree: t('defaultProject.degree'),
startDate: "2015-09-01",
endDate: "2019-06-30",
description: "",
@@ -50,10 +52,11 @@ const EducationPanel = () => {
);
};
+
export default EducationPanel;
diff --git a/apps/fronted/src/components/editor/experience/ExperienceItem.tsx b/apps/fronted/src/components/editor/experience/ExperienceItem.tsx
index abcd999..cc84f8a 100644
--- a/apps/fronted/src/components/editor/experience/ExperienceItem.tsx
+++ b/apps/fronted/src/components/editor/experience/ExperienceItem.tsx
@@ -13,6 +13,7 @@ import Field from "../Field";
import { Experience } from "@/types/resume";
import ThemeModal from "@/components/shared/ThemeModal";
import { useResumeStore } from "@/store/useResumeStore";
+import { useTranslations } from "next-intl";
interface ProjectEditorProps {
experience: Experience;
@@ -25,6 +26,8 @@ const ProjectEditor: React.FC = ({
experience,
onSave,
}) => {
+ const t = useTranslations("workbench.experiencePanel");
+
const handleChange = (field: keyof Experience, value: string) => {
onSave({
...experience,
@@ -37,33 +40,33 @@ const ProjectEditor: React.FC = ({
handleChange("company", value)}
- placeholder="项目名称"
+ placeholder={t("placeholders.company")}
required
/>
handleChange("position", value)}
- placeholder="如:前端工程师"
+ placeholder={t("placeholders.position")}
required
/>
handleChange("date", value)}
- placeholder="如:2023.01 - 2023.06"
+ placeholder={t("placeholders.date")}
required
/>
handleChange("details", value)}
type="editor"
- placeholder="简要描述项目的背景和目标..."
+ placeholder={t("placeholders.details")}
/>
diff --git a/apps/fronted/src/components/editor/experience/ExperiencePanel.tsx b/apps/fronted/src/components/editor/experience/ExperiencePanel.tsx
index 2acab73..2511bbb 100644
--- a/apps/fronted/src/components/editor/experience/ExperiencePanel.tsx
+++ b/apps/fronted/src/components/editor/experience/ExperiencePanel.tsx
@@ -3,21 +3,23 @@ import { cn } from "@/lib/utils";
import { Reorder } from "framer-motion";
import { PlusCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
+import { useTranslations } from "next-intl";
import ExperienceItem from "./ExperienceItem";
import { Experience } from "@/types/resume";
import { useResumeStore } from "@/store/useResumeStore";
const ExperiencePanel = () => {
+ const t = useTranslations("workbench.experiencePanel");
const { activeResume, updateExperience, updateExperienceBatch } =
useResumeStore();
const { experience = [] } = activeResume || {};
const handleCreateProject = () => {
const newProject: Experience = {
id: crypto.randomUUID(),
- company: "某科技有限公司",
- position: "高级前端工程师",
- date: "2020-至今",
- details: "负责公司核心产品...",
+ company: t("defaultProject.company"),
+ position: t("defaultProject.position"),
+ date: t("defaultProject.date"),
+ details: t("defaultProject.details"),
visible: true,
};
updateExperience(newProject);
@@ -44,10 +46,11 @@ const ExperiencePanel = () => {
);
};
+
export default ExperiencePanel;
diff --git a/apps/fronted/src/components/editor/project/ProjectItem.tsx b/apps/fronted/src/components/editor/project/ProjectItem.tsx
index 5baab24..9b1a881 100644
--- a/apps/fronted/src/components/editor/project/ProjectItem.tsx
+++ b/apps/fronted/src/components/editor/project/ProjectItem.tsx
@@ -12,6 +12,7 @@ import { ChevronDown, Eye, EyeOff, GripVertical, Trash2 } from "lucide-react";
import { useCallback, useState } from "react";
import Field from "../Field";
import ThemeModal from "@/components/shared/ThemeModal";
+import { useTranslations } from "next-intl";
interface Project {
id: string;
@@ -30,6 +31,7 @@ interface ProjectEditorProps {
}
const ProjectEditor: React.FC = ({ project, onSave }) => {
+ const t = useTranslations("workbench.projectItem");
const handleChange = (field: keyof Project, value: string) => {
onSave({
...project,
@@ -42,33 +44,33 @@ const ProjectEditor: React.FC = ({ project, onSave }) => {
handleChange("name", value)}
- placeholder="项目名称"
+ placeholder={t("placeholders.name")}
required
/>
handleChange("role", value)}
- placeholder="如:前端负责人"
+ placeholder={t("placeholders.role")}
required
/>
handleChange("date", value)}
- placeholder="如:2023.01 - 2023.06"
+ placeholder={t("placeholders.date")}
required
/>
handleChange("description", value)}
type="editor"
- placeholder="简要描述项目的背景和目标..."
+ placeholder={t("placeholders.description")}
/>
diff --git a/apps/fronted/src/components/editor/project/ProjectPanel.tsx b/apps/fronted/src/components/editor/project/ProjectPanel.tsx
index ccebb98..377efb4 100644
--- a/apps/fronted/src/components/editor/project/ProjectPanel.tsx
+++ b/apps/fronted/src/components/editor/project/ProjectPanel.tsx
@@ -2,21 +2,23 @@ import { cn } from "@/lib/utils";
import { useResumeStore } from "@/store/useResumeStore";
import { Reorder } from "framer-motion";
import { PlusCircle } from "lucide-react";
+import { useTranslations } from "next-intl";
import { Button } from "@/components/ui/button";
import ProjectItem from "./ProjectItem";
import { Project } from "@/types/resume";
const ProjectPanel = () => {
+ const t = useTranslations("workbench.projectPanel");
const { activeResume, updateProjects, updateProjectsBatch } =
useResumeStore();
const { projects = [] } = activeResume || {};
const handleCreateProject = () => {
const newProject: Project = {
id: crypto.randomUUID(),
- name: "Project Name",
- role: "Project Role",
- date: "",
- description: "",
+ name: t("defaultProject.name"),
+ role: t("defaultProject.role"),
+ date: t("defaultProject.date"),
+ description: t("defaultProject.description"),
visible: true,
};
updateProjects(newProject);
@@ -43,10 +45,11 @@ const ProjectPanel = () => {
);
};
+
export default ProjectPanel;
diff --git a/apps/fronted/src/components/shared/PdfExport.tsx b/apps/fronted/src/components/shared/PdfExport.tsx
index 7cb9f43..f14d864 100644
--- a/apps/fronted/src/components/shared/PdfExport.tsx
+++ b/apps/fronted/src/components/shared/PdfExport.tsx
@@ -4,6 +4,7 @@ import { Download, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { useResumeStore } from "@/store/useResumeStore";
import { Button } from "@/components/ui/button";
+import { useTranslations } from "next-intl";
const getOptimizedStyles = () => {
const styleCache = new Map();
@@ -70,6 +71,7 @@ const PdfExport = () => {
const [isExporting, setIsExporting] = useState(false);
const { activeResume } = useResumeStore();
const { globalSettings = {}, title } = activeResume || {};
+ const t = useTranslations("pdfExport");
const handleExport = async () => {
const exportStartTime = performance.now();
@@ -118,10 +120,10 @@ const PdfExport = () => {
window.URL.revokeObjectURL(url);
console.log(`Total export took ${performance.now() - exportStartTime}ms`);
- toast.success("PDF 导出成功!");
+ toast.success(t("toast.success"));
} catch (error) {
console.error("Export error:", error);
- toast.error("PDF 导出失败,请重试");
+ toast.error(t("toast.error"));
} finally {
setIsExporting(false);
}
@@ -140,7 +142,7 @@ const PdfExport = () => {
) : (
)}
- {isExporting ? "导出中..." : "导出 PDF"}
+ {isExporting ? t("button.exporting") : t("button.default")}
);
diff --git a/apps/fronted/src/components/shared/UpdateLocale.tsx b/apps/fronted/src/components/shared/UpdateLocale.tsx
index 0ee2661..c9b3a7e 100644
--- a/apps/fronted/src/components/shared/UpdateLocale.tsx
+++ b/apps/fronted/src/components/shared/UpdateLocale.tsx
@@ -3,5 +3,5 @@ import { setUserLocale } from "@/i18n/db";
import { revalidatePath } from "next/cache";
export default async function updateLocale(locale: string) {
setUserLocale(locale);
- revalidatePath("/app");
+ // revalidatePath("/app");
}
diff --git a/apps/fronted/src/i18n/locales/en.json b/apps/fronted/src/i18n/locales/en.json
index 5ade5fa..dca7e70 100644
--- a/apps/fronted/src/i18n/locales/en.json
+++ b/apps/fronted/src/i18n/locales/en.json
@@ -74,5 +74,228 @@
}
}
}
+ },
+ "pdfExport": {
+ "button": {
+ "exporting": "Exporting...",
+ "default": "Export PDF"
+ },
+ "toast": {
+ "success": "PDF exported successfully!",
+ "error": "PDF export failed, please try again"
+ }
+ },
+ "workbench": {
+ "sidePanel": {
+ "layout": {
+ "title": "Layout",
+ "addCustomSection": "Add Custom Section"
+ },
+ "theme": {
+ "title": "Theme Color",
+ "custom": "Custom"
+ },
+ "typography": {
+ "title": "Typography",
+ "font": {
+ "title": "Font",
+ "sans": "Sans-serif",
+ "serif": "Serif",
+ "mono": "Monospace"
+ },
+ "lineHeight": {
+ "title": "Line Height",
+ "normal": "Default",
+ "relaxed": "Relaxed",
+ "loose": "Loose"
+ },
+ "baseFontSize": {
+ "title": "Base Font Size"
+ },
+ "headerSize": {
+ "title": "Section Header Size"
+ },
+ "subheaderSize": {
+ "title": "Section Subheader Size"
+ }
+ },
+ "spacing": {
+ "title": "Spacing",
+ "pagePadding": {
+ "title": "Page Padding"
+ },
+ "sectionSpacing": {
+ "title": "Section Spacing"
+ },
+ "paragraphSpacing": {
+ "title": "Paragraph Spacing"
+ }
+ },
+ "mode": {
+ "title": "Mode",
+ "useIconMode": {
+ "title": "Compact Mode"
+ }
+ }
+ },
+ "basicPanel": {
+ "basicField": "Basic",
+ "customField": "Custom",
+ "customFields": {
+ "placeholders": {
+ "label": "Label",
+ "value": "Value"
+ },
+ "addButton": "Add Custom Field"
+ },
+ "basicFields": {
+ "name": "Name",
+ "title": "Title",
+ "email": "Email",
+ "phone": "Phone",
+ "website": "Website",
+ "location": "Location",
+ "birthDate": "Birth Date",
+ "employementStatus": "Employ"
+ },
+ "fieldVisibility": {
+ "show": "Show",
+ "hide": "Hide"
+ },
+ "githubContributions": "GitHub Contributions"
+ },
+ "experiencePanel": {
+ "title": "Work Experience",
+ "addButton": "Add Work Experience",
+ "defaultProject": {
+ "company": "Tech Company Ltd.",
+ "position": "Senior Frontend Engineer",
+ "date": "2020-Present",
+ "details": "Responsible for core product development..."
+ },
+ "placeholders": {
+ "company": "company name",
+ "position": "job title",
+ "date": "employment period",
+ "details": "job responsibilities and achievements"
+ }
+ },
+ "experienceItem": {
+ "labels": {
+ "company": "Company Name",
+ "position": "Position",
+ "date": "Employment Period",
+ "details": "Job Responsibilities"
+ },
+ "placeholders": {
+ "company": "Enter company name",
+ "position": "e.g., Frontend Engineer",
+ "date": "e.g., 2020-Present",
+ "details": "Describe your responsibilities and achievements in this role"
+ },
+ "buttons": {
+ "edit": "Edit",
+ "save": "Save",
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "visibility": {
+ "show": "Show",
+ "hide": "Hide"
+ }
+ },
+ "projectPanel": {
+ "title": "Project Experience",
+ "addButton": "Add Project",
+ "defaultProject": {
+ "name": "Personal Project",
+ "description": "Project Description",
+ "role": "Responsibilities",
+ "date": "2023.01 - 2023.06"
+ },
+ "placeholders": {
+ "name": "Project Name",
+ "description": "Briefly describe project background and goals",
+ "role": "Your role and responsibilities in the project",
+ "date": "Project time range",
+ "link": "Project link (optional)"
+ }
+ },
+ "projectItem": {
+ "labels": {
+ "name": "Project Name",
+ "role": "Project Role",
+ "date": "Project Period",
+ "description": "Project Description",
+ "technologies": "Tech Stack",
+ "link": "Project Link"
+ },
+ "placeholders": {
+ "name": "Enter project name",
+ "role": "Your role in the project",
+ "date": "Project time range",
+ "description": "Briefly describe project background and goals",
+ "technologies": "Technologies and tools used",
+ "link": "Project link (optional)"
+ },
+ "buttons": {
+ "edit": "Edit",
+ "save": "Save",
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "visibility": {
+ "show": "Show",
+ "hide": "Hide"
+ }
+ },
+ "educationPanel": {
+ "title": "Education",
+ "addButton": "Add Education",
+ "defaultProject": {
+ "school": "School Name",
+ "degree": "Degree",
+ "major": "Major",
+ "date": "2020.09 - 2024.06"
+ },
+ "placeholders": {
+ "school": "Enter school name",
+ "degree": "Select degree",
+ "major": "Enter major",
+ "date": "Enter study period"
+ }
+ },
+ "educationItem": {
+ "labels": {
+ "school": "School Name",
+ "degree": "Degree",
+ "major": "Major",
+ "date": "Study Period",
+ "description": "Description",
+ "gpa": "GPA",
+ "location": "Location",
+ "startDate": "Start Date",
+ "endDate": "End Date"
+ },
+ "placeholders": {
+ "school": "Enter school name",
+ "degree": "Select degree",
+ "major": "Enter major",
+ "date": "Enter study time range",
+ "description": "Enter school description",
+ "gpa": "Enter GPA",
+ "location": "Enter location"
+ },
+ "buttons": {
+ "edit": "Edit",
+ "save": "Save",
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "visibility": {
+ "show": "Show",
+ "hide": "Hide"
+ }
+ }
}
}
diff --git a/apps/fronted/src/i18n/locales/zh.json b/apps/fronted/src/i18n/locales/zh.json
index 444d571..a4990b1 100644
--- a/apps/fronted/src/i18n/locales/zh.json
+++ b/apps/fronted/src/i18n/locales/zh.json
@@ -74,5 +74,228 @@
}
}
}
+ },
+ "pdfExport": {
+ "button": {
+ "exporting": "导出中...",
+ "default": "导出 PDF"
+ },
+ "toast": {
+ "success": "PDF 导出成功!",
+ "error": "PDF 导出失败,请重试"
+ }
+ },
+ "workbench": {
+ "sidePanel": {
+ "layout": {
+ "title": "布局",
+ "addCustomSection": "添加自定义模块"
+ },
+ "theme": {
+ "title": "主题色",
+ "custom": "自定义"
+ },
+ "typography": {
+ "title": "排版",
+ "font": {
+ "title": "字体",
+ "sans": "无衬线体",
+ "serif": "衬线体",
+ "mono": "等宽体"
+ },
+ "lineHeight": {
+ "title": "行高",
+ "normal": "默认",
+ "relaxed": "适中",
+ "loose": "宽松"
+ },
+ "baseFontSize": {
+ "title": "基础字号"
+ },
+ "headerSize": {
+ "title": "模块标题字号"
+ },
+ "subheaderSize": {
+ "title": "模块二级标题字号"
+ }
+ },
+ "spacing": {
+ "title": "间距",
+ "pagePadding": {
+ "title": "页边距"
+ },
+ "sectionSpacing": {
+ "title": "模块间距"
+ },
+ "paragraphSpacing": {
+ "title": "段落间距"
+ }
+ },
+ "mode": {
+ "title": "模式",
+ "useIconMode": {
+ "title": "简洁模式"
+ }
+ }
+ },
+ "basicPanel": {
+ "basicField": "基本信息",
+ "customField": "自定义字段",
+ "customFields": {
+ "placeholders": {
+ "label": "标签",
+ "value": "值"
+ },
+ "addButton": "添加自定义字段"
+ },
+ "basicFields": {
+ "name": "姓名",
+ "title": "职位",
+ "email": "邮箱",
+ "phone": "电话",
+ "website": "个人网站",
+ "location": "地址",
+ "birthDate": "出生日期",
+ "employementStatus": "求职状态"
+ },
+ "fieldVisibility": {
+ "show": "显示",
+ "hide": "隐藏"
+ },
+ "githubContributions": "GitHub 贡献"
+ },
+ "experiencePanel": {
+ "title": "工作经历",
+ "addButton": "添加工作经历",
+ "defaultProject": {
+ "company": "某科技有限公司",
+ "position": "高级前端工程师",
+ "date": "2020-至今",
+ "details": "负责公司核心产品..."
+ },
+ "placeholders": {
+ "company": "请输入公司名称",
+ "position": "请输入职位",
+ "date": "请输入工作时间",
+ "details": "请输入工作职责和成就"
+ }
+ },
+ "experienceItem": {
+ "labels": {
+ "company": "公司名称",
+ "position": "岗位",
+ "date": "工作时间",
+ "details": "工作职责"
+ },
+ "placeholders": {
+ "company": "请输入公司名称",
+ "position": "如:前端工程师",
+ "date": "如:2020-至今",
+ "details": "描述你在这份工作中的职责和成就"
+ },
+ "buttons": {
+ "edit": "编辑",
+ "save": "保存",
+ "cancel": "取消",
+ "delete": "删除"
+ },
+ "visibility": {
+ "show": "显示",
+ "hide": "隐藏"
+ }
+ },
+ "projectPanel": {
+ "title": "项目经历",
+ "addButton": "添加项目",
+ "defaultProject": {
+ "name": "个人项目",
+ "description": "项目描述",
+ "role": "负责内容",
+ "technologies": "技术栈",
+ "date": "2023.01 - 2023.06"
+ },
+ "placeholders": {
+ "name": "项目名称",
+ "description": "简要描述项目背景和目标",
+ "role": "你在项目中的角色和职责",
+ "technologies": "使用的技术和工具",
+ "date": "项目时间范围",
+ "link": "项目链接(可选)"
+ }
+ },
+ "projectItem": {
+ "labels": {
+ "name": "项目名称",
+ "role": "项目角色",
+ "date": "项目时间",
+ "description": "项目描述",
+ "link": "项目链接"
+ },
+ "placeholders": {
+ "name": "请输入项目名称",
+ "role": "你在项目中的角色",
+ "date": "项目时间范围",
+ "description": "简要描述项目背景和目标",
+ "link": "项目链接(可选)"
+ },
+ "buttons": {
+ "edit": "编辑",
+ "save": "保存",
+ "cancel": "取消",
+ "delete": "删除"
+ },
+ "visibility": {
+ "show": "显示",
+ "hide": "隐藏"
+ }
+ },
+ "educationPanel": {
+ "title": "教育背景",
+ "addButton": "添加教育经历",
+ "defaultProject": {
+ "school": "学校名称",
+ "degree": "学历",
+ "major": "专业",
+ "date": "2020.09 - 2024.06"
+ },
+ "placeholders": {
+ "school": "请输入学校名称",
+ "degree": "请选择学历",
+ "major": "请输入专业名称",
+ "date": "请输入就读时间范围"
+ }
+ },
+ "educationItem": {
+ "labels": {
+ "school": "学校名称",
+ "degree": "学历",
+ "major": "专业",
+ "date": "就读时间",
+ "description": "学校简介",
+ "gpa": "GPA",
+ "location": "所在地",
+ "startDate": "开始时间",
+ "endDate": "结束时间"
+ },
+ "placeholders": {
+ "school": "请输入学校名称",
+ "degree": "请选择学历",
+ "major": "请输入专业名称",
+ "date": "请输入就读时间范围",
+ "description": "请输入学校简介",
+ "gpa": "请输入GPA",
+ "location": "请输入所在地"
+ },
+ "buttons": {
+ "edit": "编辑",
+ "save": "保存",
+ "cancel": "取消",
+ "delete": "删除"
+ },
+ "visibility": {
+ "show": "显示",
+ "hide": "隐藏"
+ }
+ }
}
}