"""
Provide the Locale API.
"""
from __future__ import annotations
from typing import Sequence, TypeAlias
from babel import Locale, negotiate_locale as babel_negotiate_locale
from langcodes import Language
from betty import fs
DEFAULT_LOCALE = "en-US"
UNDETERMINED_LOCALE = "und"
_LOCALE_DIRECTORY_PATH = fs.ASSETS_DIRECTORY_PATH / "locale"
[docs]
class LocaleNotFoundError(RuntimeError):
"""
Raise when a locale could not be found.
"""
[docs]
def to_babel_identifier(locale: Localey) -> str:
"""
Convert a locale or locale metadata to a Babel locale identifier.
"""
if isinstance(locale, Locale):
return str(locale)
language_data = Language.get(locale)
return "_".join(
part
for part in [
language_data.language,
language_data.script,
language_data.territory,
]
if part
)
[docs]
def to_locale(locale: Localey) -> str:
"""
Ensure that a locale or locale metadata is a locale.
"""
if isinstance(locale, str):
return locale
return "-".join(
part
for part in [
locale.language,
locale.script,
locale.territory,
]
if part
)
Localey: TypeAlias = str | Locale
[docs]
def get_data(locale: Localey) -> Locale:
"""
Get locale metadata.
:raises betty.locale.LocaleNotFoundError: Raised if the given locale cannot be found.
"""
if isinstance(locale, Locale):
return locale
try:
return Locale.parse(to_babel_identifier(locale))
except Exception as e:
raise LocaleNotFoundError(locale) from e