byceps.util.l10n   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Test Coverage

Coverage 93.02%

Importance

Changes 0
Metric Value
eloc 44
dl 0
loc 94
ccs 40
cts 43
cp 0.9302
rs 10
c 0
b 0
f 0
wmc 14

7 Functions

Rating   Name   Duplication   Size   Complexity  
A get_current_user_locale() 0 13 4
A get_locales() 0 3 1
A force_user_locale() 0 6 2
A get_user_locale() 0 7 1
A get_default_locale() 0 3 1
A format_money() 0 3 1
A get_locale_str() 0 14 3

1 Method

Rating   Name   Duplication   Size   Complexity  
A LocalizedForm.__init__() 0 4 1
1
"""
2
byceps.util.l10n
3
~~~~~~~~~~~~~~~~
4
5
Localization.
6
7
:Copyright: 2014-2024 Jochen Kupperschmidt
8
:License: Revised BSD (see `LICENSE` file for details)
9
"""
10
11 1
from collections.abc import Iterator
12
from contextlib import contextmanager
13 1
14 1
from babel import Locale
15
from flask import current_app, g, request
16 1
from flask_babel import force_locale, format_currency, get_locale
17 1
from moneyed import Money
18 1
from wtforms import Form
19 1
20 1
from byceps.services.user.models.user import User
21
22 1
23
def get_current_user_locale() -> str | None:
24
    """Return the locale for the current user, if available."""
25 1
    # Look for a locale on the current user object.
26
    user = g.user
27
    if (user is not None) and (user.locale is not None):
28 1
        return user.locale
29 1
30 1
    if request:
31
        # Try to match user agent's accepted languages.
32 1
        languages = [locale.language for locale in g.locales]
33
        return request.accept_languages.best_match(languages)
34 1
35 1
    return None
36
37
38
@contextmanager
39
def force_user_locale(user: User) -> Iterator[None]:
40 1
    """Execute code with the user's preferred locale."""
41 1
    locale = get_user_locale(user)
42
    with force_locale(locale):
43 1
        yield
44 1
45 1
46
def get_default_locale() -> str:
47
    """Return the application's default locale."""
48 1
    return current_app.config['LOCALE']
49
50 1
51
def get_user_locale(user: User) -> str:
52
    """Return the user's preferred locale.
53 1
54
    If no preference is set for the user, return the app's default
55
    locale.
56
    """
57
    return user.locale or get_default_locale()
58
59 1
60
BASE_LOCALE = Locale('en')
61
62 1
63
def get_locales() -> list[Locale]:
64
    """List available locales."""
65 1
    return [BASE_LOCALE] + current_app.babel_instance.list_translations()
66
67 1
68
def get_locale_str() -> str | None:
69
    """Return the current locale as a string.
70 1
71
    Return `None` outside of a request.
72
    """
73
    locale = get_locale()
74
    if locale is None:
75 1
        return None
76 1
77
    locale_str = locale.language
78
    if locale.territory:
79 1
        locale_str += '_' + locale.territory
80 1
81
    return locale_str
82
83 1
84
class LocalizedForm(Form):
85
    def __init__(self, *args, **kwargs):
86 1
        locales = current_app.config['LOCALES_FORMS']
87 1
        kwargs['meta'] = {'locales': locales}
88 1
        super().__init__(*args, **kwargs)
89 1
90 1
91
def format_money(money: Money) -> str:
92
    """Format monetary value with amount and currency."""
93
    return format_currency(money.amount, money.currency.code)
94