feat(easel): add localization

This commit is contained in:
2026-04-23 15:47:16 +03:00
parent ecb574e286
commit 9351b9f53a
34 changed files with 464 additions and 311 deletions

View File

@@ -1,40 +1,41 @@
from pathlib import Path
from typing import NamedTuple
from fastapi import FastAPI, Request
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from gallery.util import root_path
from gallery.version import __version__
from ..translation import _
class Section(NamedTuple):
link: str
title: str
icon: str
SECTIONS = [
Section("weather", "Weather"),
Section("schedule", "TV program"),
Section("weather", "Weather", "brightness-high"),
Section("schedule", "TV program", "tv"),
]
base_dir = Path(__file__).parent
def mount(app: FastAPI):
base_dir = Path(__file__).parent
print("!", root_path / "static/dist")
app.mount("/static/main", StaticFiles(directory=root_path / "static/dist"))
app.mount("/static/common", StaticFiles(directory=base_dir / "static"))
templates = Jinja2Templates(directory=base_dir / "templates")
router = APIRouter()
@app.get("/", response_class=HTMLResponse)
async def get_section_list(request: Request):
return templates.TemplateResponse(
request=request,
name="root_index.html",
context={
"version": __version__,
"sections": SECTIONS,
},
)
templates = Jinja2Templates(directory=base_dir / "templates")
templates.env.globals.update({"_": _})
@router.get("/", response_class=HTMLResponse)
async def get_section_list(request: Request):
return templates.TemplateResponse(
request=request,
name="root_index.html",
context={
"version": __version__,
"sections": SECTIONS,
},
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,24 +0,0 @@
.icon {
display: inline-block;
width: 2rem;
height: 2rem;
background-size: contain;
}
.widget .app {
padding: 0.5rem !important;
}
.widget header {
display: none !important;
}
.widget main {
display: flex;
flex-direction: column;
align-items: center;
}
.widget footer {
display: none !important;
}

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="{{request.state.language}}">
<head>
{% block head %}
@@ -10,13 +10,11 @@
content="ie=edge">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet"
href="/static/main/gallery-static.css?v={{version}}">
href="/static/gallery.css?v={{version}}">
<script type="module"
src="/static/main/gallery-static.js?v={{version}}"></script>
<link rel="stylesheet"
href="/static/common/style.css?v={{version}}">
src="/static/gallery.es.js?v={{version}}"></script>
<link rel="icon"
href="/static/common/favicon.ico?v={{version}}"
href="/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
</head>
@@ -24,13 +22,43 @@
<body>
<div class="app col-lg-8 mx-auto p-3 py-md-5">
<header class="d-flex align-items-center pb-3 mb-5 border-bottom">
<a href="/"
class="d-flex align-items-center text-dark text-decoration-none">
<div class="icon me-2"
style="background-image: url(/static/common/gallery.png);"></div>
<span class="fs-4 text-body">API Gallery</span>
</a>
<app-link href="/"
icon="gear">API Gallery</app-link>
{% block header %}{% endblock %}
<ul class="navbar-nav flex-row flex-wrap ms-md-auto">
<li class="nav-item dropdown">
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center"
id="bd-language"
type="button"
aria-expanded="false"
data-bs-toggle="dropdown"
aria-label="Select language (default)">
<span class="me-2 language-icon-active">🇬🇧</span>
<span class="d-lg-none ms-2"
id="bd-language-text">Select language</span>
</button>
<ul class="dropdown-menu dropdown-menu-end"
aria-labelledby="bd-language-text">
<li>
<button type="button"
class="dropdown-item d-flex align-items-center"
data-bs-language-value="en"
aria-pressed="false">
<span class="me-2 language-icon">🇬🇧</span>
English
</button>
</li>
<li>
<button type="button"
class="dropdown-item d-flex align-items-center"
data-bs-language-value="ru"
aria-pressed="false">
<span class="me-2 language-icon">🇷🇺</span>
Russian
</button>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center"
id="bd-theme"
@@ -84,13 +112,6 @@
</div>
<script>
(function () {
document.toggleTheme = () => {
const current = document.documentElement.getAttribute('data-bs-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-bs-theme', next);
localStorage.setItem('theme', next);
};
const params = new URLSearchParams(window.location.search);
const widget = params.get('widget') || window.location.hostname.startsWith('weather');
if (widget) {

View File

@@ -10,15 +10,17 @@
{% for section in sections %}
<a href="{{section.link}}"
class="list-group-item list-group-item-action px-4">
<div class="d-flex w-100">
<span class="icon me-2"
style="background-image: url(/static/{{section.link}}/{{section.link}}.png);"></span>
<h4>{{section.title}}</h4>
</div>
<app-link href="{{section.link}}"
icon="{{section.icon}}">
{{_(section.title)}}
</app-link>
</a>
{% endfor %}
</div>
<hr class="col-3 col-md-2 mb-5">
<h1>Docs</h1>
<a href="/docs" target="_blank"><h4>Swagger</h4></a>
<a href="/docs"
target="_blank">
<h4>Swagger</h4>
</a>
{% endblock %}