mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-07-22 23:50:15 -04:00
feat: Customize Ingredient Plural Handling (#7057)
This commit is contained in:
66
mealie/lang/locale_config.py
Normal file
66
mealie/lang/locale_config.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
class LocaleTextDirection(StrEnum):
|
||||
LTR = "ltr"
|
||||
RTL = "rtl"
|
||||
|
||||
|
||||
class LocalePluralFoodHandling(StrEnum):
|
||||
ALWAYS = "always"
|
||||
WITHOUT_UNIT = "without-unit"
|
||||
NEVER = "never"
|
||||
|
||||
|
||||
@dataclass
|
||||
class LocaleConfig:
|
||||
name: str
|
||||
dir: LocaleTextDirection = LocaleTextDirection.LTR
|
||||
plural_food_handling: LocalePluralFoodHandling = LocalePluralFoodHandling.ALWAYS
|
||||
|
||||
|
||||
LOCALE_CONFIG: dict[str, LocaleConfig] = {
|
||||
"af-ZA": LocaleConfig(name="Afrikaans (Afrikaans)"),
|
||||
"ar-SA": LocaleConfig(name="العربية (Arabic)", dir=LocaleTextDirection.RTL),
|
||||
"bg-BG": LocaleConfig(name="Български (Bulgarian)"),
|
||||
"ca-ES": LocaleConfig(name="Català (Catalan)"),
|
||||
"cs-CZ": LocaleConfig(name="Čeština (Czech)"),
|
||||
"da-DK": LocaleConfig(name="Dansk (Danish)"),
|
||||
"de-DE": LocaleConfig(name="Deutsch (German)"),
|
||||
"el-GR": LocaleConfig(name="Ελληνικά (Greek)"),
|
||||
"en-GB": LocaleConfig(name="British English", plural_food_handling=LocalePluralFoodHandling.WITHOUT_UNIT),
|
||||
"en-US": LocaleConfig(name="American English", plural_food_handling=LocalePluralFoodHandling.WITHOUT_UNIT),
|
||||
"es-ES": LocaleConfig(name="Español (Spanish)"),
|
||||
"et-EE": LocaleConfig(name="Eesti (Estonian)"),
|
||||
"fi-FI": LocaleConfig(name="Suomi (Finnish)"),
|
||||
"fr-BE": LocaleConfig(name="Belge (Belgian)"),
|
||||
"fr-CA": LocaleConfig(name="Français canadien (Canadian French)"),
|
||||
"fr-FR": LocaleConfig(name="Français (French)"),
|
||||
"gl-ES": LocaleConfig(name="Galego (Galician)"),
|
||||
"he-IL": LocaleConfig(name="עברית (Hebrew)", dir=LocaleTextDirection.RTL),
|
||||
"hr-HR": LocaleConfig(name="Hrvatski (Croatian)"),
|
||||
"hu-HU": LocaleConfig(name="Magyar (Hungarian)"),
|
||||
"is-IS": LocaleConfig(name="Íslenska (Icelandic)"),
|
||||
"it-IT": LocaleConfig(name="Italiano (Italian)"),
|
||||
"ja-JP": LocaleConfig(name="日本語 (Japanese)", plural_food_handling=LocalePluralFoodHandling.NEVER),
|
||||
"ko-KR": LocaleConfig(name="한국어 (Korean)", plural_food_handling=LocalePluralFoodHandling.NEVER),
|
||||
"lt-LT": LocaleConfig(name="Lietuvių (Lithuanian)"),
|
||||
"lv-LV": LocaleConfig(name="Latviešu (Latvian)"),
|
||||
"nl-NL": LocaleConfig(name="Nederlands (Dutch)"),
|
||||
"no-NO": LocaleConfig(name="Norsk (Norwegian)"),
|
||||
"pl-PL": LocaleConfig(name="Polski (Polish)"),
|
||||
"pt-BR": LocaleConfig(name="Português do Brasil (Brazilian Portuguese)"),
|
||||
"pt-PT": LocaleConfig(name="Português (Portuguese)"),
|
||||
"ro-RO": LocaleConfig(name="Română (Romanian)"),
|
||||
"ru-RU": LocaleConfig(name="Pусский (Russian)"),
|
||||
"sk-SK": LocaleConfig(name="Slovenčina (Slovak)"),
|
||||
"sl-SI": LocaleConfig(name="Slovenščina (Slovenian)"),
|
||||
"sr-SP": LocaleConfig(name="српски (Serbian)"),
|
||||
"sv-SE": LocaleConfig(name="Svenska (Swedish)"),
|
||||
"tr-TR": LocaleConfig(name="Türkçe (Turkish)", plural_food_handling=LocalePluralFoodHandling.NEVER),
|
||||
"uk-UA": LocaleConfig(name="Українська (Ukrainian)"),
|
||||
"vi-VN": LocaleConfig(name="Tiếng Việt (Vietnamese)", plural_food_handling=LocalePluralFoodHandling.NEVER),
|
||||
"zh-CN": LocaleConfig(name="简体中文 (Chinese simplified)", plural_food_handling=LocalePluralFoodHandling.NEVER),
|
||||
"zh-TW": LocaleConfig(name="繁體中文 (Chinese traditional)", plural_food_handling=LocalePluralFoodHandling.NEVER),
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
from abc import abstractmethod
|
||||
from contextvars import ContextVar
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Protocol
|
||||
|
||||
from fastapi import Header
|
||||
|
||||
from mealie.lang.locale_config import LOCALE_CONFIG, LocaleConfig
|
||||
from mealie.pkgs import i18n
|
||||
|
||||
CWD = Path(__file__).parent
|
||||
@@ -17,6 +19,19 @@ class Translator(Protocol):
|
||||
pass
|
||||
|
||||
|
||||
_locale_context: ContextVar[tuple[Translator, LocaleConfig] | None] = ContextVar("locale_context", default=None)
|
||||
|
||||
|
||||
def set_locale_context(translator: Translator, locale_config: LocaleConfig) -> None:
|
||||
"""Set the locale context for the current request"""
|
||||
_locale_context.set((translator, locale_config))
|
||||
|
||||
|
||||
def get_locale_context() -> tuple[Translator, LocaleConfig] | None:
|
||||
"""Get the current locale context"""
|
||||
return _locale_context.get()
|
||||
|
||||
|
||||
@lru_cache
|
||||
def _load_factory() -> i18n.ProviderFactory:
|
||||
return i18n.ProviderFactory(
|
||||
@@ -25,12 +40,19 @@ def _load_factory() -> i18n.ProviderFactory:
|
||||
)
|
||||
|
||||
|
||||
def local_provider(accept_language: str | None = Header(None)) -> Translator:
|
||||
def get_locale_provider(accept_language: str | None = Header(None)) -> Translator:
|
||||
factory = _load_factory()
|
||||
accept_language = accept_language or "en-US"
|
||||
return factory.get(accept_language)
|
||||
|
||||
|
||||
def get_locale_config(accept_language: str | None = Header(None)) -> LocaleConfig:
|
||||
if accept_language and accept_language in LOCALE_CONFIG:
|
||||
return LOCALE_CONFIG[accept_language]
|
||||
else:
|
||||
return LOCALE_CONFIG["en-US"]
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_all_translations(key: str) -> dict[str, str]:
|
||||
factory = _load_factory()
|
||||
|
||||
Reference in New Issue
Block a user