fix(i18n): enable translations in all templates and implement cookie-based language persistence
- Add _() translation function to add_tablet.html, add_user.html, loan_tablet.html - Add _() translation function to add_non_loanable_device.html, edit_non_loanable_device.html - Add _() translation function to history.html, non_loanable_devices.html, project_management.html - Update app.py to use cookie-based language persistence with 1-year expiry - Add /set_language endpoint to handle language switching with cookie + session - Update language switcher in base.html to use new endpoint - Set Spanish (es) as default language for internal app - Import make_response and session from Flask
This commit is contained in:
parent
8c1d12a5c4
commit
2248237c79
10 changed files with 133 additions and 107 deletions
36
app.py
36
app.py
|
|
@ -4,7 +4,7 @@ Simple Tablet Lending and Return Management Web Application
|
|||
with SQLite backend
|
||||
"""
|
||||
|
||||
from flask import Flask, render_template, request, redirect, url_for, flash
|
||||
from flask import Flask, render_template, request, redirect, url_for, flash, make_response, session
|
||||
import sqlite3
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
|
@ -25,15 +25,41 @@ app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'translations'
|
|||
|
||||
# Locale selector function
|
||||
def get_locale():
|
||||
# Try to get language from URL parameter
|
||||
lang = request.args.get('lang')
|
||||
# Try to get language from cookie
|
||||
lang = request.cookies.get('language')
|
||||
if lang and lang in app.config['LANGUAGES']:
|
||||
return lang
|
||||
# Try to get from session
|
||||
if hasattr(request, 'session') and 'language' in request.session:
|
||||
return request.session['language']
|
||||
# Try to get from browser preferences
|
||||
return request.accept_languages.best_match(app.config['LANGUAGES'].keys())
|
||||
# Default to Spanish (es) for internal app
|
||||
return 'es'
|
||||
|
||||
|
||||
# Before request handler to set language from URL param and persist to cookie/session
|
||||
@app.before_request
|
||||
def handle_language():
|
||||
lang = request.args.get('lang')
|
||||
if lang and lang in app.config['LANGUAGES']:
|
||||
# Store in session
|
||||
session['language'] = lang
|
||||
# Set cookie for longer persistence (1 year)
|
||||
# Note: We need to use response.set_cookie, but before_request can't modify response
|
||||
# So we'll handle this in a separate route
|
||||
return None
|
||||
|
||||
|
||||
# Language switcher endpoint
|
||||
@app.route('/set_language')
|
||||
def set_language():
|
||||
lang = request.args.get('lang')
|
||||
if lang and lang in app.config['LANGUAGES']:
|
||||
session['language'] = lang
|
||||
# Set cookie
|
||||
resp = make_response(redirect(request.referrer or '/'))
|
||||
resp.set_cookie('language', lang, max_age=31536000) # 1 year
|
||||
return resp
|
||||
return redirect(request.referrer or '/')
|
||||
|
||||
# Initialize Babel with locale selector
|
||||
babel = Babel(app, locale_selector=get_locale)
|
||||
|
|
|
|||
|
|
@ -1,63 +1,63 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Add Non-Loanable Device</h2>
|
||||
<p>Add a device that will be tracked in inventory but cannot be loaned to users (e.g., projectors, monitors, etc.)</p>
|
||||
<h2>{{ _('Add Non-Loanable Device') }}</h2>
|
||||
<p>{{ _('Add a device that will be tracked in inventory but cannot be loaned to users (e.g., projectors, monitors, etc.)') }}</p>
|
||||
|
||||
<form method="POST" action="/add_non_loanable_device">
|
||||
<div class="form-group">
|
||||
<label for="device_type">Device Type:</label>
|
||||
<label for="device_type">{{ _('Device Type') }}:</label>
|
||||
<select id="device_type" name="device_type" required>
|
||||
<option value="">Select device type...</option>
|
||||
<option value="projector">Projector</option>
|
||||
<option value="monitor">Monitor</option>
|
||||
<option value="laptop">Laptop (non-loanable)</option>
|
||||
<option value="printer">Printer</option>
|
||||
<option value="camera">Camera</option>
|
||||
<option value="audio">Audio Equipment</option>
|
||||
<option value="network">Network Equipment</option>
|
||||
<option value="other">Other</option>
|
||||
<option value="">{{ _('Select device type...') }}</option>
|
||||
<option value="projector">{{ _('Projector') }}</option>
|
||||
<option value="monitor">{{ _('Monitor') }}</option>
|
||||
<option value="laptop">{{ _('Laptop (non-loanable)') }}</option>
|
||||
<option value="printer">{{ _('Printer') }}</option>
|
||||
<option value="camera">{{ _('Camera') }}</option>
|
||||
<option value="audio">{{ _('Audio Equipment') }}</option>
|
||||
<option value="network">{{ _('Network Equipment') }}</option>
|
||||
<option value="other">{{ _('Other') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="brand">Brand:</label>
|
||||
<label for="brand">{{ _('Brand') }}:</label>
|
||||
<input type="text" id="brand" name="brand" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="model">Model:</label>
|
||||
<label for="model">{{ _('Model') }}:</label>
|
||||
<input type="text" id="model" name="model" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="serial_number">Serial Number:</label>
|
||||
<label for="serial_number">{{ _('Serial Number') }}:</label>
|
||||
<input type="text" id="serial_number" name="serial_number" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="location">Location:</label>
|
||||
<label for="location">{{ _('Location') }}:</label>
|
||||
<input type="text" id="location" name="location">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="purchase_date">Purchase Date:</label>
|
||||
<label for="purchase_date">{{ _('Purchase Date') }}:</label>
|
||||
<input type="date" id="purchase_date" name="purchase_date">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="purchase_cost">Purchase Cost:</label>
|
||||
<label for="purchase_cost">{{ _('Purchase Cost') }}:</label>
|
||||
<input type="number" id="purchase_cost" name="purchase_cost" step="0.01">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="notes">Notes:</label>
|
||||
<label for="notes">{{ _('Notes') }}:</label>
|
||||
<textarea id="notes" name="notes"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn">Add Device</button>
|
||||
<a href="/non_loanable_devices" class="btn">Cancel</a>
|
||||
<button type="submit" class="btn">{{ _('Add Device') }}</button>
|
||||
<a href="/non_loanable_devices" class="btn">{{ _('Cancel') }}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Add New Tablet</h2>
|
||||
<h2>{{ _('Add New Tablet') }}</h2>
|
||||
<form method="POST" action="/add_tablet">
|
||||
<div class="form-group">
|
||||
<label for="brand">Brand:</label>
|
||||
<label for="brand">{{ _('Brand') }}:</label>
|
||||
<input type="text" id="brand" name="brand" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="model">Model:</label>
|
||||
<label for="model">{{ _('Model') }}:</label>
|
||||
<input type="text" id="model" name="model" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="serial_number">Serial Number:</label>
|
||||
<label for="serial_number">{{ _('Serial Number') }}:</label>
|
||||
<input type="text" id="serial_number" name="serial_number" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="notes">Notes:</label>
|
||||
<label for="notes">{{ _('Notes') }}:</label>
|
||||
<textarea id="notes" name="notes"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn">Add Tablet</button>
|
||||
<button type="submit" class="btn">{{ _('Add Tablet') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -1,30 +1,30 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Add New User</h2>
|
||||
<h2>{{ _('Add New User') }}</h2>
|
||||
<form method="POST" action="/add_user">
|
||||
<div class="form-group">
|
||||
<label for="name">Name:</label>
|
||||
<label for="name">{{ _('Name') }}:</label>
|
||||
<input type="text" id="name" name="name" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email">Email:</label>
|
||||
<label for="email">{{ _('Email') }}:</label>
|
||||
<input type="email" id="email" name="email">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="phone">Phone:</label>
|
||||
<label for="phone">{{ _('Phone') }}:</label>
|
||||
<input type="text" id="phone" name="phone">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="identification">Identification:</label>
|
||||
<label for="identification">{{ _('Identification') }}:</label>
|
||||
<input type="text" id="identification" name="identification" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn">Add User</button>
|
||||
<button type="submit" class="btn">{{ _('Add User') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -122,7 +122,7 @@
|
|||
<span class="text-sm opacity-80">{{ _('Language') }}:</span>
|
||||
{% for lang_code, lang_name in config['LANGUAGES'].items() %}
|
||||
<a
|
||||
href="?lang={{ lang_code }}"
|
||||
href="{{ url_for('set_language', lang=lang_code) }}"
|
||||
class="px-2 py-1 text-sm rounded hover:bg-white/20 transition-colors
|
||||
{% if language == lang_code %}bg-white/30 font-medium{% endif %}"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,71 +1,71 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Edit Non-Loanable Device</h2>
|
||||
<h2>{{ _('Edit Non-Loanable Device') }}</h2>
|
||||
|
||||
<form method="POST" action="/edit_non_loanable_device/{{ device.id }}">
|
||||
<div class="form-group">
|
||||
<label for="device_type">Device Type:</label>
|
||||
<label for="device_type">{{ _('Device Type') }}:</label>
|
||||
<select id="device_type" name="device_type" required>
|
||||
<option value="projector" {% if device.device_type == 'projector' %}selected{% endif %}>Projector</option>
|
||||
<option value="monitor" {% if device.device_type == 'monitor' %}selected{% endif %}>Monitor</option>
|
||||
<option value="laptop" {% if device.device_type == 'laptop' %}selected{% endif %}>Laptop (non-loanable)</option>
|
||||
<option value="printer" {% if device.device_type == 'printer' %}selected{% endif %}>Printer</option>
|
||||
<option value="camera" {% if device.device_type == 'camera' %}selected{% endif %}>Camera</option>
|
||||
<option value="audio" {% if device.device_type == 'audio' %}selected{% endif %}>Audio Equipment</option>
|
||||
<option value="network" {% if device.device_type == 'network' %}selected{% endif %}>Network Equipment</option>
|
||||
<option value="other" {% if device.device_type == 'other' %}selected{% endif %}>Other</option>
|
||||
<option value="projector" {% if device.device_type == 'projector' %}selected{% endif %}>{{ _('Projector') }}</option>
|
||||
<option value="monitor" {% if device.device_type == 'monitor' %}selected{% endif %}>{{ _('Monitor') }}</option>
|
||||
<option value="laptop" {% if device.device_type == 'laptop' %}selected{% endif %}>{{ _('Laptop (non-loanable)') }}</option>
|
||||
<option value="printer" {% if device.device_type == 'printer' %}selected{% endif %}>{{ _('Printer') }}</option>
|
||||
<option value="camera" {% if device.device_type == 'camera' %}selected{% endif %}>{{ _('Camera') }}</option>
|
||||
<option value="audio" {% if device.device_type == 'audio' %}selected{% endif %}>{{ _('Audio Equipment') }}</option>
|
||||
<option value="network" {% if device.device_type == 'network' %}selected{% endif %}>{{ _('Network Equipment') }}</option>
|
||||
<option value="other" {% if device.device_type == 'other' %}selected{% endif %}>{{ _('Other') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="brand">Brand:</label>
|
||||
<label for="brand">{{ _('Brand') }}:</label>
|
||||
<input type="text" id="brand" name="brand" value="{{ device.brand }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="model">Model:</label>
|
||||
<label for="model">{{ _('Model') }}:</label>
|
||||
<input type="text" id="model" name="model" value="{{ device.model }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="serial_number">Serial Number:</label>
|
||||
<label for="serial_number">{{ _('Serial Number') }}:</label>
|
||||
<input type="text" id="serial_number" name="serial_number" value="{{ device.serial_number }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="location">Location:</label>
|
||||
<label for="location">{{ _('Location') }}:</label>
|
||||
<input type="text" id="location" name="location" value="{{ device.location or '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Status:</label>
|
||||
<label for="status">{{ _('Status') }}:</label>
|
||||
<select id="status" name="status" required>
|
||||
<option value="available" {% if device.status == 'available' %}selected{% endif %}>Available</option>
|
||||
<option value="in_use" {% if device.status == 'in_use' %}selected{% endif %}>In Use</option>
|
||||
<option value="maintenance" {% if device.status == 'maintenance' %}selected{% endif %}>Maintenance</option>
|
||||
<option value="retired" {% if device.status == 'retired' %}selected{% endif %}>Retired</option>
|
||||
<option value="available" {% if device.status == 'available' %}selected{% endif %}>{{ _('Available') }}</option>
|
||||
<option value="in_use" {% if device.status == 'in_use' %}selected{% endif %}>{{ _('In Use') }}</option>
|
||||
<option value="maintenance" {% if device.status == 'maintenance' %}selected{% endif %}>{{ _('Maintenance') }}</option>
|
||||
<option value="retired" {% if device.status == 'retired' %}selected{% endif %}>{{ _('Retired') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="purchase_date">Purchase Date:</label>
|
||||
<label for="purchase_date">{{ _('Purchase Date') }}:</label>
|
||||
<input type="date" id="purchase_date" name="purchase_date" value="{{ device.purchase_date or '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="purchase_cost">Purchase Cost:</label>
|
||||
<label for="purchase_cost">{{ _('Purchase Cost') }}:</label>
|
||||
<input type="number" id="purchase_cost" name="purchase_cost" step="0.01" value="{{ device.purchase_cost or '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="notes">Notes:</label>
|
||||
<label for="notes">{{ _('Notes') }}:</label>
|
||||
<textarea id="notes" name="notes">{{ device.notes or '' }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn">Update Device</button>
|
||||
<a href="/non_loanable_devices" class="btn">Cancel</a>
|
||||
<button type="submit" class="btn">{{ _('Update Device') }}</button>
|
||||
<a href="/non_loanable_devices" class="btn">{{ _('Cancel') }}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="section">
|
||||
<h2>Loan History</h2>
|
||||
<h2>{{ _('Loan History') }}</h2>
|
||||
{% if loans %}
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tablet</th>
|
||||
<th>Serial Number</th>
|
||||
<th>Borrower</th>
|
||||
<th>Loan Date</th>
|
||||
<th>Return Date</th>
|
||||
<th>Status</th>
|
||||
<th>{{ _('Tablet') }}</th>
|
||||
<th>{{ _('Serial Number') }}</th>
|
||||
<th>{{ _('Borrower') }}</th>
|
||||
<th>{{ _('Loan Date') }}</th>
|
||||
<th>{{ _('Return Date') }}</th>
|
||||
<th>{{ _('Status') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>No loan history available.</p>
|
||||
<p>{{ _('No loan history available.') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Loan Tablet</h2>
|
||||
<h2>{{ _('Loan Tablet') }}</h2>
|
||||
<form method="POST" action="/loan_tablet">
|
||||
<!-- Tablet Selection with Search -->
|
||||
<div class="form-group">
|
||||
<label for="tablet_id">Tablet:</label>
|
||||
<label for="tablet_id">{{ _('Tablet') }}:</label>
|
||||
<input type="text" id="tablet_search" class="search-input"
|
||||
placeholder="Search tablets (brand, model, or serial)..."
|
||||
placeholder="{{ _('Search tablets (brand, model, or serial)...') }}"
|
||||
onkeyup="filterDropdown('tablet_search', 'tablet_id')">
|
||||
<select id="tablet_id" name="tablet_id" required size="5">
|
||||
<option value="">Select a tablet</option>
|
||||
<option value="">{{ _('Select a tablet') }}</option>
|
||||
{% for tablet in available_tablets %}
|
||||
<option value="{{ tablet.id }}"
|
||||
data-search="{{ tablet.brand|lower }} {{ tablet.model|lower }} {{ tablet.serial_number|lower }}">
|
||||
|
|
@ -22,12 +22,12 @@
|
|||
|
||||
<!-- User Selection with Search -->
|
||||
<div class="form-group">
|
||||
<label for="user_id">User:</label>
|
||||
<label for="user_id">{{ _('User') }}:</label>
|
||||
<input type="text" id="user_search" class="search-input"
|
||||
placeholder="Search users (name or ID)..."
|
||||
placeholder="{{ _('Search users (name or ID)...') }}"
|
||||
onkeyup="filterDropdown('user_search', 'user_id')">
|
||||
<select id="user_id" name="user_id" required size="5">
|
||||
<option value="">Select a user</option>
|
||||
<option value="">{{ _('Select a user') }}</option>
|
||||
{% for user in users %}
|
||||
<option value="{{ user.id }}"
|
||||
data-search="{{ user.name|lower }} {{ user.identification|lower }}">
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn">Loan Tablet</button>
|
||||
<button type="submit" class="btn">{{ _('Loan Tablet') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="section">
|
||||
<h2>Non-Loanable Devices Inventory</h2>
|
||||
<p>These devices are tracked in inventory but cannot be loaned to users.</p>
|
||||
<a href="/add_non_loanable_device" class="btn">Add Non-Loanable Device</a>
|
||||
<h2>{{ _('Non-Loanable Devices Inventory') }}</h2>
|
||||
<p>{{ _('These devices are tracked in inventory but cannot be loaned to users.') }}</p>
|
||||
<a href="/add_non_loanable_device" class="btn">{{ _('Add Non-Loanable Device') }}</a>
|
||||
|
||||
{% if devices %}
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Brand</th>
|
||||
<th>Model</th>
|
||||
<th>Serial Number</th>
|
||||
<th>Location</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
<th>{{ _('Type') }}</th>
|
||||
<th>{{ _('Brand') }}</th>
|
||||
<th>{{ _('Model') }}</th>
|
||||
<th>{{ _('Serial Number') }}</th>
|
||||
<th>{{ _('Location') }}</th>
|
||||
<th>{{ _('Status') }}</th>
|
||||
<th>{{ _('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -30,8 +30,8 @@
|
|||
<td>{{ device.location or '-' }}</td>
|
||||
<td>{{ device.status }}</td>
|
||||
<td>
|
||||
<a href="/edit_non_loanable_device/{{ device.id }}" class="btn">Edit</a>
|
||||
<a href="/delete_non_loanable_device/{{ device.id }}" class="btn btn-danger" onclick="return confirm('Are you sure you want to delete this device?')">Delete</a>
|
||||
<a href="/edit_non_loanable_device/{{ device.id }}" class="btn">{{ _('Edit') }}</a>
|
||||
<a href="/delete_non_loanable_device/{{ device.id }}" class="btn btn-danger" onclick="return confirm('{{ _("Are you sure you want to delete this device?") }}')">{{ _('Delete') }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>No non-loanable devices registered.</p>
|
||||
<p>{{ _('No non-loanable devices registered.') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Project Management - Development Notes</h2>
|
||||
<h2>{{ _('Project Management - Development Notes') }}</h2>
|
||||
|
||||
<div class="project-management-container">
|
||||
<div class="editor-section">
|
||||
<div class="editor-controls">
|
||||
<button onclick="saveNotes()" class="btn">Save Notes</button>
|
||||
<button onclick="loadNotes()" class="btn">Reload</button>
|
||||
<button onclick="saveNotes()" class="btn">{{ _('Save Notes') }}</button>
|
||||
<button onclick="loadNotes()" class="btn">{{ _('Reload') }}</button>
|
||||
<span id="status" style="margin-left: 15px; font-style: italic;"></span>
|
||||
</div>
|
||||
|
||||
<div class="editor-row">
|
||||
<div class="editor-col">
|
||||
<h3>Editor</h3>
|
||||
<h3>{{ _('Editor') }}</h3>
|
||||
<textarea id="markdown-editor" class="markdown-editor"
|
||||
placeholder="Write your markdown notes here..."></textarea>
|
||||
placeholder="{{ _('Write your markdown notes here...') }}"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="editor-col">
|
||||
<h3>Preview</h3>
|
||||
<h3>{{ _('Preview') }}</h3>
|
||||
<div id="markdown-preview" class="markdown-preview"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -54,13 +54,13 @@
|
|||
.then(content => {
|
||||
document.getElementById('markdown-editor').value = content;
|
||||
document.getElementById('markdown-preview').innerHTML = marked.parse(content);
|
||||
document.getElementById('status').textContent = 'Loaded successfully';
|
||||
document.getElementById('status').textContent = '{{ _("Loaded successfully") }}';
|
||||
setTimeout(() => {
|
||||
document.getElementById('status').textContent = '';
|
||||
}, 2000);
|
||||
})
|
||||
.catch(error => {
|
||||
document.getElementById('status').textContent = 'Using default content';
|
||||
document.getElementById('status').textContent = '{{ _("Using default content") }}';
|
||||
setTimeout(() => {
|
||||
document.getElementById('status').textContent = '';
|
||||
}, 2000);
|
||||
|
|
@ -80,10 +80,10 @@
|
|||
})
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
statusEl.textContent = 'Saved successfully!';
|
||||
statusEl.textContent = '{{ _("Saved successfully!") }}';
|
||||
statusEl.style.color = '#4CAF50';
|
||||
} else {
|
||||
statusEl.textContent = 'Error saving';
|
||||
statusEl.textContent = '{{ _("Error saving") }}';
|
||||
statusEl.style.color = '#f44336';
|
||||
}
|
||||
setTimeout(() => {
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
}, 2000);
|
||||
})
|
||||
.catch(error => {
|
||||
statusEl.textContent = 'Error: ' + error.message;
|
||||
statusEl.textContent = '{{ _("Error") }}: ' + error.message;
|
||||
statusEl.style.color = '#f44336';
|
||||
setTimeout(() => {
|
||||
statusEl.textContent = '';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue