tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fluent.rst (4296B)


      1 .. role:: bash(code)
      2   :language: bash
      3 
      4 .. role:: js(code)
      5   :language: javascript
      6 
      7 .. role:: python(code)
      8   :language: python
      9 
     10 
     11 ===========================
     12 Fluent to Fluent Migrations
     13 ===========================
     14 
     15 When migrating existing Fluent messages,
     16 it's possible to copy a source directly with :python:`COPY_PATTERN`,
     17 or to apply string replacements and other changes
     18 by extending the :python:`TransformPattern` visitor class.
     19 
     20 These transforms work with individual Fluent patterns,
     21 i.e. the body of a Fluent message or one of its attributes.
     22 
     23 Copying Fluent Patterns
     24 -----------------------
     25 
     26 Consider for example a patch modifying an existing message to move the original
     27 value to a :js:`alt` attribute.
     28 
     29 Original message:
     30 
     31 
     32 .. code-block:: fluent
     33 
     34  about-logins-icon = Warning icon
     35      .title = Breached website
     36 
     37 
     38 New message:
     39 
     40 
     41 .. code-block:: fluent
     42 
     43  about-logins-breach-icon =
     44      .alt = Warning icon
     45      .title = Breached website
     46 
     47 
     48 This type of changes requires a new message identifier, which in turn causes
     49 existing translations to be lost. It’s possible to migrate the existing
     50 translated content with:
     51 
     52 
     53 .. code-block:: python
     54 
     55    from fluent.migrate import COPY_PATTERN
     56 
     57    ctx.add_transforms(
     58        "browser/browser/aboutLogins.ftl",
     59        "browser/browser/aboutLogins.ftl",
     60        transforms_from(
     61    """
     62    about-logins-breach-icon =
     63        .alt = {COPY_PATTERN(from_path, "about-logins-icon")}
     64        .title = {COPY_PATTERN(from_path, "about-logins-icon.title")}
     65    """,from_path="browser/browser/aboutLogins.ftl"),
     66    )
     67 
     68 
     69 In this specific case, the destination and source files are the same. The dot
     70 notation is used to access attributes: :js:`about-logins-icon.title` matches
     71 the :js:`title` attribute of the message with identifier
     72 :js:`about-logins-icon`, while :js:`about-logins-icon` alone matches the value
     73 of the message.
     74 
     75 
     76 .. warning::
     77 
     78  The second argument of :python:`COPY_PATTERN` and :python:`TransformPattern`
     79  identifies a pattern, so using the message identifier will not
     80  migrate the message as a whole, with all its attributes, only its value.
     81 
     82 Transforming Fluent Patterns
     83 ----------------------------
     84 
     85 To apply changes to Fluent messages, you may extend the
     86 :python:`TransformPattern` class to create your transformation.
     87 This is a powerful general-purpose tool, of which :python:`COPY_PATTERN` is the
     88 simplest extension that applies no transformation to the source.
     89 
     90 Consider for example a patch copying an existing message to strip out its HTML
     91 content to use as an ARIA value.
     92 
     93 Original message:
     94 
     95 
     96 .. code-block:: fluent
     97 
     98  videocontrols-label =
     99      { $position }<span data-l10n-name="duration"> / { $duration }</span>
    100 
    101 
    102 New message:
    103 
    104 
    105 .. code-block:: fluent
    106 
    107  videocontrols-scrubber =
    108      .aria-valuetext = { $position } / { $duration }
    109 
    110 
    111 A migration may be applied to create this new message with:
    112 
    113 
    114 .. code-block:: python
    115 
    116    from fluent.migrate.transforms import TransformPattern
    117    import fluent.syntax.ast as FTL
    118 
    119    class STRIP_SPAN(TransformPattern):
    120        def visit_TextElement(self, node):
    121            node.value = re.sub("</?span[^>]*>", "", node.value)
    122            return node
    123 
    124    def migrate(ctx):
    125        path = "toolkit/toolkit/global/videocontrols.ftl"
    126        ctx.add_transforms(
    127            path,
    128            path,
    129            [
    130                FTL.Message(
    131                    id=FTL.Identifier("videocontrols-scrubber"),
    132                    attributes=[
    133                        FTL.Attribute(
    134                            id=FTL.Identifier("aria-valuetext"),
    135                            value=STRIP_SPAN(path, "videocontrols-label"),
    136                        ),
    137                    ],
    138                ),
    139            ],
    140        )
    141 
    142 
    143 Note that a custom extension such as :python:`STRIP_SPAN` is not supported by
    144 the :python:`transforms_from` utility, so the list of transforms needs to be
    145 defined explicitly.
    146 
    147 Internally, :python:`TransformPattern` extends the `fluent.syntax`__
    148 :python:`Transformer`, which defines the :python:`FTL` AST used here.
    149 As a specific convenience, pattern element visitors such as
    150 :python:`visit_TextElement` are allowed to return a :python:`FTL.Pattern`
    151 to replace themselves with more than one node.
    152 
    153 __ https://projectfluent.org/python-fluent/fluent.syntax/stable/