1- "use client" ;
1+ "use client" ;
22
33import { useEffect , useState , useCallback } from "react" ;
44import {
@@ -11,7 +11,7 @@ import {
1111import { CSS } from "@dnd-kit/utilities" ;
1212import { RefreshCw , AlertCircle , Plus , X , ChevronDown , ChevronUp , GripVertical } from "lucide-react" ;
1313import { extractCV , CVData , Keywords } from "@/lib/api" ;
14- import { useLang , detectJobLang } from "@/lib/i18n" ;
14+ import { useLang } from "@/lib/i18n" ;
1515
1616// ─── Types ───────────────────────────────────────────────────────────────────
1717
@@ -39,63 +39,6 @@ const LANGUAGES_FR = [
3939 "Danois" , "Norvégien" , "Finnois" , "Coréen" , "Hindi" , "Autre" ,
4040] ;
4141
42- // ─── i18n labels ─────────────────────────────────────────────────────────────
43-
44- function t ( key : string , lang : "en" | "fr" ) : string {
45- const labels : Record < string , Record < string , string > > = {
46- reviewing : { en : "Review your CV" , fr : "Vérifiez votre CV" } ,
47- reviewSub : { en : "Check everything looks right. Edit any field before generating." , fr : "Vérifiez que tout est correct. Modifiez avant de générer." } ,
48- basics : { en : "Basics" , fr : "Informations générales" } ,
49- contact : { en : "Contact" , fr : "Contact" } ,
50- experience : { en : "Experience" , fr : "Expérience" } ,
51- education : { en : "Education" , fr : "Formation" } ,
52- skills : { en : "Skills" , fr : "Compétences" } ,
53- certifications : { en : "Certifications" , fr : "Certifications" } ,
54- languages : { en : "Languages" , fr : "Langues" } ,
55- projects : { en : "Projects" , fr : "Projets" } ,
56- keywords : { en : "Job Keywords" , fr : "Mots-clés du poste" } ,
57- fullName : { en : "Full name" , fr : "Nom complet" } ,
58- profTitle : { en : "Professional title" , fr : "Titre professionnel" } ,
59- summary : { en : "Summary" , fr : "Résumé" } ,
60- email : { en : "Email" , fr : "Email" } ,
61- phone : { en : "Phone" , fr : "Téléphone" } ,
62- location : { en : "Location" , fr : "Localisation" } ,
63- linkedin : { en : "LinkedIn URL" , fr : "URL LinkedIn" } ,
64- company : { en : "Company" , fr : "Entreprise" } ,
65- title : { en : "Title" , fr : "Titre" } ,
66- start : { en : "Start" , fr : "Début" } ,
67- end : { en : "End" , fr : "Fin" } ,
68- bullets : { en : "Bullets" , fr : "Points" } ,
69- addBullet : { en : "Add bullet" , fr : "Ajouter un point" } ,
70- addExperience : { en : "Add experience" , fr : "Ajouter une expérience" } ,
71- addEducation : { en : "Add formation" , fr : "Ajouter une formation" } ,
72- addCert : { en : "Add certification" , fr : "Ajouter une certification" } ,
73- addLanguage : { en : "Add language" , fr : "Ajouter une langue" } ,
74- addProject : { en : "Add project" , fr : "Ajouter un projet" } ,
75- addSkill : { en : "Add skill" , fr : "Ajouter une compétence" } ,
76- remove : { en : "Remove" , fr : "Supprimer" } ,
77- institution : { en : "Institution" , fr : "Établissement" } ,
78- degree : { en : "Degree" , fr : "Diplôme" } ,
79- field : { en : "Field of study" , fr : "Domaine d'études" } ,
80- year : { en : "Year" , fr : "Année" } ,
81- issuer : { en : "Issuer" , fr : "Organisme" } ,
82- language : { en : "Language" , fr : "Langue" } ,
83- level : { en : "Level" , fr : "Niveau" } ,
84- projName : { en : "Project name" , fr : "Nom du projet" } ,
85- projDesc : { en : "Description" , fr : "Description" } ,
86- projUrl : { en : "URL" , fr : "URL" } ,
87- looksGood : { en : "Looks good — choose template" , fr : "C'est bon — choisir le modèle" } ,
88- back : { en : "← Back" , fr : "← Retour" } ,
89- keywordsSub : { en : "Keywords extracted from the job description. The AI uses these when tailoring." , fr : "Mots-clés extraits de l'offre d'emploi. L'IA les utilise pour adapter votre CV." } ,
90- technical : { en : "Technical" , fr : "Technique" } ,
91- soft : { en : "Soft skills" , fr : "Savoir-être" } ,
92- industry : { en : "Industry" , fr : "Secteur" } ,
93- add : { en : "Add" , fr : "Ajouter" } ,
94- dragHint : { en : "Drag sections to reorder" , fr : "Glissez les sections pour les réorganiser" } ,
95- enableSection : { en : "Enable section" , fr : "Activer la section" } ,
96- } ;
97- return labels [ key ] ?. [ lang ] ?? labels [ key ] ?. [ "en" ] ?? key ;
98- }
9942
10043// ─── Small UI components ──────────────────────────────────────────────────────
10144
@@ -206,16 +149,6 @@ function SortableSection({ id, title, children, defaultOpen = false, rightSlot }
206149 ) ;
207150}
208151
209- // ─── Language detection ───────────────────────────────────────────────────────
210-
211- function detectLang ( jobDescription : string ) : "en" | "fr" {
212- const frWords = [ "le " , "la " , "les " , "de " , "du " , "des " , "et " , "en " , "pour " , "avec " ,
213- "nous " , "vous " , "dans " , "sur " , "une " , "un " , "est " , "sont " , "être " , "avoir " ,
214- "poste " , "emploi " , "entreprise " , "équipe " , "expérience " , "compétences " ] ;
215- const text = jobDescription . toLowerCase ( ) ;
216- const frCount = frWords . filter ( w => text . includes ( w ) ) . length ;
217- return frCount >= 4 ? "fr" : "en" ;
218- }
219152
220153// ─── Props ────────────────────────────────────────────────────────────────────
221154
@@ -340,15 +273,15 @@ export default function StepReview({ file, pastedText, jobDescription, initialCv
340273 if ( loadState === "loading" ) return (
341274 < div className = "animate-fade-up" >
342275 < h2 className = "text-3xl md:text-4xl font-bold mb-2" style = { { fontFamily : "var(--font-display)" } } >
343- { lang === "fr" ? "Analyse de votre profil…" : "Analysing your profile…" }
276+ { u ( "analysing" ) }
344277 </ h2 >
345278 < p className = "text-[#9A9A9A] mb-10 text-sm" >
346- { lang === "fr" ? "Extraction de votre expérience. Environ 15 secondes." : "Extracting your experience and matching it to the job. Takes about 15 seconds." }
279+ { u ( "analysingTime" ) }
347280 </ p >
348281 < div className = "flex items-center gap-4 px-8 py-4 border border-[#2E2E2E]" >
349282 < RefreshCw size = { 16 } className = "animate-spin" style = { { color : "#FF4D00" } } />
350283 < span className = "text-sm text-[#F5F0EB] animate-pulse" >
351- { lang === "fr" ? "Lecture de votre CV et de l'offre d'emploi…" : "Reading your CV and job description…" }
284+ { u ( "analysingMsg" ) }
352285 </ span >
353286 </ div >
354287 </ div >
@@ -362,7 +295,7 @@ export default function StepReview({ file, pastedText, jobDescription, initialCv
362295 < div className = "flex items-start gap-3 p-4 border border-red-900 bg-red-950/30" >
363296 < AlertCircle size = { 18 } className = "text-red-400 mt-0.5 shrink-0" />
364297 < div >
365- < p className = "text-sm font-medium text-red-400 mb-1" > { lang === "fr" ? "Échec de l'extraction" : "Extraction failed" } </ p >
298+ < p className = "text-sm font-medium text-red-400 mb-1" > { u ( "extractFailed" ) } </ p >
366299 < p className = "text-xs text-red-400/70" > { errorMessage } </ p >
367300 </ div >
368301 </ div >
@@ -553,7 +486,7 @@ export default function StepReview({ file, pastedText, jobDescription, initialCv
553486 < p className = "text-xs text-[#9A9A9A]" > { u ( "keywordsSub" ) } </ p >
554487 { ( [ "technical" , "soft" , "industry" ] as const ) . map ( bucket => (
555488 < div key = { bucket } >
556- < p className = "text-xs font-semibold uppercase tracking-widest text-[#9A9A9A] mb-2" > { t ( bucket , lang ) } </ p >
489+ < p className = "text-xs font-semibold uppercase tracking-widest text-[#9A9A9A] mb-2" > { u ( bucket ) } </ p >
557490 < div className = "flex flex-wrap gap-2" >
558491 { keywords [ bucket ] . map ( ( k , i ) => < Pill key = { i } label = { k } onRemove = { ( ) => removeKw ( bucket , i ) } /> ) }
559492 < AddPill placeholder = { u ( "add" ) } onAdd = { v => addKw ( bucket , v ) } />
@@ -612,7 +545,7 @@ export default function StepReview({ file, pastedText, jobDescription, initialCv
612545 { isEnabled
613546 ? sectionContent [ section . id ]
614547 : < p className = "text-xs text-[#9A9A9A] italic" >
615- { lang === "fr" ? "Section désactivée. Activez-la pour l'inclure dans votre CV." : "Section disabled. Toggle on to include in your CV." }
548+ { u ( "sectionDisabled" ) }
616549 </ p >
617550 }
618551 </ SortableSection >
0 commit comments