diff --git a/README.md b/README.md index 6b4576e..e1c0d36 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ CatNote is a minimalist web application that lets you generate Markdown-based receipts or notes, render them as PNGs, and send them directly to an MXW01 Cat Thermal Printer. Ideal for making quick, beautiful, and portable printed notes using Markdown, with optional image upload. -**Note:** The default UI is currently *only available in Spanish*, as this project began for my own use. Support for both English and Spanish is planned for a future release. - ## Features * Enter Markdown and preview output. diff --git a/app.py b/app.py index 48ffa05..140fe7c 100644 --- a/app.py +++ b/app.py @@ -3,11 +3,12 @@ import tempfile import subprocess import requests import base64 -from flask import Flask, render_template_string, request, send_from_directory, session +from flask import Flask, render_template, request, send_from_directory, session from PIL import Image, ImageDraw, ImageFont import os import re import argparse +import json app = Flask(__name__) app.secret_key = 'TpfxYMxUJxJMtCCTraBSg1rbd6NLz38JTmIfpBLsotcI47EqXU' @@ -24,562 +25,8 @@ BANNER_FONT_SIZE = 300 IMAGE_WIDTH = 384 BULLET_CHAR = "• " -DITHERING_MODES = { - "Sin dithering": "none", - "Floyd-Steinberg": "floyd", - "Bayer 2x2": "bayer2x2", - "Bayer 4x4": "bayer4x4", - "Bayer 8x8": "bayer8x8", - "Bayer 16x16": "bayer16x16", - "Atkinson": "atkinson", - "Jarvis-Judice-Ninke": "jjn" -} - -HTML_FORM = ''' - - - - CatNote - - - - -
-
-
-

😺 CatNote 🖨️

-
-
-
-
-
-
-
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
Imprimiendo...
-
-
-
-
-
-
- - -
-
- {% if printed %} -
✅ Enviado a impresora
- {% endif %} - {% if error %} -
⚠️ {{ error }}
- {% endif %} -
-
- {% if img %} -

Vista previa

- - {% else %} -

Su vista previa aparecerá aquí

- {% endif %} -
-
-

Referencia rápida de Markdown

