| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- from __future__ import annotations
- import re
- from importlib import import_module
- from pathlib import Path
- from typing import Any
- from typing import ClassVar
- from typing import Dict
- from typing import cast
- from pendulum.utils._compat import resources
- class Locale:
- """
- Represent a specific locale.
- """
- _cache: ClassVar[dict[str, Locale]] = {}
- def __init__(self, locale: str, data: Any) -> None:
- self._locale: str = locale
- self._data: Any = data
- self._key_cache: dict[str, str] = {}
- @classmethod
- def load(cls, locale: str | Locale) -> Locale:
- if isinstance(locale, Locale):
- return locale
- locale = cls.normalize_locale(locale)
- if locale in cls._cache:
- return cls._cache[locale]
- # Checking locale existence
- actual_locale = locale
- locale_path = cast(Path, resources.files(__package__).joinpath(actual_locale))
- while not locale_path.exists():
- if actual_locale == locale:
- raise ValueError(f"Locale [{locale}] does not exist.")
- actual_locale = actual_locale.split("_")[0]
- m = import_module(f"pendulum.locales.{actual_locale}.locale")
- cls._cache[locale] = cls(locale, m.locale)
- return cls._cache[locale]
- @classmethod
- def normalize_locale(cls, locale: str) -> str:
- m = re.match("([a-z]{2})[-_]([a-z]{2})", locale, re.I)
- if m:
- return f"{m.group(1).lower()}_{m.group(2).lower()}"
- else:
- return locale.lower()
- def get(self, key: str, default: Any | None = None) -> Any:
- if key in self._key_cache:
- return self._key_cache[key]
- parts = key.split(".")
- try:
- result = self._data[parts[0]]
- for part in parts[1:]:
- result = result[part]
- except KeyError:
- result = default
- self._key_cache[key] = result
- return self._key_cache[key]
- def translation(self, key: str) -> Any:
- return self.get(f"translations.{key}")
- def plural(self, number: int) -> str:
- return cast(str, self._data["plural"](number))
- def ordinal(self, number: int) -> str:
- return cast(str, self._data["ordinal"](number))
- def ordinalize(self, number: int) -> str:
- ordinal = self.get(f"custom.ordinal.{self.ordinal(number)}")
- if not ordinal:
- return f"{number}"
- return f"{number}{ordinal}"
- def match_translation(self, key: str, value: Any) -> dict[str, str] | None:
- translations = self.translation(key)
- if value not in translations.values():
- return None
- return cast(Dict[str, str], {v: k for k, v in translations.items()}[value])
- def __repr__(self) -> str:
- return f"{self.__class__.__name__}('{self._locale}')"
|