chore: add template folder
This commit is contained in:
parent
4d6fe85f53
commit
d33aeef1af
163
templates/blog-post.html
Normal file
163
templates/blog-post.html
Normal file
@ -0,0 +1,163 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{title}} - {{site_name | default(value="My Blog")}}</title>
|
||||
<meta name="description" content="{{description | default(value=content | excerpt(length=160))}}">
|
||||
{% if author %}
|
||||
<meta name="author" content="{{author}}">
|
||||
{% endif %}
|
||||
{% if tags %}
|
||||
<meta name="keywords" content="{{tags | join(sep=', ')}}">
|
||||
{% endif %}
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
h1 {
|
||||
color: #2c3e50;
|
||||
margin-bottom: 10px;
|
||||
font-size: 2.5em;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.meta {
|
||||
color: #7f8c8d;
|
||||
margin-bottom: 30px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.meta span {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.content {
|
||||
font-size: 1.1em;
|
||||
line-height: 1.8;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.tags {
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background: #3498db;
|
||||
color: white;
|
||||
padding: 5px 12px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.85em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.tag:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
.reading-time {
|
||||
color: #95a5a6;
|
||||
font-style: italic;
|
||||
}
|
||||
.share-buttons {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.share-button {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
background: #34495e;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.share-button:hover {
|
||||
background: #2c3e50;
|
||||
}
|
||||
.back-link {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.back-link a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
.back-link a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<article>
|
||||
<header>
|
||||
<h1>{{title}}</h1>
|
||||
<div class="meta">
|
||||
{% if author %}
|
||||
<span>By {{author}}</span>
|
||||
{% endif %}
|
||||
{% if published_date %}
|
||||
<span>Published on {{published_date | date_format(format="%B %d, %Y")}}</span>
|
||||
{% endif %}
|
||||
{% if reading_time %}
|
||||
<span class="reading-time">{{reading_time}} min read</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
{% if featured_image %}
|
||||
<img src="{{featured_image}}" alt="{{title}}" style="width: 100%; height: auto; margin-bottom: 20px; border-radius: 5px;">
|
||||
{% endif %}
|
||||
|
||||
{{content | markdown | safe}}
|
||||
</div>
|
||||
|
||||
{% if tags %}
|
||||
<div class="tags">
|
||||
<strong>Tags:</strong>
|
||||
{% for tag in tags %}
|
||||
<a href="/tag/{{tag | slug}}" class="tag">{{tag}}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if enable_sharing %}
|
||||
<div class="share-buttons">
|
||||
<strong>Share this post:</strong><br>
|
||||
<a href="https://twitter.com/intent/tweet?text={{title | urlencode}}&url={{page_url | urlencode}}" class="share-button" target="_blank">Twitter</a>
|
||||
<a href="https://www.facebook.com/sharer/sharer.php?u={{page_url | urlencode}}" class="share-button" target="_blank">Facebook</a>
|
||||
<a href="https://www.linkedin.com/sharing/share-offsite/?url={{page_url | urlencode}}" class="share-button" target="_blank">LinkedIn</a>
|
||||
<a href="mailto:?subject={{title | urlencode}}&body={{page_url | urlencode}}" class="share-button">Email</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
|
||||
<div class="back-link">
|
||||
<a href="{{back_url | default(value='/')}}">← Back to {{back_text | default(value='Home')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if analytics_id %}
|
||||
<script>
|
||||
// Add analytics tracking here if needed
|
||||
console.log('Analytics ID: {{analytics_id}}');
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
296
templates/email/README.md
Normal file
296
templates/email/README.md
Normal file
@ -0,0 +1,296 @@
|
||||
# Email Templates Structure
|
||||
|
||||
This directory contains internationalized email templates for the Rustelo framework. Templates are organized by language and support both HTML and text formats.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
templates/email/
|
||||
├── en_/ # English templates (default language)
|
||||
│ ├── html/ # HTML email templates
|
||||
│ │ ├── contact.hbs # Contact form submission
|
||||
│ │ ├── notification.hbs # General notifications
|
||||
│ │ └── welcome.hbs # Welcome email (example)
|
||||
│ └── text/ # Plain text email templates
|
||||
│ ├── contact.hbs # Contact form submission
|
||||
│ ├── notification.hbs # General notifications
|
||||
│ └── welcome.hbs # Welcome email (example)
|
||||
├── es_/ # Spanish templates
|
||||
│ ├── html/
|
||||
│ └── text/
|
||||
├── fr_/ # French templates (example)
|
||||
│ ├── html/
|
||||
│ └── text/
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Language Naming Convention
|
||||
|
||||
- Language directories must end with an underscore (`_`)
|
||||
- Use ISO 639-1 language codes (e.g., `en`, `es`, `fr`, `de`)
|
||||
- Examples: `en_`, `es_`, `fr_`, `de_`, `it_`, `pt_`, `ru_`, `ja_`, `ko_`, `zh_`
|
||||
|
||||
## Template Naming Convention
|
||||
|
||||
Templates are automatically registered with the naming pattern: `{language}_{template_name}_{format}`
|
||||
|
||||
Examples:
|
||||
- `en_contact_html` - English contact form HTML template
|
||||
- `es_contact_text` - Spanish contact form text template
|
||||
- `fr_notification_html` - French notification HTML template
|
||||
|
||||
## Language Fallback
|
||||
|
||||
The email system provides automatic language fallback:
|
||||
|
||||
1. **Requested Language**: First tries the specific language (e.g., `es_contact_html`)
|
||||
2. **Default Language**: Falls back to English (`en_contact_html`)
|
||||
3. **Legacy Support**: Falls back to templates without language prefix (`contact_html`)
|
||||
|
||||
## Creating New Templates
|
||||
|
||||
### 1. Create Language Directory
|
||||
|
||||
```bash
|
||||
mkdir -p templates/email/fr_/html
|
||||
mkdir -p templates/email/fr_/text
|
||||
```
|
||||
|
||||
### 2. Create Template Files
|
||||
|
||||
Create both HTML and text versions for each template:
|
||||
|
||||
```bash
|
||||
# HTML version
|
||||
touch templates/email/fr_/html/contact.hbs
|
||||
touch templates/email/fr_/html/notification.hbs
|
||||
|
||||
# Text version
|
||||
touch templates/email/fr_/text/contact.hbs
|
||||
touch templates/email/fr_/text/notification.hbs
|
||||
```
|
||||
|
||||
### 3. Template Content Structure
|
||||
|
||||
Each template should use Handlebars syntax and include appropriate variables:
|
||||
|
||||
**Contact Form Variables:**
|
||||
- `{{name}}` - Sender's name
|
||||
- `{{email}}` - Sender's email
|
||||
- `{{subject}}` - Message subject
|
||||
- `{{message}}` - Message content
|
||||
- `{{form_type}}` - Type of form (contact, support, etc.)
|
||||
- `{{submitted_at}}` - Submission timestamp
|
||||
- `{{ip_address}}` - Sender's IP address (optional)
|
||||
- `{{user_agent}}` - Sender's browser info (optional)
|
||||
- `{{fields}}` - Additional form fields (optional)
|
||||
|
||||
**Notification Variables:**
|
||||
- `{{title}}` - Notification title
|
||||
- `{{message}}` - Notification message
|
||||
- `{{content}}` - Additional content (optional)
|
||||
- `{{type}}` - Notification type (info, warning, success, danger)
|
||||
- `{{action_url}}` - Call-to-action URL (optional)
|
||||
- `{{action_text}}` - Call-to-action text (optional)
|
||||
- `{{timestamp}}` - Notification timestamp
|
||||
|
||||
## Available Handlebars Helpers
|
||||
|
||||
The email system provides several custom helpers:
|
||||
|
||||
### Date Formatting
|
||||
```handlebars
|
||||
{{date_format submitted_at "%B %d, %Y at %I:%M %p UTC"}}
|
||||
{{date_format submitted_at "%d de %B de %Y a las %H:%M UTC"}}
|
||||
```
|
||||
|
||||
### Text Manipulation
|
||||
```handlebars
|
||||
{{capitalize form_type}} <!-- "contact" → "Contact" -->
|
||||
{{truncate user_agent 100}} <!-- Limit text to 100 characters -->
|
||||
{{default action_text "Click Here"}} <!-- Use default if empty -->
|
||||
{{url_encode email}} <!-- URL encode text -->
|
||||
```
|
||||
|
||||
### Conditional Content
|
||||
```handlebars
|
||||
{{#if fields}}
|
||||
Additional fields are present
|
||||
{{/if}}
|
||||
|
||||
{{#each fields}}
|
||||
{{@key}}: {{this}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
## Language Detection
|
||||
|
||||
The email system automatically detects the preferred language from:
|
||||
|
||||
1. **User Profile**: User's saved language preference (if authenticated)
|
||||
2. **Request Headers**: `Accept-Language` HTTP header
|
||||
3. **Default Fallback**: English (`en`)
|
||||
|
||||
### Supported Languages
|
||||
|
||||
The system currently supports these language codes:
|
||||
- `en` - English
|
||||
- `es` - Spanish
|
||||
- `fr` - French
|
||||
- `de` - German
|
||||
- `it` - Italian
|
||||
- `pt` - Portuguese
|
||||
- `ru` - Russian
|
||||
- `ja` - Japanese
|
||||
- `ko` - Korean
|
||||
- `zh` - Chinese
|
||||
|
||||
## Using Templates in Code
|
||||
|
||||
### Server-side Usage
|
||||
|
||||
```rust
|
||||
// Send with automatic language detection
|
||||
email_service.send_contact_form(
|
||||
"John Doe",
|
||||
"john@example.com",
|
||||
"Question",
|
||||
"Message content",
|
||||
"admin@app.com"
|
||||
).await?;
|
||||
|
||||
// Send with specific language
|
||||
email_service.send_contact_form_with_language(
|
||||
"Juan Pérez",
|
||||
"juan@example.com",
|
||||
"Pregunta",
|
||||
"Contenido del mensaje",
|
||||
"admin@app.com",
|
||||
"es" // Spanish
|
||||
).await?;
|
||||
|
||||
// Send templated email
|
||||
email_service.send_templated_email_with_language(
|
||||
"user@example.com",
|
||||
"Welcome!",
|
||||
"welcome",
|
||||
template_data,
|
||||
"fr" // French
|
||||
).await?;
|
||||
```
|
||||
|
||||
### Client-side Language
|
||||
|
||||
The contact and support form components automatically detect language from browser headers:
|
||||
|
||||
```rust
|
||||
// Language is automatically detected from Accept-Language header
|
||||
<ContactForm
|
||||
recipient="contact@yourapp.com"
|
||||
title="Contact Us"
|
||||
/>
|
||||
```
|
||||
|
||||
## Template Best Practices
|
||||
|
||||
### 1. Consistency
|
||||
- Use consistent styling across all language versions
|
||||
- Maintain the same structure and layout
|
||||
- Keep variable names identical across languages
|
||||
|
||||
### 2. Cultural Considerations
|
||||
- Adapt date formats for different regions
|
||||
- Consider right-to-left languages if needed
|
||||
- Use appropriate salutations and closings
|
||||
- Respect cultural communication norms
|
||||
|
||||
### 3. Content Guidelines
|
||||
- Keep translations accurate and natural
|
||||
- Use professional tone appropriate for business communication
|
||||
- Include all necessary legal disclaimers
|
||||
- Test with native speakers when possible
|
||||
|
||||
### 4. HTML Best Practices
|
||||
- Use semantic HTML structure
|
||||
- Include proper `lang` attribute in HTML templates
|
||||
- Ensure responsive design for mobile devices
|
||||
- Use accessible color contrasts
|
||||
- Include fallback fonts for different character sets
|
||||
|
||||
### 5. Text Templates
|
||||
- Keep plain text versions readable and well-formatted
|
||||
- Use appropriate line breaks and spacing
|
||||
- Include all important information from HTML version
|
||||
- Test rendering in various email clients
|
||||
|
||||
## Testing Templates
|
||||
|
||||
### 1. Development Testing
|
||||
Use the console provider to see rendered templates:
|
||||
|
||||
```toml
|
||||
[email]
|
||||
provider = "console"
|
||||
```
|
||||
|
||||
### 2. Language Testing
|
||||
Test specific languages by setting Accept-Language header:
|
||||
|
||||
```bash
|
||||
curl -H "Accept-Language: es-ES,es;q=0.9" \
|
||||
-X POST /api/email/contact \
|
||||
-d '{"name":"Test","email":"test@example.com","subject":"Test","message":"Test"}'
|
||||
```
|
||||
|
||||
### 3. Template Validation
|
||||
- Verify all variables are properly escaped
|
||||
- Check for proper fallback behavior
|
||||
- Test with various data inputs
|
||||
- Validate HTML structure and accessibility
|
||||
|
||||
## Migration from Legacy Templates
|
||||
|
||||
If you have existing templates without language prefixes:
|
||||
|
||||
1. **Backup existing templates**
|
||||
2. **Create language directories** (`en_/html/`, `en_/text/`)
|
||||
3. **Move templates** to appropriate language directories
|
||||
4. **Update template names** to remove language prefixes
|
||||
5. **Test thoroughly** to ensure proper fallback behavior
|
||||
|
||||
## Configuration
|
||||
|
||||
Email template directory is configured in your application config:
|
||||
|
||||
```toml
|
||||
[email]
|
||||
# Template directory (relative to root_path)
|
||||
template_dir = "templates/email"
|
||||
```
|
||||
|
||||
Or via environment variable:
|
||||
```bash
|
||||
EMAIL_TEMPLATE_DIR=/path/to/templates/email
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Template Not Found Errors
|
||||
1. Check directory structure and naming convention
|
||||
2. Verify template files exist and are readable
|
||||
3. Check log output for specific template name being requested
|
||||
4. Ensure language fallback is working properly
|
||||
|
||||
### Language Detection Issues
|
||||
1. Verify Accept-Language header format
|
||||
2. Check supported language list
|
||||
3. Test with explicit language parameter
|
||||
4. Review language detection logs
|
||||
|
||||
### Rendering Issues
|
||||
1. Validate Handlebars syntax
|
||||
2. Check for missing variables
|
||||
3. Test with sample data
|
||||
4. Verify helper function usage
|
||||
|
||||
For more detailed troubleshooting, see the main email system documentation.
|
217
templates/email/en_/html/contact.hbs
Normal file
217
templates/email/en_/html/contact.hbs
Normal file
@ -0,0 +1,217 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Contact Form Submission</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.header p {
|
||||
margin: 10px 0 0 0;
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
}
|
||||
.content {
|
||||
padding: 30px;
|
||||
}
|
||||
.field {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
border-left: 4px solid #667eea;
|
||||
}
|
||||
.field-label {
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.field-value {
|
||||
color: #212529;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.message-field {
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.message-field .field-value {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.metadata {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #dee2e6;
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.metadata h3 {
|
||||
margin: 0 0 15px 0;
|
||||
color: #495057;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.metadata-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.metadata-label {
|
||||
color: #6c757d;
|
||||
font-weight: 500;
|
||||
}
|
||||
.metadata-value {
|
||||
color: #495057;
|
||||
}
|
||||
.footer {
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
.footer p {
|
||||
margin: 0;
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
.highlight {
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
padding: 15px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.highlight strong {
|
||||
color: #856404;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
.header, .content {
|
||||
padding: 20px;
|
||||
}
|
||||
.metadata-item {
|
||||
flex-direction: column;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.metadata-label {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>📧 New Contact Form Submission</h1>
|
||||
<p>You have received a new message from your website</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="highlight">
|
||||
<strong>Reply directly to this email</strong> to respond to the sender, or use the contact information below.
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Name</div>
|
||||
<div class="field-value">{{name}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Email Address</div>
|
||||
<div class="field-value">
|
||||
<a href="mailto:{{email}}" style="color: #667eea; text-decoration: none;">{{email}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Subject</div>
|
||||
<div class="field-value">{{subject}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Message</div>
|
||||
<div class="message-field">
|
||||
<div class="field-value">{{message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if fields}}
|
||||
<div class="field">
|
||||
<div class="field-label">Additional Information</div>
|
||||
<div style="margin-top: 10px;">
|
||||
{{#each fields}}
|
||||
<div style="margin-bottom: 10px; padding: 10px; background-color: #fff; border-radius: 4px; border-left: 3px solid #28a745;">
|
||||
<strong>{{@key}}:</strong> {{this}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="metadata">
|
||||
<h3>Submission Details</h3>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Submitted:</span>
|
||||
<span class="metadata-value">{{date_format submitted_at "%B %d, %Y at %I:%M %p UTC"}}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Form Type:</span>
|
||||
<span class="metadata-value">{{capitalize form_type}}</span>
|
||||
</div>
|
||||
{{#if ip_address}}
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">IP Address:</span>
|
||||
<span class="metadata-value">{{ip_address}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if user_agent}}
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">User Agent:</span>
|
||||
<span class="metadata-value">{{truncate user_agent 100}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>This email was generated automatically from your website contact form.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
181
templates/email/en_/html/notification.hbs
Normal file
181
templates/email/en_/html/notification.hbs
Normal file
@ -0,0 +1,181 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{title}}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
|
||||
color: white;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.header .icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.content {
|
||||
padding: 30px;
|
||||
}
|
||||
.message {
|
||||
background-color: #f8f9fa;
|
||||
border-left: 4px solid #007bff;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
.message p {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.additional-content {
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.additional-content h3 {
|
||||
margin: 0 0 15px 0;
|
||||
color: #495057;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.additional-content .content-body {
|
||||
color: #212529;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.footer {
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
.footer p {
|
||||
margin: 0;
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
.timestamp {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #dee2e6;
|
||||
text-align: center;
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
.alert {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.alert-info {
|
||||
color: #0c5460;
|
||||
background-color: #d1ecf1;
|
||||
border-color: #bee5eb;
|
||||
}
|
||||
.alert-warning {
|
||||
color: #856404;
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffeaa7;
|
||||
}
|
||||
.alert-success {
|
||||
color: #155724;
|
||||
background-color: #d4edda;
|
||||
border-color: #c3e6cb;
|
||||
}
|
||||
.alert-danger {
|
||||
color: #721c24;
|
||||
background-color: #f8d7da;
|
||||
border-color: #f5c6cb;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
.header, .content {
|
||||
padding: 20px;
|
||||
}
|
||||
.header h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.header .icon {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="icon">🔔</div>
|
||||
<h1>{{title}}</h1>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{#if type}}
|
||||
<div class="alert alert-{{type}}">
|
||||
<strong>{{capitalize type}}:</strong> This is a {{type}} notification.
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="message">
|
||||
<p>{{message}}</p>
|
||||
</div>
|
||||
|
||||
{{#if content}}
|
||||
<div class="additional-content">
|
||||
<h3>Additional Information</h3>
|
||||
<div class="content-body">
|
||||
{{{content}}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if action_url}}
|
||||
<div style="text-align: center; margin: 30px 0;">
|
||||
<a href="{{action_url}}" style="display: inline-block; padding: 12px 24px; background-color: #007bff; color: white; text-decoration: none; border-radius: 6px; font-weight: 600;">
|
||||
{{default action_text "Take Action"}}
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="timestamp">
|
||||
<p>Sent on {{date_format (default timestamp "now") "%B %d, %Y at %I:%M %p UTC"}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>This is an automated notification. Please do not reply to this email.</p>
|
||||
{{#if unsubscribe_url}}
|
||||
<p style="margin-top: 10px;">
|
||||
<a href="{{unsubscribe_url}}" style="color: #6c757d; font-size: 12px;">Unsubscribe from notifications</a>
|
||||
</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
32
templates/email/en_/text/contact.hbs
Normal file
32
templates/email/en_/text/contact.hbs
Normal file
@ -0,0 +1,32 @@
|
||||
=== CONTACT FORM SUBMISSION ===
|
||||
|
||||
You have received a new message from your website contact form.
|
||||
|
||||
CONTACT DETAILS:
|
||||
Name: {{name}}
|
||||
Email: {{email}}
|
||||
Subject: {{subject}}
|
||||
|
||||
MESSAGE:
|
||||
{{message}}
|
||||
|
||||
{{#if fields}}
|
||||
ADDITIONAL INFORMATION:
|
||||
{{#each fields}}
|
||||
{{@key}}: {{this}}
|
||||
{{/each}}
|
||||
|
||||
{{/if}}
|
||||
SUBMISSION DETAILS:
|
||||
Submitted: {{date_format submitted_at "%B %d, %Y at %I:%M %p UTC"}}
|
||||
Form Type: {{capitalize form_type}}
|
||||
{{#if ip_address}}
|
||||
IP Address: {{ip_address}}
|
||||
{{/if}}
|
||||
{{#if user_agent}}
|
||||
User Agent: {{truncate user_agent 100}}
|
||||
{{/if}}
|
||||
|
||||
---
|
||||
This email was generated automatically from your website contact form.
|
||||
To reply to the sender, use their email address: {{email}}
|
29
templates/email/en_/text/notification.hbs
Normal file
29
templates/email/en_/text/notification.hbs
Normal file
@ -0,0 +1,29 @@
|
||||
=== NOTIFICATION ===
|
||||
|
||||
{{title}}
|
||||
|
||||
{{#if type}}
|
||||
[{{uppercase type}}] This is a {{type}} notification.
|
||||
{{/if}}
|
||||
|
||||
{{message}}
|
||||
|
||||
{{#if content}}
|
||||
|
||||
ADDITIONAL INFORMATION:
|
||||
{{content}}
|
||||
{{/if}}
|
||||
|
||||
{{#if action_url}}
|
||||
|
||||
ACTION REQUIRED:
|
||||
{{default action_text "Take Action"}}: {{action_url}}
|
||||
{{/if}}
|
||||
|
||||
---
|
||||
Sent on {{date_format (default timestamp "now") "%B %d, %Y at %I:%M %p UTC"}}
|
||||
|
||||
This is an automated notification. Please do not reply to this email.
|
||||
{{#if unsubscribe_url}}
|
||||
To unsubscribe from notifications, visit: {{unsubscribe_url}}
|
||||
{{/if}}
|
217
templates/email/es_/html/contact.hbs
Normal file
217
templates/email/es_/html/contact.hbs
Normal file
@ -0,0 +1,217 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Formulario de Contacto Recibido</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.header p {
|
||||
margin: 10px 0 0 0;
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
}
|
||||
.content {
|
||||
padding: 30px;
|
||||
}
|
||||
.field {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
border-left: 4px solid #667eea;
|
||||
}
|
||||
.field-label {
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.field-value {
|
||||
color: #212529;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.message-field {
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.message-field .field-value {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.metadata {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #dee2e6;
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.metadata h3 {
|
||||
margin: 0 0 15px 0;
|
||||
color: #495057;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.metadata-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.metadata-label {
|
||||
color: #6c757d;
|
||||
font-weight: 500;
|
||||
}
|
||||
.metadata-value {
|
||||
color: #495057;
|
||||
}
|
||||
.footer {
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
.footer p {
|
||||
margin: 0;
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
.highlight {
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
padding: 15px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.highlight strong {
|
||||
color: #856404;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
.header, .content {
|
||||
padding: 20px;
|
||||
}
|
||||
.metadata-item {
|
||||
flex-direction: column;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.metadata-label {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>📧 Nuevo Formulario de Contacto</h1>
|
||||
<p>Has recibido un nuevo mensaje desde tu sitio web</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="highlight">
|
||||
<strong>Responde directamente a este correo</strong> para contestar al remitente, o usa la información de contacto a continuación.
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Nombre</div>
|
||||
<div class="field-value">{{name}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Dirección de Correo</div>
|
||||
<div class="field-value">
|
||||
<a href="mailto:{{email}}" style="color: #667eea; text-decoration: none;">{{email}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Asunto</div>
|
||||
<div class="field-value">{{subject}}</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-label">Mensaje</div>
|
||||
<div class="message-field">
|
||||
<div class="field-value">{{message}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if fields}}
|
||||
<div class="field">
|
||||
<div class="field-label">Información Adicional</div>
|
||||
<div style="margin-top: 10px;">
|
||||
{{#each fields}}
|
||||
<div style="margin-bottom: 10px; padding: 10px; background-color: #fff; border-radius: 4px; border-left: 3px solid #28a745;">
|
||||
<strong>{{@key}}:</strong> {{this}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="metadata">
|
||||
<h3>Detalles del Envío</h3>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Enviado:</span>
|
||||
<span class="metadata-value">{{date_format submitted_at "%d de %B de %Y a las %H:%M UTC"}}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Tipo de Formulario:</span>
|
||||
<span class="metadata-value">{{capitalize form_type}}</span>
|
||||
</div>
|
||||
{{#if ip_address}}
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Dirección IP:</span>
|
||||
<span class="metadata-value">{{ip_address}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if user_agent}}
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Navegador:</span>
|
||||
<span class="metadata-value">{{truncate user_agent 100}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>Este correo fue generado automáticamente desde el formulario de contacto de tu sitio web.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
181
templates/email/es_/html/notification.hbs
Normal file
181
templates/email/es_/html/notification.hbs
Normal file
@ -0,0 +1,181 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{title}}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
|
||||
color: white;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.header .icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.content {
|
||||
padding: 30px;
|
||||
}
|
||||
.message {
|
||||
background-color: #f8f9fa;
|
||||
border-left: 4px solid #007bff;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
.message p {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.additional-content {
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.additional-content h3 {
|
||||
margin: 0 0 15px 0;
|
||||
color: #495057;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.additional-content .content-body {
|
||||
color: #212529;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.footer {
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
.footer p {
|
||||
margin: 0;
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
.timestamp {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #dee2e6;
|
||||
text-align: center;
|
||||
color: #6c757d;
|
||||
font-size: 14px;
|
||||
}
|
||||
.alert {
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.alert-info {
|
||||
color: #0c5460;
|
||||
background-color: #d1ecf1;
|
||||
border-color: #bee5eb;
|
||||
}
|
||||
.alert-warning {
|
||||
color: #856404;
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffeaa7;
|
||||
}
|
||||
.alert-success {
|
||||
color: #155724;
|
||||
background-color: #d4edda;
|
||||
border-color: #c3e6cb;
|
||||
}
|
||||
.alert-danger {
|
||||
color: #721c24;
|
||||
background-color: #f8d7da;
|
||||
border-color: #f5c6cb;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
.header, .content {
|
||||
padding: 20px;
|
||||
}
|
||||
.header h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.header .icon {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="icon">🔔</div>
|
||||
<h1>{{title}}</h1>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{{#if type}}
|
||||
<div class="alert alert-{{type}}">
|
||||
<strong>{{capitalize type}}:</strong> Esta es una notificación {{type}}.
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="message">
|
||||
<p>{{message}}</p>
|
||||
</div>
|
||||
|
||||
{{#if content}}
|
||||
<div class="additional-content">
|
||||
<h3>Información Adicional</h3>
|
||||
<div class="content-body">
|
||||
{{{content}}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if action_url}}
|
||||
<div style="text-align: center; margin: 30px 0;">
|
||||
<a href="{{action_url}}" style="display: inline-block; padding: 12px 24px; background-color: #007bff; color: white; text-decoration: none; border-radius: 6px; font-weight: 600;">
|
||||
{{default action_text "Tomar Acción"}}
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="timestamp">
|
||||
<p>Enviado el {{date_format (default timestamp "now") "%d de %B de %Y a las %H:%M UTC"}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>Esta es una notificación automática. Por favor no respondas a este correo.</p>
|
||||
{{#if unsubscribe_url}}
|
||||
<p style="margin-top: 10px;">
|
||||
<a href="{{unsubscribe_url}}" style="color: #6c757d; font-size: 12px;">Cancelar suscripción de notificaciones</a>
|
||||
</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
32
templates/email/es_/text/contact.hbs
Normal file
32
templates/email/es_/text/contact.hbs
Normal file
@ -0,0 +1,32 @@
|
||||
=== FORMULARIO DE CONTACTO ===
|
||||
|
||||
Has recibido un nuevo mensaje desde el formulario de contacto de tu sitio web.
|
||||
|
||||
DETALLES DEL CONTACTO:
|
||||
Nombre: {{name}}
|
||||
Correo: {{email}}
|
||||
Asunto: {{subject}}
|
||||
|
||||
MENSAJE:
|
||||
{{message}}
|
||||
|
||||
{{#if fields}}
|
||||
INFORMACIÓN ADICIONAL:
|
||||
{{#each fields}}
|
||||
{{@key}}: {{this}}
|
||||
{{/each}}
|
||||
|
||||
{{/if}}
|
||||
DETALLES DEL ENVÍO:
|
||||
Enviado: {{date_format submitted_at "%d de %B de %Y a las %H:%M UTC"}}
|
||||
Tipo de Formulario: {{capitalize form_type}}
|
||||
{{#if ip_address}}
|
||||
Dirección IP: {{ip_address}}
|
||||
{{/if}}
|
||||
{{#if user_agent}}
|
||||
Navegador: {{truncate user_agent 100}}
|
||||
{{/if}}
|
||||
|
||||
---
|
||||
Este correo fue generado automáticamente desde el formulario de contacto de tu sitio web.
|
||||
Para responder al remitente, usa su dirección de correo: {{email}}
|
29
templates/email/es_/text/notification.hbs
Normal file
29
templates/email/es_/text/notification.hbs
Normal file
@ -0,0 +1,29 @@
|
||||
=== NOTIFICACIÓN ===
|
||||
|
||||
{{title}}
|
||||
|
||||
{{#if type}}
|
||||
[{{uppercase type}}] Esta es una notificación {{type}}.
|
||||
{{/if}}
|
||||
|
||||
{{message}}
|
||||
|
||||
{{#if content}}
|
||||
|
||||
INFORMACIÓN ADICIONAL:
|
||||
{{content}}
|
||||
{{/if}}
|
||||
|
||||
{{#if action_url}}
|
||||
|
||||
ACCIÓN REQUERIDA:
|
||||
{{default action_text "Tomar Acción"}}: {{action_url}}
|
||||
{{/if}}
|
||||
|
||||
---
|
||||
Enviado el {{date_format (default timestamp "now") "%d de %B de %Y a las %H:%M UTC"}}
|
||||
|
||||
Esta es una notificación automática. Por favor no respondas a este correo.
|
||||
{{#if unsubscribe_url}}
|
||||
Para cancelar la suscripción de notificaciones, visita: {{unsubscribe_url}}
|
||||
{{/if}}
|
361
templates/page.html
Normal file
361
templates/page.html
Normal file
@ -0,0 +1,361 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{lang | default(value='en')}}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{title}} - {{site_name | default(value="My Website")}}</title>
|
||||
<meta name="description" content="{{description | default(value=content | excerpt(length=160))}}">
|
||||
{% if author %}
|
||||
<meta name="author" content="{{author}}">
|
||||
{% endif %}
|
||||
{% if keywords %}
|
||||
<meta name="keywords" content="{{keywords | join(sep=', ')}}">
|
||||
{% endif %}
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 2rem 0;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
.header h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
.header .subtitle {
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.9;
|
||||
font-weight: 300;
|
||||
}
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.main-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 300px;
|
||||
gap: 40px;
|
||||
margin: 40px auto;
|
||||
max-width: 1200px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.content {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
||||
min-height: 400px;
|
||||
}
|
||||
.content h2 {
|
||||
color: #2c3e50;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.8rem;
|
||||
border-bottom: 2px solid #3498db;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.content h3 {
|
||||
color: #34495e;
|
||||
margin: 30px 0 15px 0;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.content p {
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.content ul, .content ol {
|
||||
margin-bottom: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
.content li {
|
||||
margin-bottom: 8px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.content blockquote {
|
||||
border-left: 4px solid #3498db;
|
||||
padding-left: 20px;
|
||||
margin: 20px 0;
|
||||
font-style: italic;
|
||||
color: #555;
|
||||
}
|
||||
.content code {
|
||||
background: #f8f9fa;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-family: 'Consolas', 'Monaco', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.content pre {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
overflow-x: auto;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.content pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
.sidebar {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
||||
height: fit-content;
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
}
|
||||
.sidebar h3 {
|
||||
color: #2c3e50;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.3rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
.sidebar li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.sidebar a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
.sidebar a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.meta-info {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
}
|
||||
.meta-info strong {
|
||||
color: #333;
|
||||
}
|
||||
.breadcrumbs {
|
||||
background: #f8f9fa;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.breadcrumbs a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.breadcrumbs a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.breadcrumbs span {
|
||||
color: #666;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.footer {
|
||||
background: #2c3e50;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
margin-top: 60px;
|
||||
}
|
||||
.footer p {
|
||||
margin-bottom: 10px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.footer a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
}
|
||||
.footer a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
|
||||
color: white;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
margin: 40px 0;
|
||||
}
|
||||
.cta-section h3 {
|
||||
font-size: 1.8rem;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.cta-section p {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 25px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.cta-button {
|
||||
display: inline-block;
|
||||
background: white;
|
||||
color: #3498db;
|
||||
padding: 15px 30px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.cta-button:hover {
|
||||
background: #f8f9fa;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.main-content {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
margin: 20px auto;
|
||||
padding: 0 15px;
|
||||
}
|
||||
.content, .sidebar {
|
||||
padding: 20px;
|
||||
}
|
||||
.header h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.header .subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{% if breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<div class="container">
|
||||
{% for crumb in breadcrumbs %}
|
||||
{% if not loop.last %}
|
||||
<a href="{{crumb.url}}">{{crumb.title}}</a>
|
||||
<span>></span>
|
||||
{% else %}
|
||||
<span>{{crumb.title}}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<h1>{{title}}</h1>
|
||||
{% if subtitle %}
|
||||
<p class="subtitle">{{subtitle}}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main-content">
|
||||
<main class="content">
|
||||
{% if show_meta %}
|
||||
<div class="meta-info">
|
||||
{% if last_updated %}
|
||||
<strong>Last Updated:</strong> {{last_updated | date_format(format="%B %d, %Y")}}
|
||||
{% endif %}
|
||||
{% if author %}
|
||||
<br><strong>Author:</strong> {{author}}
|
||||
{% endif %}
|
||||
{% if reading_time %}
|
||||
<br><strong>Reading Time:</strong> {{reading_time}} minutes
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if featured_image %}
|
||||
<img src="{{featured_image}}" alt="{{title}}" style="width: 100%; height: auto; margin-bottom: 30px; border-radius: 5px;">
|
||||
{% endif %}
|
||||
|
||||
{{content | markdown | safe}}
|
||||
|
||||
{% if cta_enabled %}
|
||||
<div class="cta-section">
|
||||
<h3>{{cta_title | default(value="Ready to Get Started?")}}</h3>
|
||||
<p>{{cta_description | default(value="Take the next step and explore what we have to offer.")}}</p>
|
||||
<a href="{{cta_url | default(value='/contact')}}" class="cta-button">{{cta_button_text | default(value="Get Started")}}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</main>
|
||||
|
||||
<aside class="sidebar">
|
||||
{% if toc_enabled and toc %}
|
||||
<h3>Table of Contents</h3>
|
||||
<ul>
|
||||
{% for item in toc %}
|
||||
<li><a href="#{{item.anchor}}">{{item.title}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if sidebar_links %}
|
||||
<h3>{{sidebar_title | default(value="Quick Links")}}</h3>
|
||||
<ul>
|
||||
{% for link in sidebar_links %}
|
||||
<li><a href="{{link.url}}">{{link.title}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if contact_info %}
|
||||
<h3>Contact Information</h3>
|
||||
<div class="meta-info">
|
||||
{% if contact_info.email %}
|
||||
<strong>Email:</strong> <a href="mailto:{{contact_info.email}}">{{contact_info.email}}</a><br>
|
||||
{% endif %}
|
||||
{% if contact_info.phone %}
|
||||
<strong>Phone:</strong> {{contact_info.phone}}<br>
|
||||
{% endif %}
|
||||
{% if contact_info.address %}
|
||||
<strong>Address:</strong> {{contact_info.address}}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if related_pages %}
|
||||
<h3>Related Pages</h3>
|
||||
<ul>
|
||||
{% for page in related_pages %}
|
||||
<li><a href="{{page.url}}">{{page.title}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p>© {{current_year | default(value="2024")}} {{site_name | default(value="My Website")}}. All rights reserved.</p>
|
||||
{% if footer_links %}
|
||||
<p>
|
||||
{% for link in footer_links %}
|
||||
<a href="{{link.url}}">{{link.title}}</a>
|
||||
{% if not loop.last %} | {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{% if analytics_id %}
|
||||
<script>
|
||||
// Add analytics tracking here if needed
|
||||
console.log('Analytics ID: {{analytics_id}}');
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user