i18n: fix string with variables format

This commit is contained in:
Iain Learmonth 2026-03-08 16:02:18 +00:00
parent 50ae94c9e9
commit 6b8fb3b470
12 changed files with 115 additions and 22 deletions

View file

@ -25,8 +25,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

View file

@ -24,12 +24,12 @@ msgstr "How do I know that I can trust this page?"
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
#: src/snapshots/templates/article-template.html.j2:76

View file

@ -26,12 +26,12 @@ msgstr "¿Cómo sé que puedo confiar en esta página?"
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""
"Esta historia es una copia de un artículo de <a href=\"%(site_url)\" "
"class=\"snap-trust-header__sitelink\">%(site_title)</a>. Se la entregamos "
"Esta historia es una copia de un artículo de <a href=\"{site_url}\" "
"class=\"snap-trust-header__sitelink\">{site_title}</a>. Se la entregamos "
"desde un archivo confiable para garantizar su disponibilidad a lo largo del "
"tiempo."

View file

@ -24,8 +24,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

View file

@ -24,8 +24,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

View file

@ -23,8 +23,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

View file

@ -24,8 +24,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

View file

@ -24,8 +24,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

View file

@ -25,8 +25,8 @@ msgstr ""
#: src/snapshots/templates/article-template.html.j2:73
msgid ""
"This story is a copy of an article from <a href=\"%(site_url)\" class"
"=\"snap-trust-header__sitelink\">%(site_title)</a>. It is delivered to "
"This story is a copy of an article from <a href=\"{site_url}\" class"
"=\"snap-trust-header__sitelink\">{site_title}</a>. It is delivered to "
"you from a trusted archive to assure its availability over time."
msgstr ""

50
src/database.py Normal file
View file

@ -0,0 +1,50 @@
import contextlib
from typing import Annotated, Iterator, Generator
from fastapi import Depends
from sqlalchemy import (
MetaData, create_engine, Connection,
)
from sqlalchemy.orm import sessionmaker, Session
from src.config import settings
from src.constants import DB_NAMING_CONVENTION
engine = create_engine(
str(settings.DATABASE_URL),
pool_size=settings.DATABASE_POOL_SIZE,
pool_recycle=settings.DATABASE_POOL_TTL,
pool_pre_ping=settings.DATABASE_POOL_PRE_PING,
)
metadata = MetaData(naming_convention=DB_NAMING_CONVENTION)
sm = sessionmaker(autocommit=False, expire_on_commit=False, bind=engine)
@contextlib.contextmanager
def get_db_connection() -> Iterator[Connection]:
with engine.connect() as connection:
try:
yield connection
except Exception:
connection.rollback()
raise
@contextlib.contextmanager
def get_db_session() -> Iterator[Session]:
session = sm()
try:
yield session
except Exception:
session.rollback()
raise
finally:
session.close()
def get_db() -> Generator[Session, None]:
with get_db_session() as session:
yield session
DbSession = Annotated[Session, Depends(get_db)]

34
src/models.py Normal file
View file

@ -0,0 +1,34 @@
from datetime import datetime
from typing import Any
from sqlalchemy import DateTime, JSON, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from src.database import metadata
class CustomBase(DeclarativeBase):
type_annotation_map = {
datetime: DateTime(timezone=True),
dict[str, Any]: JSON,
}
metadata = metadata
class ActivatedMixin:
active: Mapped[bool] = mapped_column(default=True)
class DeletedTimestampMixin:
deleted_at: Mapped[datetime | None] = mapped_column(nullable=True)
class DescriptionMixin:
description: Mapped[str]
class IdMixin:
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
class TimestampMixin:
created_at: Mapped[datetime] = mapped_column(default=func.now())
updated_at: Mapped[datetime] = mapped_column(default=func.now(), onupdate=func.now())

9
src/snapshots/models.py Normal file
View file

@ -0,0 +1,9 @@
from sqlalchemy.orm import Mapped
from src.models import CustomBase, IdMixin
class Snapshot(CustomBase, IdMixin):
__tablename__ = "snapshot"
url: Mapped[str]