feat: add runtime locale overrides

This commit is contained in:
3252a8
2026-05-25 17:47:45 +03:00
parent 23784d00fe
commit 59fa301344
51 changed files with 4026 additions and 214 deletions
+2
View File
@@ -1,6 +1,7 @@
from . import (
ad_dal,
app_settings_dal,
locale_overrides_dal,
message_log_dal,
panel_sync_dal,
payment_dal,
@@ -23,5 +24,6 @@ __all__ = (
"ad_dal",
"security_dal",
"app_settings_dal",
"locale_overrides_dal",
"support_dal",
)
+86
View File
@@ -0,0 +1,86 @@
"""Persistent overrides for localization strings."""
from datetime import datetime, timezone
from typing import Dict, List, Optional, Tuple
from sqlalchemy import delete, select
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.ext.asyncio import AsyncSession
from db.models import LocaleOverride
async def get_all_overrides(session: AsyncSession) -> Dict[str, Dict[str, str]]:
rows = (await session.execute(select(LocaleOverride))).scalars().all()
result: Dict[str, Dict[str, str]] = {}
for row in rows:
result.setdefault(row.lang, {})[row.key] = row.value
return result
async def get_overrides_with_meta(session: AsyncSession) -> List[Dict[str, object]]:
rows = (await session.execute(select(LocaleOverride))).scalars().all()
items: List[Dict[str, object]] = []
for row in rows:
items.append(
{
"lang": row.lang,
"key": row.key,
"value": row.value,
"updated_at": row.updated_at.isoformat() if row.updated_at else None,
"updated_by": row.updated_by,
}
)
return items
async def upsert_override(
session: AsyncSession,
*,
lang: str,
key: str,
value: str,
updated_by: Optional[int],
) -> None:
now = datetime.now(timezone.utc)
stmt = (
pg_insert(LocaleOverride)
.values(lang=lang, key=key, value=value, updated_at=now, updated_by=updated_by)
.on_conflict_do_update(
index_elements=[LocaleOverride.lang, LocaleOverride.key],
set_={
"value": value,
"updated_at": now,
"updated_by": updated_by,
},
)
)
await session.execute(stmt)
async def delete_override(session: AsyncSession, *, lang: str, key: str) -> bool:
stmt = delete(LocaleOverride).where(
LocaleOverride.lang == lang,
LocaleOverride.key == key,
)
result = await session.execute(stmt)
return bool(result.rowcount or 0)
async def bulk_apply(
session: AsyncSession,
*,
updates: Dict[Tuple[str, str], Tuple[bool, str]],
updated_by: Optional[int],
) -> None:
for (lang, key), (set_flag, value) in updates.items():
if set_flag:
await upsert_override(
session,
lang=lang,
key=key,
value=value,
updated_by=updated_by,
)
else:
await delete_override(session, lang=lang, key=key)
+22
View File
@@ -902,6 +902,23 @@ def _migration_0027_add_subscription_install_share_token(connection: Connection)
)
def _migration_0028_add_locale_overrides(connection: Connection) -> None:
connection.execute(
text(
"""
CREATE TABLE IF NOT EXISTS locale_overrides (
lang VARCHAR(16) NOT NULL,
key VARCHAR(255) NOT NULL,
value TEXT NOT NULL,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_by BIGINT,
PRIMARY KEY (lang, key)
)
"""
)
)
MIGRATIONS: List[Migration] = [
Migration(
id="0001_add_channel_subscription_fields",
@@ -1049,6 +1066,11 @@ MIGRATIONS: List[Migration] = [
description="Add stable public share tokens for install instructions",
upgrade=_migration_0027_add_subscription_install_share_token,
),
Migration(
id="0028_add_locale_overrides",
description="Persist runtime overrides for localization strings",
upgrade=_migration_0028_add_locale_overrides,
),
]
+15
View File
@@ -489,3 +489,18 @@ class AppSettingOverride(Base):
nullable=False,
)
updated_by = Column(BigInteger, nullable=True)
class LocaleOverride(Base):
__tablename__ = "locale_overrides"
lang = Column(String(16), primary_key=True)
key = Column(String(255), primary_key=True)
value = Column(Text, nullable=False)
updated_at = Column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
nullable=False,
)
updated_by = Column(BigInteger, nullable=True)