- -
-
- - - -''' +with open('static/translations.json', 'r', encoding='utf-8') as f: + TRANSLATIONS = json.load(f) def remove_uploaded_img(): path = session.pop('uploaded_img_path', None) @@ -906,6 +353,20 @@ def index(): md = "" printed = False error = None + lang = request.args.get('lang') or session.get('lang', 'en') + session['lang'] = lang + t = TRANSLATIONS.get(lang, TRANSLATIONS['en']) + dithering_modes = { + t['no_dithering']: "none", + "Floyd-Steinberg": "floyd", + "Bayer 2x2": "bayer2x2", + "Bayer 4x4": "bayer4x4", + "Bayer 8x8": "bayer8x8", + "Bayer 16x16": "bayer16x16", + "Atkinson": "atkinson", + "Jarvis-Judice-Ninke": "jjn" + } + if request.method == "POST": userimg = request.files.get("userimg") uploaded_img_bytes = None @@ -977,8 +438,8 @@ def index(): printed = True except Exception as e: error = f"Failed to print: {e}" - return render_template_string(HTML_FORM, dithering_modes=DITHERING_MODES, img=img_data, default_md=md, - printed=printed, error=error, current_dithering=session.get('dithering', 'floyd'), current_rotation=session.get('rotation', 0), current_printmode=session.get('printmode', '1bpp'), current_bannermode=session.get('bannermode', False)) + return render_template("index.html", dithering_modes=dithering_modes, img=img_data, default_md=md, + printed=printed, error=error, current_dithering=session.get('dithering', 'floyd'), current_rotation=session.get('rotation', 0), current_printmode=session.get('printmode', '1bpp'), current_bannermode=session.get('bannermode', False), t=t, lang=lang) @app.route('/manifest.json') def manifest(): @@ -996,5 +457,4 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description='CatNote: Server for Markdown to MXW01 Cat Printer') parser.add_argument('-p', '--port', type=int, default=5000, help='Port to run the server on (default: 5000)') args = parser.parse_args() - app.run(host='0.0.0.0', port=args.port) - + app.run(host='0.0.0.0', port=args.port, debug=True) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2eacab7..8a3aec6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Flask markdown Pillow requests +json \ No newline at end of file diff --git a/static/translations.json b/static/translations.json new file mode 100644 index 0000000..9018fd2 --- /dev/null +++ b/static/translations.json @@ -0,0 +1,74 @@ +{ + "en": { + "catnote": "CatNote", + "enter_markdown_here": "Enter Markdown here...", + "upload_image_optional": "Upload image (optional):", + "banner_mode_vertical": "Banner Mode (vertical)", + "dithering": "Dithering:", + "intensity": "Intensity:", + "rotate_image": "Rotate image:", + "print_mode": "Print mode:", + "printing": "Printing...", + "sent_to_printer": "Sent to printer", + "preview": "Preview", + "your_preview_will_appear_here": "Your preview will appear here", + "quick_markdown_reference": "Quick Markdown Cheatsheet", + "bold": "Bold:", + "italic": "Italic:", + "bold_and_italic": "Bold and Italic:", + "large_header": "Large Header:", + "medium_header": "Medium Header:", + "small_header": "Small Header:", + "bullet_list": "Bullet List:", + "numbered_list": "Numbered List:", + "image": "Image:", + "line_break": "Line break:", + "uploaded_image": "Uploaded image:", + "generate_btn": "🖼️ Generate", + "print_btn": "🖨️ Print", + "text": "text", + "title": "Title", + "element": "Element", + "alt_text": "Alt text", + "image_url": "Image URL", + "leave_an_empty_line": "Leave an empty line", + "uses_the_uploaded_image": "(uses the uploaded image)", + "no_dithering": "No dithering" + }, + "es": { + "catnote": "CatNote", + "enter_markdown_here": "Ingrese Markdown aquí...", + "upload_image_optional": "Subir imagen (opcional):", + "banner_mode_vertical": "Modo Banner (vertical)", + "dithering": "Dithering:", + "intensity": "Intensidad:", + "rotate_image": "Rotar imagen:", + "print_mode": "Modo de impresión:", + "printing": "Imprimiendo...", + "sent_to_printer": "Enviado a impresora", + "preview": "Vista previa", + "your_preview_will_appear_here": "Su vista previa aparecerá aquí", + "quick_markdown_reference": "Referencia rápida de Markdown", + "bold": "Negrita:", + "italic": "Cursiva:", + "bold_and_italic": "Negrita y cursiva:", + "large_header": "Encabezado grande:", + "medium_header": "Encabezado mediano:", + "small_header": "Encabezado chico:", + "bullet_list": "Lista con viñetas:", + "numbered_list": "Lista numerada:", + "image": "Imágen:", + "line_break": "Salto de línea:", + "uploaded_image": "Imagen subida:", + "generate_btn": "🖼️ Generar", + "print_btn": "🖨️ Imprimir", + "text": "texto", + "title": "Título", + "element": "Elemento", + "alt_text": "Texto alternativo", + "image_url": "URL de la imagen", + "leave_an_empty_line": "Deje una línea vacía", + "uses_the_uploaded_image": "(usa la imagen cargada)", + "no_dithering": "Sin dithering" + } +} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..5c729db --- /dev/null +++ b/templates/index.html @@ -0,0 +1,645 @@ + + + + + {{ t['catnote'] }} + + + + + +
+
+
+

😺 {{ t['catnote'] }} 🖨️

+
+
+
+
+
+
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
{{ t['printing'] }}
+
+
+
+
+
+
+ + +
+
+ {% if printed %} +
✅ {{ t['sent_to_printer'] }}
+ {% endif %} + {% if error %} +
⚠️ {{ error }}
+ {% endif %} +
+
+ {% if img %} +

{{ t['preview'] }}

+ + {% else %} +

{{ t['your_preview_will_appear_here'] }}

+ {% endif %} +
+
+

{{ t['quick_markdown_reference'] }}

+ +
+
+
+ +
+ + + + \ No newline at end of file