65 lines
2.8 KiB
Python
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}"
|