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).
| assets | ||
| locale | ||
| scripts | ||
| src | ||
| .gitignore | ||
| config.yaml | ||
| Makefile | ||
| pages.yaml | ||
| README.md | ||
| requirements.txt | ||
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/.moper 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.yamlare 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,layoutoutputper localeseokeyscontext(data files + nav_active)
Gettext Workflow
- Write strings in French directly in templates:
{{ _("Mon texte") }} - Extract:
make pot→locale/messages.pot - Edit
.pofiles inlocale/en_US/andlocale/es_ES/(e.g. with Poedit) - Compile:
make compile→.mofiles - Build:
python scripts/build.py
Accessibility
Templates enforce by design:
- Unique
<h1>per page <nav aria-label="...">witharia-current="page"on active item- Skip link at top of
<body> <html lang="...">correct per versionhreflangalternates in<head>
Run Lighthouse or axe after adding your CSS/content to validate contrast ratios.
Adapting for Another Site
- Update
config.yaml(site name, base URL, locales, routing). - Update
pages.yaml(add/remove/rename pages). - Edit or replace templates in
src/templates/. - Update data files in
src/data/. - Regenerate and retranslate
.pofiles. - 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.txtgeneration. - Add GDPR conformity for the contact form
- Add a
schema.json - Support RTL
License
MIT – See LICENSE file.