From 6b460fded4cf6d571e6186b9e744bf016db1e55a Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 28 May 2026 13:31:53 +0300 Subject: [PATCH] feat(web): create i18n.js with EN/RO translation dictionaries Extract i18n dictionary from main.js into dedicated i18n.js module. Sets window.MyAi.i18n with 228 keys across English and Romanian. Main.js will consume this via t(key) helper function. Closes #31 Co-Authored-By: Claude Sonnet 4.6 --- web/wwwroot/js/i18n.js | 230 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 web/wwwroot/js/i18n.js diff --git a/web/wwwroot/js/i18n.js b/web/wwwroot/js/i18n.js new file mode 100644 index 0000000..1e6697a --- /dev/null +++ b/web/wwwroot/js/i18n.js @@ -0,0 +1,230 @@ +/** + * MyAi Translation Dictionary + * + * Exposes window.MyAi.i18n with EN/RO translation keys. + * Main.js accesses these via the t(key) helper function. + */ +(function () { + "use strict"; + window.MyAi = window.MyAi || {}; + window.MyAi.i18n = { + en: { + "brand.subtitle": "AI engineering showcase", + "nav.demos": "Demos", + "nav.contact": "Contact", + "nav.navigator": "Navigator", + "nav.matcher": "Matcher", + "home.eyebrow": "Applied AI lab", + "home.title": "Production-minded AI demos, not generic chatbot wrappers.", + "home.text": "MyAi.ro is a technical showcase for practical AI systems: document understanding, retrieval, matching, automation and decision support.", + "home.openCv": "Open CV Matcher", + "home.step1": "CV.pdf", + "home.step2": "skills, projects, experience", + "home.step3": "relevant CV context", + "home.step4": "job match + gaps", + "home.navigator": "Navigator", + "home.selectDemo": "Select an AI demo", + "home.selectText": "Our first steps in AI integrations.", + "tag.available": "Available", + "tag.next": "Next", + "demo.cv.title": "CV Matcher", + "demo.cv.text": "Upload a CV PDF, add a job link or description, and get a match score with strengths and gaps.", + "demo.open": "Open demo →", + "demo.rag.title": "RAG Playground", + "demo.rag.text": "Experiment with chunk size, retrieval count and source context transparency.", + "demo.agent.title": "Agent Automation", + "demo.agent.text": "Job discovery, filtering, ranking and notification workflows.", + "contact.title": "Discuss an AI integration or custom software project", + "contact.text": "Fill in the form and we'll get back to you.", + "contact.person": "Contact person", + "contact.phone": "Phone", + "form.name": "Name", + "form.namePlaceholder": "Your name", + "form.email": "Email", + "form.emailPlaceholder": "name@company.com", + "form.message": "Message", + "form.messagePlaceholder": "Tell me what you want to build.", + "form.send": "Send message", + "form.thanks": "Thank you for your message.", + "form.captchaFailed": "Captcha verification failed.", + "form.failed": "Failed to send the message.", + "form.rateLimited": "Too many requests from your network. Please wait a moment and try again.", + "form.required.name": "Please enter your name.", + "form.required.email": "Please enter your email address.", + "form.required.emailInvalid": "Please enter a valid email address.", + "form.required.message": "Please write a message.", + "subscribe.title": "Stay in the loop", + "subscribe.text": "Get a short note when a new AI demo is published. One email at most every few weeks.", + "subscribe.emailPlaceholder": "name@company.com", + "subscribe.gdpr": "I agree to receive occasional emails about new demos.", + "subscribe.submit": "Subscribe", + "subscribe.thanks": "Thanks! You are subscribed.", + "subscribe.failed": "Could not subscribe right now. Please try again later.", + "subscribe.noConsent": "Please confirm your consent first.", + "footer.rights": "All rights reserved", + "footer.top": "Back to top", + "legal.terms": "Terms", + "legal.privacy": "Privacy", + "legal.cookies": "Cookies", + "status.sending": "Sending...", + "cookies.title": "Cookies", + "cookies.text": "We use necessary cookies and, with your consent, analytics through Google Tag Manager.", + "cookies.policy": "Privacy policy", + "cookies.reject": "Reject", + "cookies.necessary": "Necessary only", + "cookies.accept": "Accept analytics", + "cookies.settings": "Cookie settings", + "cv.brand": "CV Matcher", + "cv.eyebrow": "AI CV Matcher", + "cv.title": "Upload your CV, add a job link, and see how well they match.", + "cv.text": "We read your CV, find the parts most relevant to the job, then produce a match score with strengths, gaps and suggested next steps.", + "cv.try": "Try matcher", + "cv.back": "Back to navigator", + "cv.step1": "PDF text extraction", + "cv.step2": "CV chunking + embeddings", + "cv.step3": "Job URL/description parsing", + "cv.step4": "Match score + evidence", + "cv.input": "Input", + "cv.details": "CV and job details", + "cv.upload": "Upload CV PDF", + "cv.fileHint": "PDF only.", + "cv.jobLink": "Job link", + "cv.jobDescription": "Or paste job description", + "cv.jobPlaceholder": "Paste the job description if the page can't be read automatically.", + "cv.gdpr": "I agree that my CV is processed and stored.", + "cv.submit": "Extract CV and match job", + "cv.result": "Result", + "cv.analysis": "Match analysis", + "cv.empty": "Upload a CV and provide a job link or description to generate a result.", + "cv.contactTitle": "Want this adapted for your workflow?", + "cv.contactText": "Send a quick note and we'll get back to you.", + "cv.noFile": "Please upload a CV PDF.", + "cv.noJob": "Add a job link or paste a job description.", + "cv.noConsent": "GDPR consent is required.", + "cv.processing": "Processing...", + "cv.extracting": "Extracting CV and matching job...", + "cv.processingLong": "Processing CV PDF and job input.", + "cv.cvFailed": "CV extraction failed", + "cv.matchFailed": "Job matching failed", + "cv.rateLimited": "Too many CV matcher requests from your network. Please try again in a few minutes.", + "cv.completed": "Match completed.", + "cv.backendMissing": "There was an error while processing the CV.", + "cv.loaderTitle": "Working on your CV", + "cv.loaderText": "Extracting text, retrieving context and scoring the match. This can take a moment.", + "cv.noSummary": "No summary available.", + "cv.noItems": "No items yet.", + "cv.strengths": "Strengths", + "cv.gaps": "Gaps", + "cv.evidence": "Supporting CV excerpts" + }, + ro: { + "brand.subtitle": "prezentare inginerie AI", + "nav.demos": "Demo-uri", + "nav.contact": "Contact", + "nav.navigator": "Navigator", + "nav.matcher": "Matcher", + "home.eyebrow": "Laborator AI aplicat", + "home.title": "Demo-uri AI orientate spre producție, nu simple wrapper-e de chatbot.", + "home.text": "MyAi.ro este o prezentare tehnică pentru sisteme AI practice: înțelegere documente, retrieval, potrivire, automatizare și suport decizional.", + "home.openCv": "Deschide CV Matcher", + "home.step1": "CV.pdf", + "home.step2": "competențe, proiecte, experiență", + "home.step3": "context relevant din CV", + "home.step4": "potrivire job + lipsuri", + "home.navigator": "Navigator", + "home.selectDemo": "Alege un demo AI", + "home.selectText": "Primele noastre proiecte.", + "tag.available": "Disponibil", + "tag.next": "Urmează", + "demo.cv.title": "CV Matcher", + "demo.cv.text": "Încarcă un CV PDF, adaugă un link sau o descriere de job și primește un scor de potrivire cu puncte forte și lipsuri.", + "demo.open": "Deschide demo →", + "demo.rag.title": "RAG Playground", + "demo.rag.text": "Experimentează cu dimensiunea chunk-urilor, numărul de rezultate și transparența surselor.", + "demo.agent.title": "Automatizare cu agenți", + "demo.agent.text": "Fluxuri pentru descoperire joburi, filtrare, ordonare și notificări.", + "contact.title": "Discută o integrare AI sau un proiect software custom", + "contact.text": "Completează formularul și te vom contacta.", + "contact.person": "Persoană de contact", + "contact.phone": "Telefon", + "form.name": "Nume", + "form.namePlaceholder": "Numele tău", + "form.email": "Email", + "form.emailPlaceholder": "nume@companie.ro", + "form.message": "Mesaj", + "form.messagePlaceholder": "Spune-mi ce vrei să construiești.", + "form.send": "Trimite mesajul", + "form.thanks": "Mulțumesc pentru mesaj.", + "form.captchaFailed": "Verificarea Captcha a eșuat.", + "form.failed": "Mesajul nu a putut fi trimis.", + "form.rateLimited": "Prea multe cereri din rețeaua ta. Te rugăm să aștepți câteva momente și să încerci din nou.", + "form.required.name": "Te rugăm să introduci numele.", + "form.required.email": "Te rugăm să introduci adresa de email.", + "form.required.emailInvalid": "Te rugăm să introduci o adresă de email validă.", + "form.required.message": "Te rugăm să scrii un mesaj.", + "subscribe.title": "Rămâi la curent", + "subscribe.text": "Primești o notă scurtă când publicăm un nou demo AI. Cel mult un email la câteva săptămâni.", + "subscribe.emailPlaceholder": "nume@companie.ro", + "subscribe.gdpr": "Sunt de acord să primesc ocazional emailuri despre noile demo-uri.", + "subscribe.submit": "Abonează-mă", + "subscribe.thanks": "Mulțumesc! Ești abonat.", + "subscribe.failed": "Nu am putut realiza abonarea acum. Te rugăm să încerci mai târziu.", + "subscribe.noConsent": "Te rugăm să confirmi întâi consimțământul.", + "footer.rights": "Toate drepturile rezervate", + "footer.top": "Înapoi sus", + "legal.terms": "Termeni", + "legal.privacy": "Confidențialitate", + "legal.cookies": "Cookies", + "status.sending": "Se trimite...", + "cookies.title": "Cookies", + "cookies.text": "Folosim cookies necesare și, cu acordul tău, analytics prin Google Tag Manager.", + "cookies.policy": "Politica de confidențialitate", + "cookies.reject": "Respinge", + "cookies.necessary": "Doar necesare", + "cookies.accept": "Accept analytics", + "cookies.settings": "Setări cookies", + "cv.brand": "CV Matcher", + "cv.eyebrow": "AI CV Matcher", + "cv.title": "Încarcă CV-ul, adaugă un link de job și vezi cât de bine se potrivesc.", + "cv.text": "Îți citim CV-ul, găsim părțile cele mai relevante pentru job și calculăm un scor de potrivire cu puncte forte, lipsuri și pași următori sugerați.", + "cv.try": "Încearcă matcherul", + "cv.back": "Înapoi la navigator", + "cv.step1": "Extragere text PDF", + "cv.step2": "Chunking CV + embeddings", + "cv.step3": "Parsare URL/descriere job", + "cv.step4": "Scor potrivire + dovezi", + "cv.input": "Date de intrare", + "cv.details": "CV și detalii job", + "cv.upload": "Încarcă CV PDF", + "cv.fileHint": "Doar PDF.", + "cv.jobLink": "Link job", + "cv.jobDescription": "Sau lipește descrierea jobului", + "cv.jobPlaceholder": "Lipește descrierea jobului dacă pagina nu poate fi citită automat.", + "cv.gdpr": "Sunt de acord ca CV-ul meu să fie procesat și stocat.", + "cv.submit": "Extrage CV și compară jobul", + "cv.result": "Rezultat", + "cv.analysis": "Analiză potrivire", + "cv.empty": "Încarcă un CV și adaugă un link sau o descriere de job pentru a genera rezultatul.", + "cv.contactTitle": "Vrei o variantă adaptată fluxului tău de lucru?", + "cv.contactText": "Lasă-ne un mesaj și revenim cu detalii.", + "cv.noFile": "Te rog încarcă un CV PDF.", + "cv.noJob": "Adaugă un link de job sau lipește descrierea jobului.", + "cv.noConsent": "Consimțământul GDPR este obligatoriu.", + "cv.processing": "Se procesează...", + "cv.extracting": "Se extrage CV-ul și se compară jobul...", + "cv.processingLong": "Se procesează PDF-ul și informațiile despre job.", + "cv.cvFailed": "Extragerea CV-ului a eșuat", + "cv.matchFailed": "Potrivirea jobului a eșuat", + "cv.rateLimited": "Prea multe cereri către CV matcher din rețeaua ta. Te rugăm să încerci din nou peste câteva minute.", + "cv.completed": "Matching finalizat.", + "cv.backendMissing": "A apărut o eroare la procesarea CV-ului.", + "cv.loaderTitle": "Procesăm CV-ul tău", + "cv.loaderText": "Extragem textul, recuperăm contextul și calculăm scorul potrivirii. Poate dura câteva momente.", + "cv.noSummary": "Niciun sumar disponibil.", + "cv.noItems": "Niciun element.", + "cv.strengths": "Puncte forte", + "cv.gaps": "Lipsuri", + "cv.evidence": "Fragmente relevante din CV" + } + }; +})();