1# coding=utf8
2from __future__ import unicode_literals
3from __future__ import absolute_import
4
5import fluent.syntax.ast as FTL
6
7from .errors import SkipTransform
8from .transforms import evaluate
9from .util import get_message, get_transform
10
11
12def merge_resource(ctx, reference, current, transforms, in_changeset):
13    """Transform legacy translations into FTL.
14
15    Use the `reference` FTL AST as a template.  For each en-US string in the
16    reference, first check for an existing translation in the current FTL
17    `localization` and use it if it's present; then if the string has
18    a transform defined in the migration specification and if it's in the
19    currently processed changeset, evaluate the transform.
20    """
21
22    def merge_body(body):
23        return [
24            entry
25            for entry in map(merge_entry, body)
26            if entry is not None
27        ]
28
29    def merge_entry(entry):
30        # All standalone comments will be merged.
31        if isinstance(entry, FTL.BaseComment):
32            return entry
33
34        # Ignore Junk
35        if isinstance(entry, FTL.Junk):
36            return None
37
38        ident = entry.id.name
39
40        # If the message is present in the existing localization, we add it to
41        # the resulting resource.  This ensures consecutive merges don't remove
42        # translations but rather create supersets of them.
43        existing = get_message(current.body, ident)
44        if existing is not None:
45            return existing
46
47        transform = get_transform(transforms, ident)
48
49        # Make sure this message is supposed to be migrated as part of the
50        # current changeset.
51        if transform is not None and in_changeset(ident):
52            if transform.comment is None:
53                transform.comment = entry.comment
54            try:
55                return evaluate(ctx, transform)
56            except SkipTransform:
57                return None
58
59    body = merge_body(reference.body)
60    return FTL.Resource(body)
61