jean-web/jwebsite/site.py

65 lines
2.8 KiB
Python

import gettext
from gettext import GNUTranslations, NullTranslations
from pathlib import Path
from shutil import copy
from typing import Any
from jinja2.environment import Environment
from jinja2.loaders import FileSystemLoader
from jwebsite.content import Content, ContentDirectory
from jwebsite.git import git_creation_date
class Site:
def __init__(self, root_directory: Path) -> None:
self.__root_directory = root_directory
self.__output_directory = root_directory / "build"
self.__environment = Environment(loader=FileSystemLoader(searchpath=root_directory / "src"))
self.__environment.filters.update({"output": self.__output, "git_creation_date": git_creation_date})
self.__content = ContentDirectory(root_directory / "content")
self.__translations: dict[str, GNUTranslations | NullTranslations] = {}
@property
def content(self) -> ContentDirectory:
return self.__content
def set_translations(self, domain: str, locale_dir: str, languages: list[str]) -> None:
self.__environment.add_extension("jinja2.ext.i18n")
self.__translations["en"] = NullTranslations()
for language in languages:
self.__translations[language] = gettext.translation(
domain, localedir=str(locale_dir), languages=[language]
)
def render(self, source: str, output: str | Path, **context: Any) -> None:
if self.__translations:
for language, translation in self.__translations.items():
Content.current_language = language
self.__environment.install_gettext_translations(translation, newstyle=True) # type: ignore
self.__render(source, self.__output_directory / language / output, **context)
self.__environment.uninstall_gettext_translations(translation) # type: ignore
else:
self.__render(source, self.__output_directory / output, **context)
def __render(self, source: str, output_path: Path, **context: Any) -> None:
output_path.parent.mkdir(exist_ok=True, parents=True)
template = self.__environment.get_template(source)
content = template.render(site=self, **context)
with open(output_path, "w") as output_file:
output_file.write(content)
def __output(self, path: str | Path) -> str:
path = Path(path)
if path.is_absolute():
src_path = path
relative_src_path = src_path.relative_to(self.__content.path)
else:
src_path = self.__content.path / path
relative_src_path = path
dst_path = self.__output_directory / relative_src_path
dst_path.parent.mkdir(parents=True, exist_ok=True)
copy(src_path, dst_path, follow_symlinks=True)
return f"/{relative_src_path}"