1
|
|
|
""" |
2
|
|
|
byceps.util.l10n |
3
|
|
|
~~~~~~~~~~~~~~~~ |
4
|
|
|
|
5
|
|
|
Localization. |
6
|
|
|
|
7
|
|
|
:Copyright: 2006-2021 Jochen Kupperschmidt |
8
|
|
|
:License: Revised BSD (see `LICENSE` file for details) |
9
|
|
|
""" |
10
|
|
|
|
11
|
1 |
|
from __future__ import annotations |
12
|
1 |
|
from contextlib import contextmanager |
13
|
1 |
|
import locale |
14
|
1 |
|
from typing import Iterator, Optional |
15
|
|
|
import warnings |
16
|
1 |
|
|
17
|
1 |
|
from babel import Locale |
18
|
1 |
|
from flask import current_app, g, request |
19
|
|
|
from flask_babel import force_locale |
20
|
|
|
from wtforms import Form |
21
|
1 |
|
|
22
|
1 |
|
from ..services.user.transfer.models import User |
23
|
1 |
|
|
24
|
1 |
|
|
25
|
1 |
|
def set_locale(locale_str: str) -> None: |
26
|
|
|
try: |
27
|
|
|
locale.setlocale(locale.LC_ALL, locale_str) |
28
|
1 |
|
except locale.Error: |
29
|
|
|
warnings.warn(f'Could not set locale to "{locale_str}".') |
30
|
|
|
|
31
|
1 |
|
|
32
|
1 |
|
def get_current_user_locale() -> Optional[str]: |
33
|
|
|
"""Return the locale for the current user, if available.""" |
34
|
|
|
# Look for a locale on the current user object. |
35
|
1 |
|
user = getattr(g, 'user') |
36
|
|
|
if (user is not None) and (user.locale is not None): |
37
|
1 |
|
return user.locale |
38
|
1 |
|
|
39
|
|
|
if request: |
40
|
1 |
|
# Try to match user agent's accepted languages. |
41
|
|
|
languages = [locale.language for locale in get_locales()] |
42
|
|
|
return request.accept_languages.best_match(languages) |
43
|
1 |
|
|
44
|
|
|
return None |
45
|
|
|
|
46
|
1 |
|
|
47
|
|
|
@contextmanager |
48
|
1 |
|
def force_user_locale(user: User) -> Iterator[None]: |
49
|
|
|
"""Execute code with the user's preferred locale.""" |
50
|
|
|
locale = get_user_locale(user) |
51
|
1 |
|
with force_locale(locale): |
52
|
|
|
yield |
53
|
1 |
|
|
54
|
1 |
|
|
55
|
1 |
|
def get_user_locale(user: User) -> str: |
56
|
1 |
|
"""Return the user's preferred locale. |
57
|
|
|
|
58
|
|
|
If no preference is set for the user, return the app's default |
59
|
|
|
locale. |
60
|
|
|
""" |
61
|
|
|
return user.locale or current_app.config['LOCALE'] |
62
|
|
|
|
63
|
|
|
|
64
|
|
|
BASE_LOCALE = Locale('en') |
65
|
|
|
|
66
|
|
|
|
67
|
|
|
def get_locales() -> list[Locale]: |
68
|
|
|
"""List available locales.""" |
69
|
|
|
return [BASE_LOCALE] + current_app.babel_instance.list_translations() |
70
|
|
|
|
71
|
|
|
|
72
|
|
|
class LocalizedForm(Form): |
73
|
|
|
|
74
|
|
|
def __init__(self, *args, **kwargs): |
75
|
|
|
locales = current_app.config['LOCALES_FORMS'] |
76
|
|
|
kwargs['meta'] = {'locales': locales} |
77
|
|
|
super().__init__(*args, **kwargs) |
78
|
|
|
|