feat: allow to define translation for jinja2 i18n

This commit is contained in:
Corentin 2024-05-21 15:15:00 +02:00
parent e6363bea4e
commit e898505125
3 changed files with 31 additions and 10 deletions

View File

@ -1,5 +1,4 @@
from functools import cache
from gettext import textdomain
from pathlib import Path
from typing import Any, Iterable, Iterator
@ -8,6 +7,8 @@ from yaml import Loader, load
class Content:
current_language: str | None = None
def __init__(self, path: Path) -> None:
self.__path = path
@ -30,7 +31,7 @@ class ContentDirectory(Content):
def glob(self, pattern: str) -> Iterable[Content]:
for item in self.path.glob(pattern):
yield self.load(str(item))
yield self.load(str(item.relative_to(self.path)))
@cache # noqa: B019
def __load_children(self, name: str) -> Content:
@ -52,8 +53,9 @@ class ContentDirectory(Content):
@staticmethod
def __get_localized_path(path: Path) -> Path:
domain = textdomain()
localized_path = path.with_name(f"{path.stem}-{domain}{path.suffix}")
if Content.current_language is None:
return path
localized_path = path.with_name(f"{path.stem}-{Content.current_language}{path.suffix}")
if not localized_path.exists():
return path

View File

@ -1,3 +1,5 @@
import gettext
from gettext import GNUTranslations, NullTranslations
from pathlib import Path
from shutil import copy
from typing import Any
@ -5,7 +7,7 @@ from typing import Any
from jinja2.environment import Environment
from jinja2.loaders import FileSystemLoader
from jwebsite.content import ContentDirectory
from jwebsite.content import Content, ContentDirectory
from jwebsite.git import git_creation_date
@ -16,16 +18,34 @@ class Site:
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:
self.__output_directory.mkdir(parents=True, exist_ok=True)
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)
output_path = self.__output_directory / output
with open(output_path, "w") as output_file:
output_file.write(content)

View File

@ -1,9 +1,8 @@
from gettext import textdomain
from pathlib import Path
from pytest import raises
from jwebsite.content import ContentDirectory
from jwebsite.content import Content, ContentDirectory
def test_load_directory(datadir: Path) -> None:
@ -50,7 +49,7 @@ def test_load_markdown(datadir: Path) -> None:
def test_localized_content(datadir: Path) -> None:
content = ContentDirectory(datadir)
textdomain("fr")
Content.current_language = "fr"
page = content.load(Path("page.md"))
assert page.html == "<p>Contenu</p>"