refactor: Extract all hardcoded content to JSON files

- Move all bilingual text from templates to UI JSON (labels, buttons, modals)
- Move skills summary paragraph to CV JSON with HTML support
- Add new UI sections: navigation, viewControls, sections, footer, portfolio,
  pdfModal, shortcutsModal, infoModal, widgets
- Update Go structs to match expanded JSON structure
- Add template.HTML type for CV.SkillsSummary field
- Add JSON content validation test (70-json-content-validation.test.mjs)

Templates now contain only structural logic (CSS classes, HTML attributes)
while all user-visible text loads from JSON files for proper i18n support.
This commit is contained in:
juanatsap
2025-11-30 10:13:37 +00:00
parent c834919a3c
commit 9636b3659f
36 changed files with 806 additions and 168 deletions
+29 -13
View File
@@ -1,9 +1,13 @@
package cv
import "html/template"
// CV represents the complete curriculum vitae structure
type CV struct {
Personal Personal `json:"personal"`
SEO SEO `json:"seo"`
Summary string `json:"summary"`
SkillsSummary template.HTML `json:"skillsSummary"`
Experience []Experience `json:"experience"`
Education []Education `json:"education"`
Skills Skills `json:"skills"`
@@ -18,19 +22,31 @@ type CV struct {
}
type Personal struct {
Name string `json:"name"`
Title string `json:"title"`
Location string `json:"location"`
Email string `json:"email"`
Phone string `json:"phone"`
DateOfBirth string `json:"dateOfBirth"`
PlaceOfBirth string `json:"placeOfBirth"`
Citizenship string `json:"citizenship"`
LinkedIn string `json:"linkedin"`
GitHub string `json:"github"`
Domestika string `json:"domestika"`
Website string `json:"website"`
Photo string `json:"photo"`
Name string `json:"name"`
Title string `json:"title"`
TitleBadges []string `json:"titleBadges"`
Location string `json:"location"`
Email string `json:"email"`
Phone string `json:"phone"`
DateOfBirth string `json:"dateOfBirth"`
PlaceOfBirth string `json:"placeOfBirth"`
Citizenship string `json:"citizenship"`
LinkedIn string `json:"linkedin"`
GitHub string `json:"github"`
Domestika string `json:"domestika"`
Website string `json:"website"`
Photo string `json:"photo"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
Username string `json:"username"`
}
type SEO struct {
PageTitle string `json:"pageTitle"`
MetaTitle string `json:"metaTitle"`
MetaDescription string `json:"metaDescription"`
OgDescription string `json:"ogDescription"`
Keywords string `json:"keywords"`
}
type Experience struct {
+131 -12
View File
@@ -4,28 +4,95 @@ import "html/template"
// UI represents user interface translations and configuration
type UI struct {
InfoModal InfoModal `json:"infoModal"`
Navigation Navigation `json:"navigation"`
ViewControls ViewControls `json:"viewControls"`
Sections Sections `json:"sections"`
Footer Footer `json:"footer"`
Portfolio Portfolio `json:"portfolio"`
PdfModal PdfModal `json:"pdfModal"`
ShortcutsModal ShortcutsModal `json:"shortcutsModal"`
InfoModal InfoModal `json:"infoModal"`
Widgets Widgets `json:"widgets"`
}
type InfoModal struct {
Title string `json:"title"`
Description template.HTML `json:"description"`
TechStack TechStack `json:"techStack"`
ViewSource string `json:"viewSource"`
ViewSourceSubtext string `json:"viewSourceSubtext"`
// Navigation labels for hamburger menu
type Navigation struct {
CvSections string `json:"cvSections"`
Training string `json:"training"`
Skills string `json:"skills"`
Experience string `json:"experience"`
Awards string `json:"awards"`
Projects string `json:"projects"`
Courses string `json:"courses"`
Languages string `json:"languages"`
References string `json:"references"`
Other string `json:"other"`
QuickActions string `json:"quickActions"`
CollapseAll string `json:"collapseAll"`
ExpandAll string `json:"expandAll"`
Zoom string `json:"zoom"`
ViewControls string `json:"viewControls"`
Actions string `json:"actions"`
}
type TechStack struct {
GoHono string `json:"goHono"`
HTMX string `json:"htmx"`
HTML5 string `json:"html5"`
CSS3 string `json:"css3"`
// ViewControls labels for toggle buttons
type ViewControls struct {
Length string `json:"length"`
Icons string `json:"icons"`
View string `json:"view"`
}
// Sections labels for CV section headers
type Sections struct {
TechnicalSkills string `json:"technicalSkills"`
MoreSkills string `json:"moreSkills"`
YearsOfExperience string `json:"yearsOfExperience"`
DrivingLicense string `json:"drivingLicense"`
ObtainedFrom string `json:"obtainedFrom"`
CurrentBadge string `json:"currentBadge"`
ExpiredBadge string `json:"expiredBadge"`
Present string `json:"present"`
Technologies string `json:"technologies"`
MaintainedBy string `json:"maintainedBy"`
}
// Footer labels
type Footer struct {
ViewOnGithub string `json:"viewOnGithub"`
LastUpdated string `json:"lastUpdated"`
}
// Portfolio labels
type Portfolio struct {
SeeAllProjects string `json:"seeAllProjects"`
DomestikaPortfolio string `json:"domestikaPortfolio"`
}
// PdfModal labels
type PdfModal struct {
Title string `json:"title"`
Subtitle string `json:"subtitle"`
PreparingPdf string `json:"preparingPdf"`
PleaseWait string `json:"pleaseWait"`
Close string `json:"close"`
DownloadButton string `json:"downloadButton"`
ShortCv PdfCvOption `json:"shortCv"`
DefaultCv PdfCvOption `json:"defaultCv"`
ExtendedCv PdfCvOption `json:"extendedCv"`
}
type PdfCvOption struct {
Title string `json:"title"`
Pages string `json:"pages"`
Description string `json:"description"`
AriaLabel string `json:"ariaLabel"`
}
type ShortcutsModal struct {
Title string `json:"title"`
Subtitle string `json:"subtitle"`
Description string `json:"description"`
Close string `json:"close"`
Sections ShortcutsSections `json:"sections"`
}
@@ -59,3 +126,55 @@ type ShortcutItem struct {
Key string `json:"key"`
Description string `json:"description"`
}
type InfoModal struct {
Title string `json:"title"`
Description template.HTML `json:"description"`
TechStack TechStack `json:"techStack"`
ViewSource string `json:"viewSource"`
ViewSourceSubtext string `json:"viewSourceSubtext"`
}
type TechStack struct {
GoHono string `json:"goHono"`
HTMX string `json:"htmx"`
HTML5 string `json:"html5"`
CSS3 string `json:"css3"`
}
// Widget label types
type Widgets struct {
BackToTop WidgetLabel `json:"backToTop"`
Info WidgetLabel `json:"info"`
Download WidgetLabel `json:"download"`
Print WidgetLabel `json:"print"`
Shortcuts WidgetLabel `json:"shortcuts"`
ZoomToggle WidgetLabel `json:"zoomToggle"`
ZoomControl ZoomControlLabel `json:"zoomControl"`
PdfToast PdfToastLabel `json:"pdfToast"`
ActionButtons ActionButtonsLabel `json:"actionButtons"`
}
type WidgetLabel struct {
AriaLabel string `json:"ariaLabel"`
Tooltip string `json:"tooltip"`
}
type ZoomControlLabel struct {
GroupLabel string `json:"groupLabel"`
CloseLabel string `json:"closeLabel"`
CloseTitle string `json:"closeTitle"`
SliderLabel string `json:"sliderLabel"`
ResetLabel string `json:"resetLabel"`
ResetTitle string `json:"resetTitle"`
}
type PdfToastLabel struct {
Title string `json:"title"`
CloseLabel string `json:"closeLabel"`
}
type ActionButtonsLabel struct {
DownloadPdf string `json:"downloadPdf"`
PrintFriendly string `json:"printFriendly"`
}