Bug 1306011 - Document L20n. r?Pike draft
authorStaś Małolepszy <stas@mozilla.com>
Sat, 05 Nov 2016 16:29:50 +0100
changeset 434392 98c603df95d33c73c63cf99c5670a679bb5ea1b6
parent 434391 fbf61bcc0fa52b238d0a88e567a189d00b407613
child 536054 e3f972bb312e73233d8e51fd54372aeeb9eaac9c
push id34757
push usersmalolepszy@mozilla.com
push dateSat, 05 Nov 2016 15:52:49 +0000
reviewersPike
bugs1306011
milestone52.0a1
Bug 1306011 - Document L20n. r?Pike Create a new top-level directory l10n/ for the cross-module documentation about the localization infrastructure and process. MozReview-Commit-ID: 6LQzo0XKovC
l10n/docs/glossary.rst
l10n/docs/index.rst
l10n/docs/l20n.rst
l10n/docs/legacy.rst
l10n/docs/syntax.rst
l10n/moz.build
moz.build
python/compare-locales/docs/glossary.rst
python/compare-locales/docs/index.rst
python/compare-locales/moz.build
rename from python/compare-locales/docs/glossary.rst
rename to l10n/docs/glossary.rst
--- a/python/compare-locales/docs/glossary.rst
+++ b/l10n/docs/glossary.rst
@@ -1,26 +1,36 @@
 ========
 Glossary
 ========
 
+
 .. glossary::
     :sorted:
 
     Localization
         The process of creating content in a native language, including
         translation, but also customizations like Search.
 
     Localizability
         Enabling a piece of software to be localized. This is mostly
         externalizing English strings, and writing build support to 
         pick up localized search engines etc.
 
     L10n
-        *Numeronym* for Localization, *L*, 10 chars, *n*
+        *Numeronym* for Localization, *L* + 10 chars + *n*.
 
     L12y
-        Numeronym for Localizability
+        *Numeronym* for *Localizability*, i.e. the state of being
+        *localizable*.
 
     l10n-merge
-        nick-name for the process of merging ``en-US`` and a particular
+        Nick-name for the process of merging ``en-US`` and a particular
         localization into one joint artifact without any missing strings, and
         without technical errors, as far as possible.
