Skip to content
Snippets Groups Projects
Commit 02eab9709d6d authored by Vincent Hatakeyama's avatar Vincent Hatakeyama
Browse files

:sparkles: add a list formatter and a locale cache

parent d766745524f8
No related branches found
No related tags found
1 merge request!2✨ add a list formatter and a locale cache
Pipeline #15059 passed
from .hooks import post_load # noqa: F401
from .icu_format import icu_format # noqa: F401
from .icu_format import icu_format, icu_list_format # noqa: F401
from .logger import get_logger # noqa: F401
......@@ -24,7 +24,7 @@
from odoo import _
from odoo.models import BaseModel
from .icu_format import icu_format
from .icu_format import icu_format, icu_list_format
from babel.messages import extract
from icu import ICUError
......@@ -90,5 +90,10 @@
)
return icu_format("C", untranslated_message, args, raise_exception)
def model_icu_list_format(self, list_data: list) -> str:
return icu_list_format(
self.env.context.get("lang") or self.env.user.lang, list_data
)
setattr(BaseModel, "icu_format", model_icu_format)
setattr(BaseModel, ICU_FORMAT_TRANSLATE, model_icu_format_translate)
......@@ -93,5 +98,6 @@
setattr(BaseModel, "icu_format", model_icu_format)
setattr(BaseModel, ICU_FORMAT_TRANSLATE, model_icu_format_translate)
setattr(BaseModel, "icu_list_format", model_icu_list_format)
def __patch_babel_extract():
......
......@@ -20,7 +20,21 @@
import datetime
from typing import Dict, Optional, Union
from icu import Formattable, ICUError, Locale, MessageFormat
from icu import Formattable, ICUError, ListFormatter, Locale, MessageFormat
class Cache:
def __init__(self, factory):
self.__data = dict()
self.__factory = factory
def __getitem__(self, item):
if item not in self.__data:
self.__data[item] = self.__factory(item)
return self.__data[item]
__locale_cache = Cache(Locale)
def icu_format(
......@@ -40,7 +54,7 @@
return the original message without formatting
:return: formatted message
"""
# TODO cache the MessageFormat somehow
# TODO cache the MessageFormat somehow, maybe using @lru_cache
key_list = list()
value_list = list()
for key, value in args.items():
......@@ -55,10 +69,10 @@
if not lang:
# Use the neutral locale if nothing is set
lang = "C"
locale = Locale(lang)
locale = __locale_cache[lang]
try:
return MessageFormat(msg, locale).format(key_list, value_list)
except ICUError:
if raise_exception:
raise
return msg
......@@ -59,6 +73,21 @@
try:
return MessageFormat(msg, locale).format(key_list, value_list)
except ICUError:
if raise_exception:
raise
return msg
__list_formatter_cache = Cache(
lambda lang: ListFormatter.createInstance(__locale_cache[lang])
)
def icu_list_format(lang: str, list_data: list) -> str:
"""Format a list using ICU ListFormatter
:param lang: the lang to use
:param list_data: The list of elements to format
:return: formatted message
"""
return __list_formatter_cache[lang].format(list_data)
......@@ -21,7 +21,7 @@
from odoo import tests
from odoo.addons.icuformat import icu_format
from odoo.addons.icuformat import icu_format, icu_list_format
class Test(tests.TransactionCase):
......@@ -112,3 +112,13 @@
self.assertEqual(
"A message", user.icu_format_translate("A message", dict())
)
def test_list_format(self):
"""Test the list formatter provided on BaseModel.
"""
self.assertEqual(icu_list_format("fr", ["a", "b", "c"]), "a, b et c")
self.assertEqual(
icu_list_format("en_GB", ["1", "2", "5"]), "1, 2 and 5"
)
user = self.env["res.users"].search([], limit=1)
self.assertEqual(user.icu_list_format(["1", "2", "5"]), "1, 2, and 5")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment