🌐 Integrated Italian translation
This commit is contained in:
@@ -12,7 +12,7 @@ from classquiz.config import settings
|
|||||||
from classquiz.db import database
|
from classquiz.db import database
|
||||||
from classquiz.routers import users, quiz, utils, stats, storage, search, testing_routes, editor
|
from classquiz.routers import users, quiz, utils, stats, storage, search, testing_routes, editor
|
||||||
from classquiz.socket_server import sio
|
from classquiz.socket_server import sio
|
||||||
from classquiz.helpers import meilisearch_init
|
from classquiz.helpers import meilisearch_init, telemetry_ping
|
||||||
|
|
||||||
settings = settings()
|
settings = settings()
|
||||||
if settings.sentry_dsn:
|
if settings.sentry_dsn:
|
||||||
@@ -39,6 +39,7 @@ async def startup() -> None:
|
|||||||
if not database_.is_connected:
|
if not database_.is_connected:
|
||||||
await database_.connect()
|
await database_.connect()
|
||||||
await meilisearch_init()
|
await meilisearch_init()
|
||||||
|
await telemetry_ping()
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("shutdown")
|
@app.on_event("shutdown")
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Settings(BaseSettings):
|
|||||||
google_client_secret: Optional[str]
|
google_client_secret: Optional[str]
|
||||||
github_client_id: Optional[str]
|
github_client_id: Optional[str]
|
||||||
github_client_secret: Optional[str]
|
github_client_secret: Optional[str]
|
||||||
|
telemetry_enabled: bool = True
|
||||||
|
|
||||||
# storage_backend
|
# storage_backend
|
||||||
storage_backend: str | None = "deta"
|
storage_backend: str | None = "deta"
|
||||||
|
|||||||
@@ -119,6 +119,15 @@ class Quiz(ormar.Model):
|
|||||||
database = database
|
database = database
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceData(ormar.Model):
|
||||||
|
instance_id: uuid.UUID = ormar.UUID(primary_key=True, default=uuid.uuid4(), nullable=False, unique=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
tablename = "instance_data"
|
||||||
|
metadata = metadata
|
||||||
|
database = database
|
||||||
|
|
||||||
|
|
||||||
class Token(BaseModel):
|
class Token(BaseModel):
|
||||||
"""
|
"""
|
||||||
For JWT
|
For JWT
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from classquiz.db.models import Quiz, User
|
import ormar.exceptions
|
||||||
|
|
||||||
|
from classquiz.db.models import Quiz, User, InstanceData
|
||||||
import xlsxwriter
|
import xlsxwriter
|
||||||
from aiohttp import ClientSession
|
from aiohttp import ClientSession
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
@@ -114,6 +116,23 @@ async def meilisearch_init():
|
|||||||
print("Finished MeiliSearch synchronisation")
|
print("Finished MeiliSearch synchronisation")
|
||||||
|
|
||||||
|
|
||||||
|
async def telemetry_ping():
|
||||||
|
try:
|
||||||
|
instance_data = await InstanceData.objects.first()
|
||||||
|
except ormar.exceptions.NoMatch:
|
||||||
|
instance_data = InstanceData()
|
||||||
|
await instance_data.save()
|
||||||
|
async with ClientSession() as session, session.post(
|
||||||
|
f"https://cit.mawoka.eu.org/public/{instance_data.instance_id}",
|
||||||
|
json={
|
||||||
|
"public_quizzes": await Quiz.objects.filter(public=True).count(),
|
||||||
|
"private_quizzes": await Quiz.objects.filter(public=False).count(),
|
||||||
|
"users": await User.objects.count(),
|
||||||
|
},
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def check_hashcash(data: str, input_data: str, claim_in: Optional[str] = "19") -> bool:
|
def check_hashcash(data: str, input_data: str, claim_in: Optional[str] = "19") -> bool:
|
||||||
"""
|
"""
|
||||||
It checks that the hashcash is valid, and if it is, it returns True
|
It checks that the hashcash is valid, and if it is, it returns True
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import fr from './locales/fr.json';
|
|||||||
import tr from './locales/tr.json';
|
import tr from './locales/tr.json';
|
||||||
import id from './locales/id.json';
|
import id from './locales/id.json';
|
||||||
import ca from './locales/ca.json';
|
import ca from './locales/ca.json';
|
||||||
|
import it from './locales/it.json';
|
||||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
|
|
||||||
import type { i18n, Resource } from 'i18next';
|
import type { i18n, Resource } from 'i18next';
|
||||||
@@ -61,6 +62,7 @@ export class I18nService {
|
|||||||
this.i18n.addResourceBundle('fr', 'translation', fr);
|
this.i18n.addResourceBundle('fr', 'translation', fr);
|
||||||
this.i18n.addResourceBundle('tr', 'translation', tr);
|
this.i18n.addResourceBundle('tr', 'translation', tr);
|
||||||
this.i18n.addResourceBundle('id', 'translation', id);
|
this.i18n.addResourceBundle('id', 'translation', id);
|
||||||
|
this.i18n.addResourceBundle('it', 'translation', it);
|
||||||
this.i18n.addResourceBundle('ca', 'translation', ca);
|
this.i18n.addResourceBundle('ca', 'translation', ca);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,11 @@
|
|||||||
code: 'ca',
|
code: 'ca',
|
||||||
name: 'Català',
|
name: 'Català',
|
||||||
flag: '🇪🇸'
|
flag: '🇪🇸'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'it',
|
||||||
|
name: 'Italiano',
|
||||||
|
flag: '🇮🇹'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const get_selected_language = (): string => {
|
const get_selected_language = (): string => {
|
||||||
|
|||||||
@@ -44,6 +44,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/jmontane">Joan Montané</a> (Catalan)
|
<a href="https://github.com/jmontane">Joan Montané</a> (Catalan)
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/maxmasetti">Max</a> (Italian)
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p><i>...Maybe you?</i></p>
|
<p><i>...Maybe you?</i></p>
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"""added instance_data
|
||||||
|
|
||||||
|
Revision ID: 3f63c0130bce
|
||||||
|
Revises: ff573859eb32
|
||||||
|
Create Date: 2022-08-28 20:20:28.932854
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
import ormar
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "3f63c0130bce"
|
||||||
|
down_revision = "ff573859eb32"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table(
|
||||||
|
"instance_data",
|
||||||
|
sa.Column("instance_id", ormar.fields.sqlalchemy_uuid.CHAR(32), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint("instance_id"),
|
||||||
|
sa.UniqueConstraint("instance_id"),
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table("instance_data")
|
||||||
|
# ### end Alembic commands ###
|
||||||
Reference in New Issue
Block a user