+
+    L20n
+        A word-play on L10n (Localization) and 2.0.  The code name for
+        the localization architecture set to replace DTD and properties files.
+
+    FTL
+        The name of the file format used for describing translation resources
+        in L20n.
new file mode 100644
--- /dev/null
+++ b/l10n/docs/index.rst
@@ -0,0 +1,40 @@
+============
+Localization
+============
+
+
+.. toctree::
+   :maxdepth: 2
+
+   glossary
+   l20n
+   syntax
+   legacy
+
+The documentation here is targeted at developers, writing localizable code
+for Firefox and Firefox for Android, as well as Thunderbird and SeaMonkey.
+
+If you haven't dealt with localization in gecko code before, it's a good
+idea to check the :doc:`./glossary` for what localization is, and which terms
+we use for what.
+
+Existing code is likely localized using the :doc:`./legacy` (DTD and properties
+file formats).  New code should should use the new L20n infrastructure and the
+FTL file format.  Refer to :doc:`l20n` for more information.
+
+
+Where are the localizations?
+----------------------------
+
+Gecko's source code only contains the English localizations (``en-US``).
+
+We host a mercurial repository per locale and per branch. Most of our
+localizations only work starting with aurora, so the bulk of the localizations
+is found on https://hg.mozilla.org/releases/l10n/mozilla-aurora/. We have
+several localizations continuously working with mozilla-central, those
+repositories are on https://hg.mozilla.org/l10n-central/.
+
+You can search inside our localized files on `Transvision`_ and
+http://dxr.mozilla.org/l10n-mozilla-aurora/.
+
+.. _Transvision: https://github.com/l20n/l20n.js/blob/master/docs/syntax.rst
new file mode 100644
--- /dev/null
+++ b/l10n/docs/l20n.rst
@@ -0,0 +1,185 @@
+===================
+Using L20n in Gecko
+===================
+
+L20n is a localization framework for Firefox.  L20n keeps simple things simple 
+and at the same time makes complex things possible.  Users should be able to 
+benefit from the entire expressive power of their language.
+
+
+Using L20n in DOM
+===========================
+
+L20n has been designed as a Web-first technology.  Using it with DOM is as
+simple as including a ``<script>`` element and specifying the translation 
+resources with a ``<link>``.
+
+L20n is most powerful when it’s used declaratively in the DOM. The localization 
+happens on the runtime and gracefully falls back to the next language in case 
+of errors. L20n doesn’t force developers to programmatically create string 
+bundles, request raw strings from them and manually interpolate variables.
+
+Instead, L20n uses a ``MutationObserver`` which is notified about changes to 
+``data-l10n-*`` attributes in the DOM tree. The complexity of the language 
+negotiation, resource loading, error fallback and string interpolation is 
+hidden in the mutation handler. It is still possible to use the JavaScript API 
+to request a translation manually in rare situations when DOM is not available 
+(e.g. OS notifications).
+
+In L20n, broken translations never break the UI. L20n tries its best to display 
+a meaningful message to the user in case of errors. It may try to fall back to 
+the next language preferred by the user if it’s available. As the last resort 
+L20n will show the identifier of the message.
+
+
+Create An FTL Translation Resource
+----------------------------------
+
+Translations for L20n are stored in ``.ftl`` files.  To learn more about
+the FTL file format, see :doc:`./syntax`.
+
+Packaging FTL files in Firefox is done by adding their directory to jar.mn.
+Please only package complete directory structures, and keep the same directory
+layout as in the source.
+
+The top-level directory like ``browser`` is close to where your code is.
+Inside ``browser/locales/en-US``, the first directory clarifies the target
+audience of the feature::
+
+    [localization] @AB_CD@.jar:
+        browser                                        (%browser/**/*.ftl)
+
+
+You can refer to them via the path relative to the locale directory.  This
+is called the Resource Identifier.  For instance, the resource identifier for 
+``browser/locale/en-US/browser/menubar.ftl`` is ``/browser/menubar.ftl``.
+
+
+Link Resources
+--------------
+
+Once you've created the resources include them in the ``<head>`` of your HTML::
+
+    <link rel="localization" href="/browser/about-dialog.ftl">
+    <link rel="localization" href="/browser/new-tab.ftl">
+
+You can group resources under a name with the ``name`` attribute::
+
+    <link rel="localization" name="main" href="/browser/about-dialogftl">
+    <link rel="localization" name="new-tab" href="/browser/new-tab.ftl">
+
+If the ``name`` attribute is not defined, ``main`` is assumed.
+
+
+Link The l20n.js Script
+-----------------------
+
+Finally include the l20n.js script right below the links to resources::
+
+    <link rel="localization" href="/browser/about-dialog.ftl">
+    <link rel="localization" href="/browser/new-tab.ftl">
+    <script src="chrome://global/content/l20n.js"></script>
+
+
+Make DOM Elements Localizable
+-----------------------------
+
+L20n automatically monitors the document DOM tree for changes to localizable 
+elements.  Use the `data-l10n-id` attribute on a node to mark it as localizable::
+
+    <p data-l10n-id="about"></p>
+
+By default, the translations will be looked up in the main `Localization` 
+object.  If needed you can use the `data-l10n-bundle` to specify a different 
+`Localization` object::
+
+    <p data-l10n-id="warning-message" data-l10n-bundle="new-tab"></p>
+
+Notice that you don't have to put the text content in the DOM anymore (you 
+still can if you want to).  All content lives in the localization resources.
+
+Use the `data-l10n-args` attribute to pass additional data into translations 
+which will be interpolated via the `{ }` syntax.  The data should be 
+serialized JSON::
+
+    <h1 data-l10n-id="hello" data-l10n-args='{"username": "Mary"}'></h1>
+
+Given the following translation::
+
+    hello = Hello, { $username }!
+
+…the result will be::
+
+    <h1>Hello, Mary!</h1>
+
+
+DOM Overlays
+============
+
+L20n allows semantic markup in translations. Localizers can use safe text-level 
+DOM elements to create translations which obey the rules of typography and 
+punctuation. Developers can also embed interactive elements inside of 
+translations and attach event handlers to them in the DOM. L20n will
+overlay translations on top of the source DOM tree preserving the identity of 
+elements and the event listeners.
+
+Only a safe subset of HTML elements (e.g. em, sup), attributes (e.g. title) and 
+entities is allowed in translations. In addition to the pre-defined whitelists, 
+any element found in the original source HTML is allowed in the translation as 
+well. Consider the following source HTML::
+
+    <p data-l10n-id="save">
+        <input type="submit">
+        <a
+            href="/main"
+            class="btn-cancel"
+        ></a>
+    </p>
+
+Assume the following malicious translation::
+
+    save =
+        | <input value="Save" type="text"> or
+        | <a
+        |     href="http://myevilwebsite.com"
+        |     onclick="alert('pwnd!')"
+        |     title="Back to the homepage"
+        | >
+        |     cancel
+        | </a>.
+
+The result will be::
+
+    <p data-l10n-id="back">
+        <input value="Save" type="submit"> or
+        <a
+            href="/main"
+            class="btn-cancel"
+            title="Back to the homepage"
+        >
+            cancel
+        </a>.
+    </p>
+
+
+The ``input`` element is not on the default whitelist but since it's present in 
+the source HTML, it is also allowed in the translation. The ``value`` attribute 
+is allowed on ``input`` elements, but ``type`` is not.  Similarly, ``href`` and 
+``onclick`` attributes are not allowed in translations and they are not 
+inserted in the final DOM. However, the ``title`` attribute is safe.
+
+It is important to note that applying translations doesn't replace DOM 
+elements but only modifies their text nodes and their attributes. This makes 
+it possible to use L20n in conjunction with MVC frameworks.
+
+You can learn more about DOM Overlays in the `design document`_.
+
+.. _design document: https://github.com/stasm/spec/blob/master/dom-overlays.markdown
+
+
+The JavaScript API
+==================
+
+It is also possible to use L20n programmatically, for instance in order to 
+localize dynamic content.  The API is exposed on `document.l10n`.  Refer to 
+the API docs in this folder for more information.
rename from python/compare-locales/docs/index.rst
rename to l10n/docs/legacy.rst
--- a/python/compare-locales/docs/index.rst
+++ b/l10n/docs/legacy.rst
@@ -1,23 +1,17 @@
-============
-Localization
-============
-
-.. toctree::
-   :maxdepth: 1
+=====================
+Legacy Infrastructure
+=====================
 
