Skip to content

Commit 60e7be4

Browse files
committed
runtime: Split FluentBundle to bundle.py to avoid circular imports
1 parent cda9de6 commit 60e7be4

File tree

2 files changed

+99
-97
lines changed

2 files changed

+99
-97
lines changed
Lines changed: 1 addition & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
import babel
2-
import babel.numbers
3-
import babel.plural
4-
51
from fluent.syntax import FluentParser
6-
from fluent.syntax.ast import Message, Term
72

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
124
from .fallback import FluentLocalization, AbstractResourceLoader, FluentResourceLoader
135

146

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

0 commit comments

Comments
 (0)