|
1 | | -import babel |
2 | | -import babel.numbers |
3 | | -import babel.plural |
4 | | - |
5 | 1 | from fluent.syntax import FluentParser |
6 | | -from fluent.syntax.ast import Message, Term |
7 | 2 |
|
8 | | -from .builtins import BUILTINS |
9 | | -from .prepare import Compiler |
10 | | -from .resolver import ResolverEnvironment, CurrentEnvironment |
11 | | -from .utils import native_to_fluent |
| 3 | +from .bundle import FluentBundle |
12 | 4 | from .fallback import FluentLocalization, AbstractResourceLoader, FluentResourceLoader |
13 | 5 |
|
14 | 6 |
|
|
24 | 16 | def FluentResource(source): |
25 | 17 | parser = FluentParser() |
26 | 18 | return parser.parse(source) |
27 | | - |
28 | | - |
29 | | -class FluentBundle: |
30 | | - """ |
31 | | - Bundles are single-language stores of translations. They are |
32 | | - aggregate parsed Fluent resources in the Fluent syntax and can |
33 | | - format translation units (entities) to strings. |
34 | | -
|
35 | | - Always use `FluentBundle.get_message` to retrieve translation units from |
36 | | - a bundle. Generate the localized string by using `format_pattern` on |
37 | | - `message.value` or `message.attributes['attr']`. |
38 | | - Translations can contain references to other entities or |
39 | | - external arguments, conditional logic in form of select expressions, traits |
40 | | - which describe their grammatical features, and can use Fluent builtins. |
41 | | - See the documentation of the Fluent syntax for more information. |
42 | | - """ |
43 | | - |
44 | | - def __init__(self, locales, functions=None, use_isolating=True): |
45 | | - self.locales = locales |
46 | | - _functions = BUILTINS.copy() |
47 | | - if functions: |
48 | | - _functions.update(functions) |
49 | | - self._functions = _functions |
50 | | - self.use_isolating = use_isolating |
51 | | - self._messages = {} |
52 | | - self._terms = {} |
53 | | - self._compiled = {} |
54 | | - self._compiler = Compiler() |
55 | | - self._babel_locale = self._get_babel_locale() |
56 | | - self._plural_form = babel.plural.to_python(self._babel_locale.plural_form) |
57 | | - |
58 | | - def add_resource(self, resource, allow_overrides=False): |
59 | | - # TODO - warn/error about duplicates |
60 | | - for item in resource.body: |
61 | | - if not isinstance(item, (Message, Term)): |
62 | | - continue |
63 | | - map_ = self._messages if isinstance(item, Message) else self._terms |
64 | | - full_id = item.id.name |
65 | | - if full_id not in map_ or allow_overrides: |
66 | | - map_[full_id] = item |
67 | | - |
68 | | - def has_message(self, message_id): |
69 | | - return message_id in self._messages |
70 | | - |
71 | | - def get_message(self, message_id): |
72 | | - return self._lookup(message_id) |
73 | | - |
74 | | - def _lookup(self, entry_id, term=False): |
75 | | - if term: |
76 | | - compiled_id = '-' + entry_id |
77 | | - else: |
78 | | - compiled_id = entry_id |
79 | | - try: |
80 | | - return self._compiled[compiled_id] |
81 | | - except LookupError: |
82 | | - pass |
83 | | - entry = self._terms[entry_id] if term else self._messages[entry_id] |
84 | | - self._compiled[compiled_id] = self._compiler(entry) |
85 | | - return self._compiled[compiled_id] |
86 | | - |
87 | | - def format_pattern(self, pattern, args=None): |
88 | | - if args is not None: |
89 | | - fluent_args = { |
90 | | - argname: native_to_fluent(argvalue) |
91 | | - for argname, argvalue in args.items() |
92 | | - } |
93 | | - else: |
94 | | - fluent_args = {} |
95 | | - |
96 | | - errors = [] |
97 | | - env = ResolverEnvironment(context=self, |
98 | | - current=CurrentEnvironment(args=fluent_args), |
99 | | - errors=errors) |
100 | | - try: |
101 | | - result = pattern(env) |
102 | | - except ValueError as e: |
103 | | - errors.append(e) |
104 | | - result = '{???}' |
105 | | - return [result, errors] |
106 | | - |
107 | | - def _get_babel_locale(self): |
108 | | - for lc in self.locales: |
109 | | - try: |
110 | | - return babel.Locale.parse(lc.replace('-', '_')) |
111 | | - except babel.UnknownLocaleError: |
112 | | - continue |
113 | | - # TODO - log error |
114 | | - return babel.Locale.default() |
0 commit comments