PolyTic – Static Polyglot Site Generator A generic static site generator built with Python, Jinja2 and gettext. Produces a multi-language, accessible, SEO-friendly static website (FR/EN/ES by now).
Find a file
2026-06-21 16:29:38 +02:00
assets kickstart project 2026-06-20 14:58:51 +02:00
locale fix Stefany 2026-06-21 16:27:58 +02:00
scripts fix Stefany 2026-06-21 16:27:58 +02:00
src fix Stefany 2026-06-21 16:27:58 +02:00
.gitignore add gitignore 2026-06-20 14:59:27 +02:00
config.yaml fix Stefany 2026-06-21 16:27:58 +02:00
Makefile kickstart project 2026-06-20 14:58:51 +02:00
pages.yaml kickstart project 2026-06-20 14:58:51 +02:00
README.md Merge remote-tracking branch 'refs/remotes/origin/main' 2026-06-21 16:29:38 +02:00
requirements.txt kickstart project 2026-06-20 14:58:51 +02:00

PolyTic Static Polyglot Site Generator

A generic static site generator built with Python, Jinja2 and gettext. Produces a multi-language, accessible, SEO-friendly static website (FR/EN/ES).

Demo site: "Learn French with Stefany" French as a Foreign Language (FLE) lessons.


Features

  • Static output deploy anywhere (Netlify, GitHub Pages, S3/CDN, shared hosting).
  • 🌍 Multi-language with gettext French as source language, .po/.mo per locale.
  • Accessible by design Skip links, landmarks, heading hierarchy, aria-* attributes.
  • 🔍 SEO-friendly Per-language URLs, hreflang, per-page title + meta description.
  • ⚙️ Config-driven config.yaml + pages.yaml are the single source of truth.
  • 🧱 Lightweight No database, no framework, just Python + Jinja2.

Quick Start

# 1. Install dependencies
pip install -r requirements.txt

# 2. (Optional) Extract strings and update .po files
make pot
make update

# 3. Compile .po → .mo (requires gettext tools)
make compile

# 4. Build the site
python scripts/build.py

# 5. Preview locally
make serve
# → open http://localhost:8000/fr/

If msgfmt is not installed, build.py can use a fallback pure-Python MO compiler.


Project Structure

config.yaml           # Global site configuration
pages.yaml            # Page definitions

src/
  templates/          # Jinja2 templates
    base.html         # Base layout (header, footer, nav, skip link)
    home.html
    about.html
    courses.html
    contact.html
  data/               # Structured content in YAML
    nav.yaml          # Navigation items
    home.yaml
    about.yaml
    courses.yaml
    contact.yaml

locale/               # Gettext catalogs (source: fr_FR)
  fr_FR/LC_MESSAGES/messages.po
  en_US/LC_MESSAGES/messages.po
  es_ES/LC_MESSAGES/messages.po

scripts/
  build.py            # Build engine

assets/
  styles.css          # Minimal accessible CSS

build/                # Generated site (gitignored)
  fr/
  en/
  es/
  sitemap.xml

Makefile
requirements.txt
AGENTS.md
README.md

Configuration

config.yaml

  • site name, base URL, author, year, default locale.
  • locales list of supported locales with code, label, dir, url_prefix.
  • routing page id → URL segment mapping.
  • seo default gettext keys for title/description fallback.
  • accessibility skip link target and main landmark id.
  • build paths and options (sitemap generation, etc.).

pages.yaml

Each page entry defines:

  • id, template, layout
  • output per locale
  • seo keys
  • context (data files + nav_active)

Gettext Workflow

  1. Write strings in French directly in templates: {{ _("Mon texte") }}
  2. Extract: make potlocale/messages.pot
  3. Edit .po files in locale/en_US/ and locale/es_ES/ (e.g. with Poedit)
  4. Compile: make compile.mo files
  5. Build: python scripts/build.py

Accessibility

Templates enforce by design:

  • Unique <h1> per page
  • <nav aria-label="..."> with aria-current="page" on active item
  • Skip link at top of <body>
  • <html lang="..."> correct per version
  • hreflang alternates in <head>

Run Lighthouse or axe after adding your CSS/content to validate contrast ratios.


Adapting for Another Site

  1. Update config.yaml (site name, base URL, locales, routing).
  2. Update pages.yaml (add/remove/rename pages).
  3. Edit or replace templates in src/templates/.
  4. Update data files in src/data/.
  5. Regenerate and retranslate .po files.
  6. Run python scripts/build.py.

Further Work

  • Add a contact form backend (Netlify Forms, Formspree, or self-hosted).
  • Add Open Graph / Twitter Card meta tags in base.html.
  • Integrate a CSS build step (Sass, PostCSS) if needed.
  • Add automated accessibility testing (axe-core CLI) to the Makefile.
  • Add robots.txt generation.
  • Add GDPR conformity for the contact form
  • Add a schema.json
  • Support RTL

License

MIT See LICENSE file.

Launched on DevGlobe