mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-05-24 01:12:54 -04:00
fix: sync locales in user registration validation (#3278)
* Add ability to inject into Python files * Update outdated references to gen_global_components.py * Add code gen for registration locale validation * sort validators * update for pydantic 2 * run generator again --------- Co-authored-by: Gasper Gril <gasper@gril.si> Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
This commit is contained in:
parent
02da2114f9
commit
b54cdf6425
@ -3,8 +3,8 @@ from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from jinja2 import Template
|
||||
from pydantic import BaseModel
|
||||
from utils import PROJECT_DIR, CodeTemplates, HTTPRequest, RouteObject
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from utils import PROJECT_DIR, CodeTemplates, HTTPRequest, RouteObject, RequestType
|
||||
|
||||
CWD = Path(__file__).parent
|
||||
|
||||
@ -12,23 +12,25 @@ OUTFILE = PROJECT_DIR / "tests" / "utils" / "api_routes" / "__init__.py"
|
||||
|
||||
|
||||
class PathObject(BaseModel):
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
route_object: RouteObject
|
||||
http_verbs: list[HTTPRequest]
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
|
||||
|
||||
def get_path_objects(app: FastAPI):
|
||||
paths = []
|
||||
|
||||
for key, value in app.openapi().items():
|
||||
if key == "paths":
|
||||
for key, value in value.items():
|
||||
for key, value2 in value.items():
|
||||
verbs = []
|
||||
for k, v in value2.items():
|
||||
verbs.append(HTTPRequest(request_type=k, **v))
|
||||
|
||||
paths.append(
|
||||
PathObject(
|
||||
route_object=RouteObject(key),
|
||||
http_verbs=[HTTPRequest(request_type=k, **v) for k, v in value.items()],
|
||||
http_verbs=verbs,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
import dotenv
|
||||
import requests
|
||||
from jinja2 import Template
|
||||
from pydantic import Extra
|
||||
from pydantic import ConfigDict
|
||||
from requests import Response
|
||||
from utils import CodeDest, CodeKeys, inject_inline, log
|
||||
|
||||
@ -56,7 +56,7 @@ LOCALE_DATA: dict[str, LocaleData] = {
|
||||
"zh-TW": LocaleData(name="繁體中文 (Chinese traditional)"),
|
||||
}
|
||||
|
||||
LOCALE_TEMPLATE = """// This Code is auto generated by gen_global_components.py
|
||||
LOCALE_TEMPLATE = """// This Code is auto generated by gen_ts_locales.py
|
||||
export const LOCALES = [{% for locale in locales %}
|
||||
{
|
||||
name: "{{ locale.name }}",
|
||||
@ -70,6 +70,8 @@ export const LOCALES = [{% for locale in locales %}
|
||||
|
||||
|
||||
class TargetLanguage(MealieModel):
|
||||
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
||||
|
||||
id: str
|
||||
name: str
|
||||
locale: str
|
||||
@ -78,10 +80,6 @@ class TargetLanguage(MealieModel):
|
||||
twoLettersCode: str
|
||||
progress: float = 0.0
|
||||
|
||||
class Config:
|
||||
extra = Extra.allow
|
||||
allow_population_by_field_name = True
|
||||
|
||||
|
||||
class CrowdinApi:
|
||||
project_name = "Mealie"
|
||||
@ -152,6 +150,7 @@ PROJECT_DIR = Path(__file__).parent.parent.parent
|
||||
datetime_dir = PROJECT_DIR / "frontend" / "lang" / "dateTimeFormats"
|
||||
locales_dir = PROJECT_DIR / "frontend" / "lang" / "messages"
|
||||
nuxt_config = PROJECT_DIR / "frontend" / "nuxt.config.js"
|
||||
reg_valid = PROJECT_DIR / "mealie" / "schema" / "_mealie" / "validators.py"
|
||||
|
||||
"""
|
||||
This snippet walks the message and dat locales directories and generates the import information
|
||||
@ -175,6 +174,19 @@ def inject_nuxt_values():
|
||||
inject_inline(nuxt_config, CodeKeys.nuxt_local_dates, all_date_locales)
|
||||
|
||||
|
||||
def inject_registration_validation_values():
|
||||
all_langs = []
|
||||
for match in locales_dir.glob("*.json"):
|
||||
lang_string = f'"{match.stem}",'
|
||||
all_langs.append(lang_string)
|
||||
|
||||
# sort
|
||||
all_langs.sort()
|
||||
|
||||
log.debug(f"injecting locales into user registration validation -> {reg_valid}")
|
||||
inject_inline(reg_valid, CodeKeys.nuxt_local_messages, all_langs)
|
||||
|
||||
|
||||
def generate_locales_ts_file():
|
||||
api = CrowdinApi("")
|
||||
models = api.get_languages()
|
||||
@ -193,6 +205,7 @@ def main():
|
||||
|
||||
generate_locales_ts_file()
|
||||
inject_nuxt_values()
|
||||
inject_registration_validation_values()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -6,7 +6,7 @@ from utils import log
|
||||
|
||||
# ============================================================
|
||||
|
||||
template = """// This Code is auto generated by gen_global_components.py
|
||||
template = """// This Code is auto generated by gen_ts_types.py
|
||||
{% for name in global %}import {{ name }} from "@/components/global/{{ name }}.vue";
|
||||
{% endfor %}{% for name in layout %}import {{ name }} from "@/components/layout/{{ name }}.vue";
|
||||
{% endfor %}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import re
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from humps import camelize
|
||||
from pydantic import BaseModel, Extra, Field
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from slugify import slugify
|
||||
|
||||
|
||||
@ -34,33 +33,30 @@ class ParameterIn(str, Enum):
|
||||
|
||||
|
||||
class RouterParameter(BaseModel):
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
required: bool = False
|
||||
name: str
|
||||
location: ParameterIn = Field(..., alias="in")
|
||||
|
||||
class Config:
|
||||
extra = Extra.allow
|
||||
|
||||
|
||||
class RequestBody(BaseModel):
|
||||
required: bool = False
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
class Config:
|
||||
extra = Extra.allow
|
||||
required: bool = False
|
||||
|
||||
|
||||
class HTTPRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="allow", populate_by_name=True)
|
||||
|
||||
request_type: RequestType
|
||||
description: str = ""
|
||||
summary: str
|
||||
requestBody: Optional[RequestBody]
|
||||
request_body: RequestBody | None = None
|
||||
|
||||
parameters: list[RouterParameter] = []
|
||||
tags: list[str] | None = []
|
||||
|
||||
class Config:
|
||||
extra = Extra.allow
|
||||
|
||||
def list_as_js_object_string(self, parameters, braces=True):
|
||||
if len(parameters) == 0:
|
||||
return ""
|
||||
@ -71,11 +67,11 @@ class HTTPRequest(BaseModel):
|
||||
return ", ".join(parameters)
|
||||
|
||||
def payload(self):
|
||||
return "payload" if self.requestBody else ""
|
||||
return "payload" if self.request_body else ""
|
||||
|
||||
def function_args(self):
|
||||
all_params = [p.name for p in self.parameters]
|
||||
if self.requestBody:
|
||||
if self.request_body:
|
||||
all_params.append("payload")
|
||||
return self.list_as_js_object_string(all_params)
|
||||
|
||||
|
@ -50,7 +50,7 @@ class CodeSlicer:
|
||||
self._next_line += 1
|
||||
|
||||
|
||||
def get_indentation_of_string(line: str, comment_char: str = "//") -> str:
|
||||
def get_indentation_of_string(line: str, comment_char: str = "//|#") -> str:
|
||||
return re.sub(rf"{comment_char}.*", "", line).removesuffix("\n")
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
// This Code is auto generated by gen_global_components.py
|
||||
// This Code is auto generated by gen_ts_locales.py
|
||||
export const LOCALES = [
|
||||
{
|
||||
name: "繁體中文 (Chinese traditional)",
|
||||
value: "zh-TW",
|
||||
progress: 30,
|
||||
progress: 29,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -15,7 +15,7 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Tiếng Việt (Vietnamese)",
|
||||
value: "vi-VN",
|
||||
progress: 1,
|
||||
progress: 0,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -27,43 +27,43 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Türkçe (Turkish)",
|
||||
value: "tr-TR",
|
||||
progress: 53,
|
||||
progress: 62,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Svenska (Swedish)",
|
||||
value: "sv-SE",
|
||||
progress: 94,
|
||||
progress: 99,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "српски (Serbian)",
|
||||
value: "sr-SP",
|
||||
progress: 32,
|
||||
progress: 31,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Slovenian",
|
||||
value: "sl-SI",
|
||||
progress: 47,
|
||||
progress: 49,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Slovak",
|
||||
value: "sk-SK",
|
||||
progress: 93,
|
||||
progress: 91,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Pусский (Russian)",
|
||||
value: "ru-RU",
|
||||
progress: 98,
|
||||
progress: 99,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Română (Romanian)",
|
||||
value: "ro-RO",
|
||||
progress: 42,
|
||||
progress: 44,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -75,19 +75,19 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Português do Brasil (Brazilian Portuguese)",
|
||||
value: "pt-BR",
|
||||
progress: 97,
|
||||
progress: 95,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Polski (Polish)",
|
||||
value: "pl-PL",
|
||||
progress: 98,
|
||||
progress: 100,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Norsk (Norwegian)",
|
||||
value: "no-NO",
|
||||
progress: 99,
|
||||
progress: 97,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -99,25 +99,25 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Latvian",
|
||||
value: "lv-LV",
|
||||
progress: 1,
|
||||
progress: 0,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Lithuanian",
|
||||
value: "lt-LT",
|
||||
progress: 93,
|
||||
progress: 91,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "한국어 (Korean)",
|
||||
value: "ko-KR",
|
||||
progress: 5,
|
||||
progress: 3,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "日本語 (Japanese)",
|
||||
value: "ja-JP",
|
||||
progress: 12,
|
||||
progress: 11,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -135,25 +135,25 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Magyar (Hungarian)",
|
||||
value: "hu-HU",
|
||||
progress: 100,
|
||||
progress: 98,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Croatian",
|
||||
value: "hr-HR",
|
||||
progress: 93,
|
||||
progress: 91,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "עברית (Hebrew)",
|
||||
value: "he-IL",
|
||||
progress: 97,
|
||||
progress: 98,
|
||||
dir: "rtl",
|
||||
},
|
||||
{
|
||||
name: "Galician",
|
||||
value: "gl-ES",
|
||||
progress: 1,
|
||||
progress: 3,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -165,19 +165,19 @@ export const LOCALES = [
|
||||
{
|
||||
name: "French, Canada",
|
||||
value: "fr-CA",
|
||||
progress: 97,
|
||||
progress: 95,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Suomi (Finnish)",
|
||||
value: "fi-FI",
|
||||
progress: 91,
|
||||
progress: 89,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Español (Spanish)",
|
||||
value: "es-ES",
|
||||
progress: 79,
|
||||
progress: 93,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -189,13 +189,13 @@ export const LOCALES = [
|
||||
{
|
||||
name: "British English",
|
||||
value: "en-GB",
|
||||
progress: 3,
|
||||
progress: 2,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Ελληνικά (Greek)",
|
||||
value: "el-GR",
|
||||
progress: 34,
|
||||
progress: 33,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -219,7 +219,7 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Català (Catalan)",
|
||||
value: "ca-ES",
|
||||
progress: 75,
|
||||
progress: 74,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@ -231,13 +231,13 @@ export const LOCALES = [
|
||||
{
|
||||
name: "العربية (Arabic)",
|
||||
value: "ar-SA",
|
||||
progress: 20,
|
||||
progress: 18,
|
||||
dir: "rtl",
|
||||
},
|
||||
{
|
||||
name: "Afrikaans (Afrikaans)",
|
||||
value: "af-ZA",
|
||||
progress: 92,
|
||||
progress: 90,
|
||||
dir: "ltr",
|
||||
},
|
||||
]
|
||||
|
2
frontend/types/components.d.ts
vendored
2
frontend/types/components.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
// This Code is auto generated by gen_global_components.py
|
||||
// This Code is auto generated by gen_ts_types.py
|
||||
import AdvancedOnly from "@/components/global/AdvancedOnly.vue";
|
||||
import AppButtonCopy from "@/components/global/AppButtonCopy.vue";
|
||||
import AppButtonUpload from "@/components/global/AppButtonUpload.vue";
|
||||
|
@ -1,38 +1,47 @@
|
||||
def validate_locale(locale: str) -> bool:
|
||||
valid = {
|
||||
"el-GR",
|
||||
"it-IT",
|
||||
"ko-KR",
|
||||
"es-ES",
|
||||
"ja-JP",
|
||||
"zh-CN",
|
||||
"tr-TR",
|
||||
"ar-SA",
|
||||
"hu-HU",
|
||||
"pt-PT",
|
||||
"no-NO",
|
||||
"sv-SE",
|
||||
"ro-RO",
|
||||
"sk-SK",
|
||||
"uk-UA",
|
||||
"fr-CA",
|
||||
"pl-PL",
|
||||
"da-DK",
|
||||
"pt-BR",
|
||||
"de-DE",
|
||||
"ca-ES",
|
||||
"sr-SP",
|
||||
"cs-CZ",
|
||||
"fr-FR",
|
||||
"zh-TW",
|
||||
# CODE_GEN_ID: MESSAGE_LOCALES
|
||||
"af-ZA",
|
||||
"ru-RU",
|
||||
"he-IL",
|
||||
"nl-NL",
|
||||
"en-US",
|
||||
"ar-SA",
|
||||
"bg-BG",
|
||||
"ca-ES",
|
||||
"cs-CZ",
|
||||
"da-DK",
|
||||
"de-DE",
|
||||
"el-GR",
|
||||
"en-GB",
|
||||
"en-US",
|
||||
"es-ES",
|
||||
"fi-FI",
|
||||
"fr-CA",
|
||||
"fr-FR",
|
||||
"gl-ES",
|
||||
"he-IL",
|
||||
"hr-HR",
|
||||
"hu-HU",
|
||||
"is-IS",
|
||||
"it-IT",
|
||||
"ja-JP",
|
||||
"ko-KR",
|
||||
"lt-LT",
|
||||
"lv-LV",
|
||||
"nl-NL",
|
||||
"no-NO",
|
||||
"pl-PL",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ro-RO",
|
||||
"ru-RU",
|
||||
"sk-SK",
|
||||
"sl-SI",
|
||||
"sr-SP",
|
||||
"sv-SE",
|
||||
"tr-TR",
|
||||
"uk-UA",
|
||||
"vi-VN",
|
||||
"zh-CN",
|
||||
"zh-TW",
|
||||
# END: MESSAGE_LOCALES
|
||||
}
|
||||
|
||||
return locale in valid
|
||||
|
Loading…
x
Reference in New Issue
Block a user