-   glossary
+This document describes the legacy localization infrastructure used in Gecko
+before 2016.  Unless it has been ported to L20n, existing code still uses this
+legacy architecture.  New code should should use the new L20n infrastructure
+and the FTL file format.  Refer to :doc:`l20n` for more information.
 
-The documentation here is targeted at developers, writing localizable code
-for Firefox and Firefox for Android, as well as Thunderbird and SeaMonkey.
-
-If you haven't dealt with localization in gecko code before, it's a good
-idea to check the :doc:`./glossary` for what localization is, and which terms
-we use for what.
 
 Exposing strings
 ----------------
 
 Localizers only handle a few file formats in well-known locations in the
 source tree.
 
 The locations are in directories like
@@ -168,24 +162,8 @@ Android
 
 For Android, we need to localize :file:`strings.xml`. We're doing so via DTD
 files, which is mostly OK. But the strings inside the XML file have to
 satisfy additional constraints about quotes etc, that are not part of XML.
 There's probably some historic background on why things are the way they are.
 
 The Android-specific checks are enabled for DTD files that are in
 :file:`mobile/android/base/locales/en-US/`.
-
-Localizations
--------------
-
-Now that we talked in-depth about how to expose content to localizers,
-where are the localizations?
-
-We host a mercurial repository per locale and per branch. Most of our
-localizations only work starting with aurora, so the bulk of the localizations
-is found on https://hg.mozilla.org/releases/l10n/mozilla-aurora/. We have
-several localizations continuously working with mozilla-central, those
-repositories are on https://hg.mozilla.org/l10n-central/.
-
-You can search inside our localized files on
-`Transvision <https://transvision.mozfr.org/>`_ and
-http://dxr.mozilla.org/l10n-mozilla-aurora/.
new file mode 100644
--- /dev/null
+++ b/l10n/docs/syntax.rst
@@ -0,0 +1,410 @@
+===========================
+The Guide to the FTL Syntax
+===========================
+
+FTL is a localization file format used for describing translation resources.
+
+FTL is designed to be simple to read, but at the same time allows to represent
+complex concepts from natural languages like gender, plurals, conjugations,
+and others.
+
+The following chapters will demonstrate how to use FTL to solve localization 
+challenges. Each chapter contains a hands-on example of simple FTL concepts.
+
+
+Hello World
+===========
+
+In FTL, software refers to messages in a given language through unique
+identifiers.
+
+::
+
+    hello = Hello, World!
+
+This is an entity called ``hello``. Entities are containers for information. 
+You use entities to identify, store, and recall information to be used in the 
+software's UI.
+
+In its simplest form, an entity has just a single string value; here *Hello,
+World!*. Most of the entities you will work with in FTL will look similar to 
+this. Some will be more complex, have more than one value variant, or use 
+expressions to select the right variant depending on the circumstances.
+
+
+Working With Text: Multiline, Quote Delimited Strings
+=====================================================
+
+::
+
+    about        = About Our Software
+    description  =
+        | Loki is a simple micro-blogging
+        | app written entirely in <i>HTML5</i>.
+        | It uses FTL to implement localization.
+    more-info     =   "  Read more about us! "
+
+The value of an FTL entity is usually a simple string.
+
+By default, a string begins after a ``=`` and ends with the end of line.  You 
+can also define easy-to-read, multiline strings with a pipe mark-up, as can be
+seen in the ``description`` entity.
+
+FTL ignores leading whitespaces in front of the value allowing localizers to
+align their messages for readability.
+For multiline strings, whitespaces both before and after the pipe are ignored.
+In rare cases where leading whitespaces should be part of the value, FTL allows
+for special quote delimited strings as can be seen in
+the ``more-info`` entity.
+
+
+Entity References
+=================
+
+::
+
+    brandName = Loki
+    installing = Installing { brandName }.
+
+    menu-save = Save
+    help-menu-save = Click "{ menu-save }" to save the file.
+
+Strings in FTL may use special syntax to incorporate small pieces of
+programmable interface. Those pieces are denoted with curly braces ``{`` and
+``}`` and are called placeables.
+
+One example of a placeable is a reference to another entity.
+
+Referencing other entities generally helps to keep certain translations
+consistent across the interface and makes maintenance easier.  It is also
+particularly handy for keeping branding separated from the rest of the
+translations, so that it can be changed easily when needed, e.g. during the
+build process of the application.
+
+
+Interpolation and External Arguments
+====================================
+
+::
+
+    welcome = Welcome { $user }
+    unreadEmails = { $user } has { $emailCount } unread emails.
+
+::
+
+    {
+        "user": "Jane",
+        "emailCount": 5
+    }
+
+
+Another common common use case for a placeable is to put an external argument,
+provided by the developer, into the string.
+
+There are all kinds of external data that might be useful in providing a good 
+localization: user names, number of unread messages, battery level, current 
+time, time left before an alarm goes off, etc.
+
+To reference a context data variable, use the dollar syntax in your FTL code: 
+``$user``. ``user`` has to be defined in the context data. In the examples 
+below, we insert the value of a context data variable into an entity's value.
+
+
+Builtins
+========
+
+::
+
+    emails = You have { $unreadEmails } unread emails.
+    emails2 = You have { NUMBER($unreadEmails) } unread emails.
+
+    last-notice =
+        | Last checked: { DATETIME($lastChecked, day: "numeric", month: long") }.
+
+::
+
+    {
+        "lastChecked": "2016-04-22T08:13:56.354Z",
+        "unreadEmails": 5
+    }
+
+In some rare cases the data provided by the developer will require some
+additional formatting before it can be placed into the string.  FTL provides
+a list of built-in functions that can help with common operations on the
+external arguments.
+
+By default, FTL can guess which formatter to run on each kind of argument:
+``DATE``, ``NUMBER``, ``LIST`` etc., but you can also call the builtin
+explicitly.
+
+Explicit calls are useful because they allow you to pass additional formatting
+options that may help make the formatted string look better in the given
+language. Examples include: defining month as ``short`` or ``long`` in the
+``DATE`` formatter (using arguments defined in ``Intl.DateTimeFormat``) or
+whether to use grouping separator when displaying a large number.
+
+
+Selectors
+=========
+
+::
+
+    emails = { $unreadEmails ->
+        [one] You have one unread email.
+        [other] You have { $unreadEmails } unread emails.
+    }
+
+::
+
+    {
+        "unreadEmails": 5
+    }
+
+One of the most common cases when a localizer needs to use a placeable is when
+there are multiple variants of the string that depend on some external
+argument.  FTL provides the select expression syntax, which chooses one of the
+provided variants based on the given selector.
+
+The selector may be a string in which case it will be compared directly to the
+keys of variants defined in the select expression.  For number selectors, the
+variant keys either match the number exactly or they match the `CLDR plural
+category`_ for the number.  The possible categories are: ``zero``, ``one``,
+``two``, ``few``, ``many`` and ``other``.  For instance, English has two plural
+categories: ``one`` and ``other``.
+
+.. _CLDR plural category: http://www.unicode.org/cldr/charts/30/supplemental/language_plural_rules.html
+
+If the translation requires a number to be formatted in a particular
+non-default manner, the selector should use the same formatting options.  The
+formatted number will then be used to choose the correct CLDR plural category
+which for some languages might be different than the category of the
+unformatted number::
+
+    your-score = { NUMBER($score, minimumFractionDigits: 1) ->
+        [0.0]   You scored zero points. What happened?
+       *[other] You scored { NUMBER($score, minimumFractionDigits: 1) } points.
+    }
+
+
+Advanced Selectors
+==================
+
+::
+
+    available-users = { LEN($users) ->
+        [0] No users
+        [1] One user.
+        [2] Two users.
+       *[other] { LEN($users) } users.
+    }
+
+    unread-emails = You have { $unreadEmails ->
+        [0] no unread emails.
+        [one] one unread email.
+       *[other] { $unreadEmails } unread emails.
+    }
+
+::
+
+    {
+        "users": ["John", "Mary"],
+        "unreadEmails": 0
+    }
+
+Selectors are pretty powerful. A localizer can use any builtin explicitly and 
+select a string variant depending on its output. In case of the 
+``available-users`` entity, we used the ``LEN`` builtin and select the variant 
+of the string depending on its output.
+
+In the ``unread-emails`` example ``0`` is used explicitly as a member key to
+specify a special case for when there are no unread emails.
+
+Additionally, the code specifies the default variant to be used if none of the
+others match. It's denoted with a ``*`` operator in front of the variant name.
+
+
+Variants
+========
+
+::
+
+    brand-name =
+       *[nominative] Aurora
+        [genitive] Aurore
+        [dative] Aurori
+        [accusative] Auroro
+        [locative] Aurori
+        [instrumental] Auroro
+
+    about-old = O brskalniku { brand-nam }
+    about = O { brand-name[locative] }
+
+As we stated at the beginning of this guide, an entity primarely consist 
+a string value. But there are cases, in which it makes sense to store multiple 
+variants of the value. The ``brand-name`` example, in languages that use noun 
+declension, may need to be declined when referred from other entities.
+
+Select expression, introduced in one of the previous chapters, does not provide 
+a way to easily refer to a particular variant of the value from another entity.  
+Instead, FTL lets you define traits, which are variants of the whole value that 
+can be externally referred to using the ``key[trait]`` syntax.
+
+For instance, in many inflected languages (e.g. German, Finnish, Hungarian, all 
+Slavic languages), the *about* preposition governs the grammatical case of the 
+complement. It might be the accusative (German), ablative (Latin) or locative 
+(Slavic languages).  In Slovenian, the ideal string would inflect the noun, 
+like so: *O Aurori*.  However, since we want the name of the browser to be 
+stored in the ``brand-name`` entity, we can't modify it.
+
+The work-around is to inflect an auxiliary noun complement, e.g. browser, to 
+give *About the Aurora browser*. Needless to say, this ends up being long and 
+often unnaturally-sounding to the native speakers. See ``about-old`` for the 
+example in Slovenian.
+
+This problem can be easily solved by defining multiple variants of the 
+``brand-name`` entity, to match different grammatical cases of the noun.
+
+
+Storing Additional Information
+==============================
+
+::
+
+    brand-name = Firefox
+        [gender] masculine
+
+    opened-new-window = { brand-name[gender] ->
+       *[masculine] { brand-name } otworzyl nowe okno.
+        [feminine] { brand-name } otworzyla nowe okno.
+    }
+
+Traits are useful beyond just value variants. They can be also used to describe 
+parameters of the entity that can be then used in other selectors.
+
+Imagine an entity ``brand-name`` that can be either *Firefox* or *Aurora*.  The 
+former is *masculine*, while the latter is *feminine*, so sentences that refer 
+to this entity may want to branch depending on the gender of it.
+
+
+HTML/XUL Attributes
+===================
+
+::
+
+    login-input = Predefined value
+        [html/placeholder] example@email.com
+        [html/aria-label]  Login input value
+        [html/title]       Type your login email
+
+Finally, traits can also be very useful when using FTL for localization of more 
+complex UI elements, such as HTML components.
+
+Those elements often contain multiple translatable messages per one widget. For 
+example, an HTML form input may have a value, but also a ``placeholder`` 
+attribute, ``aria-label`` attribute and maybe a ``title`` attribute.
+
+Another example would be a Web Component confirm window with an ``ok`` button, 
+``cancel`` button and a message.
+
+
+Sections
+========
+
+::
+
+    instruction = Click "{ open }" to begin
+        
+    [[menu]]
+
+    open = Open
+    close = Close
+    edit = Edit
+    new-file = New File
+    undo = Undo
+    search = Search
+
+Grouping entities that belong to a particular piece of UI is possible thanks to 
+sections.
+
+
+Comments
+========
+
+::
+
+    # Try to keep all menu entities as single word if possible
+    [[menu]]
+
+    open = Open
+    close = Close
+
+    # This button lives in a main toolbar
+    # $user (String) Currently logged in username
+    logout = Logout { $user }
+
+::
+
+    {
+        "user": "mkablnik"
+    }
+
+Comments in FTL can be either standalone or bound to an entity or section. If 
+a comment is located right above section or entity, it belongs to it and 
+localization tools will present it in its context.
+
+
+Complex Example
+===============
+
+::
+
+    liked-photo = { LEN($people) ->
+        [1]     { $people } likes
+        [2]     { $people } like
+        [3]     { TAKE(2, $people), "one more person" } like
+
+       *[other] { TAKE(2, $people),
+                  "{ LEN(DROP(2, $people)) ->
+                      [1]    one more person like
+                     *[other]  { LEN(DROP(2, $people)) } more people like
+                   }"
+                }
+    } your photo.
+
+::
+
+    {
+        "people": ["Anna", "Jack", "Mary", "Nick"]
+    }
+
+Here's a final example. It's a pretty complex and one that you will interact 
+with very rarely, but it shows the power of a message that can be localized 
+really well thanks to the flexibility of the syntax.
+
+In this example we branch the string depending on the number of people passed 
+as an external argument up to three people, and then, if the number is higher, 
+we sum up the list and add the variant for one more person, or any number of 
+people.
+
+This example is very sophisticated and in fact could be simplified like so::
+
+    liked-photo = { LEN($people) } like your photo
+
+It would work well enough for English and could work for other languages 
+without increasing its complexity.
+
+The power of FTL is that you can use the simple variant and then, later, you 
+can invest time to improve the message. If the message is very visible to the 
+users, it may be worth spending more time to get a better quality of the 
+string, if not, you can leave the simple version.
+
+But with FTL, you have a choice.
+
+Dive deeper
+===========
+
+You can experiment with the syntax using an interactive editor
+at http://l20n.github.io/tinker.
+If you are a tool author, you may be interested in the formal `EBNF grammar`_.
+
+.. _EBNF grammar: https://github.com/l20n/spec/blob/master/grammar.ebnf
new file mode 100644
--- /dev/null
+++ b/l10n/moz.build
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files('docs/**'):
+    BUG_COMPONENT = ('Mozilla Localizations', 'Documentation')
+
+SPHINX_TREES['localization'] = 'docs'
--- a/moz.build
+++ b/moz.build
@@ -14,16 +14,17 @@ CONFIGURE_SUBST_FILES += [
     'config/autoconf.mk',
     'config/emptyvars.mk',
 ]
 
 if CONFIG['ENABLE_CLANG_PLUGIN']:
     DIRS += ['build/clang-plugin']
 
 DIRS += [
+    'l10n',
     'config',
     'python',
     'taskcluster',
 ]
 
 if not CONFIG['JS_STANDALONE']:
     CONFIGURE_SUBST_FILES += [
         'tools/update-packaging/Makefile',
--- a/python/compare-locales/moz.build
+++ b/python/compare-locales/moz.build
@@ -1,16 +1,8 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files('compare_locales/**'):
     BUG_COMPONENT = ('Localization Infrastructure and Tools', 'compare-locales')
-with Files('docs/**'):
-    BUG_COMPONENT = ('Mozilla Localizations', 'Documentation')
-
-# SPHINX_PYTHON_PACKAGE_DIRS += [
-#     'compare_locales',
-# ]
-
-SPHINX_TREES['.'] = 'docs'