|
- from __future__ import annotations
-
- import re
- from typing import TYPE_CHECKING, Literal, Optional, Sequence
-
- from babel import lists
-
- from odoo.tools.misc import babel_locale_parse, get_lang
-
- if TYPE_CHECKING:
- import odoo.api
-
- XPG_LOCALE_RE = re.compile(
- r"""^
- ([a-z]+) # language
- (_[A-Z\d]+)? # maybe _territory
- # no support for .codeset (we don't use that in Odoo)
- (@.+)? # maybe @modifier
- $""",
- re.VERBOSE,
- )
-
-
- def format_list(
- env: odoo.api.Environment,
- lst: Sequence[str],
- style: Literal["standard", "standard-short", "or", "or-short", "unit", "unit-short", "unit-narrow"] = "standard",
- lang_code: Optional[str] = None,
- ) -> str:
- """
- Format the items in `lst` as a list in a locale-dependent manner with the chosen style.
-
- The available styles are defined by babel according to the Unicode TR35-49 spec:
- * standard:
- A typical 'and' list for arbitrary placeholders.
- e.g. "January, February, and March"
- * standard-short:
- A short version of an 'and' list, suitable for use with short or abbreviated placeholder values.
- e.g. "Jan., Feb., and Mar."
- * or:
- A typical 'or' list for arbitrary placeholders.
- e.g. "January, February, or March"
- * or-short:
- A short version of an 'or' list.
- e.g. "Jan., Feb., or Mar."
- * unit:
- A list suitable for wide units.
- e.g. "3 feet, 7 inches"
- * unit-short:
- A list suitable for short units
- e.g. "3 ft, 7 in"
- * unit-narrow:
- A list suitable for narrow units, where space on the screen is very limited.
- e.g. "3′ 7″"
-
- See https://www.unicode.org/reports/tr35/tr35-49/tr35-general.html#ListPatterns for more details.
-
- :param env: the current environment.
- :param lst: the sequence of items to format into a list.
- :param style: the style to format the list with.
- :param lang_code: the locale (i.e. en_US).
- :return: the formatted list.
- """
- locale = babel_locale_parse(lang_code or get_lang(env).code)
- # Some styles could be unavailable for the chosen locale
- if style not in locale.list_patterns:
- style = "standard"
- return lists.format_list(lst, style, locale)
-
-
- def py_to_js_locale(locale: str) -> str:
- """
- Converts a locale from Python to JavaScript format.
-
- Most of the time the conversion is simply to replace _ with -.
- Example: fr_BE → fr-BE
-
- Exception: Serbian can be written in both Latin and Cyrillic scripts
- interchangeably, therefore its locale includes a special modifier
- to indicate which script to use.
- Example: sr@latin → sr-Latn
-
- BCP 47 (JS):
- language[-extlang][-script][-region][-variant][-extension][-privateuse]
- https://www.ietf.org/rfc/rfc5646.txt
- XPG syntax (Python):
- language[_territory][.codeset][@modifier]
- https://www.gnu.org/software/libc/manual/html_node/Locale-Names.html
-
- :param locale: The locale formatted for use on the Python-side.
- :return: The locale formatted for use on the JavaScript-side.
- """
- match_ = XPG_LOCALE_RE.match(locale)
- if not match_:
- return locale
- language, territory, modifier = match_.groups()
- subtags = [language]
- if modifier == "@Cyrl":
- subtags.append("Cyrl")
- elif modifier == "@latin":
- subtags.append("Latn")
- if territory:
- subtags.append(territory.removeprefix("_"))
- return "-".join(subtags)
|