diff --git a/components/TemplateEditor.tsx b/components/TemplateEditor.tsx index 46f68ad..c8c0246 100644 --- a/components/TemplateEditor.tsx +++ b/components/TemplateEditor.tsx @@ -15,22 +15,22 @@ interface Props { } const DEFAULT_HEADER = `
-

My Company

+

La Mia Azienda

`; const DEFAULT_BODY = `

Gentile {{first_name}},

-

This is a default message body.

+

Questo è un messaggio di default.

`; const DEFAULT_FOOTER = `
-

© 2024 My Company. All rights reserved.

+

© 2024 La Mia Azienda. Tutti i diritti riservati.

`; const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { - const [name, setName] = useState(initialTemplate?.name || 'New Template'); + const [name, setName] = useState(initialTemplate?.name || 'Nuovo Template'); const [description, setDescription] = useState(initialTemplate?.description || ''); - const [subject, setSubject] = useState(initialTemplate?.subject || 'Welcome to our service'); + const [subject, setSubject] = useState(initialTemplate?.subject || 'Benvenuti nel nostro servizio'); const [header, setHeader] = useState(initialTemplate?.header || DEFAULT_HEADER); const [body, setBody] = useState(initialTemplate?.body || DEFAULT_BODY); @@ -67,8 +67,8 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { const newKey = generateTemplateKey(name); if (!newKey) { - setNameError('Template name cannot be empty or symbols only.'); - alert('Template name cannot be empty.'); + setNameError('Il nome del template non può essere vuoto o contenere solo simboli.'); + alert('Il nome del template non può essere vuoto.'); return; } @@ -83,8 +83,8 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { }); if (isDuplicate) { - setNameError('A template with this name already exists.'); - alert('A template with this name (or resulting ID) already exists. Please choose a unique name.'); + setNameError('Esiste già un template con questo nome.'); + alert('Un template con questo nome (o ID risultante) esiste già. Per favore scegli un nome univoco.'); setIsSaving(false); return; } @@ -103,7 +103,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { await saveTemplate(newTemplate); onSave(); } catch (e) { - alert("Failed to save template. Check server logs."); + alert("Impossibile salvare il template. Controlla i log del server."); } finally { setIsSaving(false); } @@ -120,14 +120,14 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { setShowAiModal(false); setAiPrompt(''); } catch (e) { - alert("Error generating content. Please check API Key configuration."); + alert("Errore nella generazione del contenuto. Controlla la configurazione della API Key."); } finally { setIsGenerating(false); } }; const tempTemplateObj = { - id: initialTemplate?.id || 'PREVIEW', + id: initialTemplate?.id || 'ANTEPRIMA', name, description, subject, @@ -158,6 +158,13 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { } }; + // Maps internal tab keys to Italian display names + const tabNames: Record = { + header: 'Testata', + body: 'Corpo', + footer: 'Piè di pagina' + }; + return (
{/* Top Bar */} @@ -168,7 +175,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {

- {initialTemplate ? 'Edit Template' : 'Create Template'} + {initialTemplate ? 'Modifica Template' : 'Crea Template'}

@@ -178,7 +185,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { className="flex items-center gap-2 px-4 py-2 text-slate-600 bg-white border border-slate-300 rounded-lg hover:bg-slate-50 font-medium transition-colors" > - Integration + Integrazione @@ -199,25 +206,25 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { {/* Metadata */}
- + setName(e.target.value)} className={`w-full px-3 py-2 border rounded-md focus:ring-2 focus:ring-brand-500 outline-none bg-white ${nameError ? 'border-red-500 focus:border-red-500' : 'border-slate-300 focus:border-brand-500'}`} - placeholder="e.g., Welcome Email" + placeholder="es. Email di Benvenuto" /> {nameError &&

{nameError}

} -

Must be unique. Used to generate the database key: {generateTemplateKey(name) || '...'}

+

Deve essere univoco. Usato per generare la chiave DB: {generateTemplateKey(name) || '...'}

- + setSubject(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md focus:ring-2 focus:ring-brand-500 focus:border-brand-500 outline-none bg-white" - placeholder="Subject line... (supports {{placeholders}})" + placeholder="Oggetto... (supporta {{placeholder}})" />
@@ -225,11 +232,11 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { {/* Variable Manager */}
- Active Variables - Auto-detected from text + Variabili Attive + Rilevate automaticamente dal testo
- {detectedVars.length === 0 && No variables detected yet. Type {'{{name}}'} to add one.} + {detectedVars.length === 0 && Nessuna variabile rilevata. Scrivi {'{{nome}}'} per aggiungerne una.} {detectedVars.map(v => ( {`{{${v}}}`} @@ -250,7 +257,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { : 'text-slate-500 hover:text-slate-700' }`} > - {tab} + {tabNames[tab]} ))}
@@ -258,14 +265,14 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { {/* Editor Area */}
- +
@@ -275,13 +282,13 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { key={activeTab} // Force remount on tab change to sync contentEditable value={getActiveContent()} onChange={setActiveContent} - placeholder={`Design your ${activeTab} here...`} + placeholder={`Crea qui la sezione ${tabNames[activeTab]}...`} className="h-full shadow-sm" />

- Use the "Variable" button in the toolbar to insert placeholders like {'{{name}}'}. + Usa il pulsante "Variabile" nella toolbar per inserire placeholder come {'{{nome}}'}.

@@ -291,10 +298,10 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
- Live Preview + Anteprima Live
- Renders as standard HTML + Renderizzato come HTML standard
{/* Scrollable container: flex-1 ensures it takes available space, overflow-y-auto enables scrolling */} @@ -303,7 +310,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
{/* Simulate Subject Line in Preview */}
- Subject: + Oggetto:

{subject.replace(/\{\{([\w\d_-]+)\}\}/g, (match, p1) => `${match}`)}

@@ -323,7 +330,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {

- Integration Details + Dettagli Integrazione

@@ -350,7 +357,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
- +
                         {currentSelectSql}
@@ -358,7 +365,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
                       
@@ -370,7 +377,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
                 
@@ -379,13 +386,13 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
                     
                   

- Paste this into a Code Node connected after your SQL node. Replace REPLACE_WITH_VALUE with your actual data variables (e.g. $('NodeName').item.json.name). + Incolla questo codice in un Nodo Code collegato dopo il tuo nodo SQL. Sostituisci REPLACE_WITH_VALUE con le variabili reali (es. $('NodeName').item.json.name).

@@ -399,15 +406,15 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {

- AI Content Generator + Generatore Contenuti IA

- Describe what you want for the {activeTab} section. - The AI will generate HTML code with placeholders. + Descrivi cosa vuoi per la sezione {tabNames[activeTab]}. + L'IA genererà il codice HTML con i placeholder necessari.