Bug 1627809 Comment 19 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

> What does it mean that document.l10n isn't enabled? That it's not available? Or that its internal state prevents it from doing anything? If it's the latter, can you briefly explain why?

`enabled` means that `document.l10n` is null.

The issue is that if your Web Component gets connected while the document is parsing, and if there were no FTL links before, we fall into this branch: https://searchfox.org/mozilla-central/source/dom/base/Document.cpp#3873

And the result is that `document.l10n` is not available in `connectedCallback`, forcing users to do sth like:

```
connectedCallback() {
  MozXULElement.insertFTLIfNeeded("browser/editBookmarkOverlay.ftl");
  document.addEventListener("DOMContentLoaded", () => {
    document.l10n.connectRoot(this.shadowRoot);
    document.l10n.translateFragment(this.shadowRoot);
  }
}
```

My goal is to enable `document.l10n` as soon as the first FTL file is inserted and allow for root adding/removing right after:


```
connectedCallback() {
  MozXULElement.insertFTLIfNeeded("browser/editBookmarkOverlay.ftl");
  document.l10n.connectRoot(this.shadowRoot);
  document.l10n.translateFragment(this.shadowRoot);
}
```

The issue with that `translateFragment` requires (at the moment) the JSM file to be loaded. So to prevent JSM from having to be loaded (which is what we do to avoid perf hit on browser.xhtml), I'd have to root `translate*` and `format*` methods via a Promise that gets resolved when JSM gets loaded, and then it can be delegated to JSM's `translate*` and `format*` promises.

This is quite a bit of work, which I will do if we don't find a better solution.

> Would it make sense to make document.l10n available and "live" always for all documents, similar to document.styleSheets? 

No, that would mean that you need to initialize DocumentL10n, DOMLocalization, Localization and, at the moment Localization.jsm for all instances of `Document` and we have hunderds of those on the startup path of the product.
L10n affects a small number of them and should be lazy.

We could make `document.l10n` lazily initialize it, but the remaining question is if we need to load JSM as soon as the first interaction with `DOMLocalization` happens.

We have at the moment two classes of operations on `DOMLocalization`:
1) Root and Resource management - `AddResourceId`, `RemoveResourceId`, `ConnectRoot`, `DisconnectRoot`.
2) Translation and Formatting related - `FormatMessages`, `TranslateElements`, `TranslateFragments`, `TranslateRoots`

The former can be performed without loading of JSM since they're stored on the C++ side. The latter require the JSM to be loaded.

Further, for performance reasons, we need to kick-off fetching of I/O eagerly, so we can't just say "once the first `TranslateFragment` gets called, initialize JSM" - we need to "initialize JSM and fetch I/O" as soon as possible and hope that by the time document is parsed the I/O is done.

So, if we want to allow people to add/remove roots and resources, but delay loading of JSM for (2), we need to be able to be in a state where you can call `document.l10n.connectRoot` but you cannot call `translateFragment` yet.

Alternatively, we can always load JSM, or we can remove JSM (I'm working on that), or we can reduce JSM to be stateless and then you could hook all methods of `Localization` to be pending on JSM being initialized, and then they become available immediatelly, but resolve only after the JSM is loaded.
> What does it mean that document.l10n isn't enabled? That it's not available? Or that its internal state prevents it from doing anything? If it's the latter, can you briefly explain why?

`enabled` means that `document.l10n` is not null.

The issue is that if your Web Component gets connected while the document is parsing, and if there were no FTL links before, we fall into this branch: https://searchfox.org/mozilla-central/source/dom/base/Document.cpp#3873

And the result is that `document.l10n` is not available in `connectedCallback`, forcing users to do sth like:

```
connectedCallback() {
  MozXULElement.insertFTLIfNeeded("browser/editBookmarkOverlay.ftl");
  document.addEventListener("DOMContentLoaded", () => {
    document.l10n.connectRoot(this.shadowRoot);
    document.l10n.translateFragment(this.shadowRoot);
  }
}
```

My goal is to enable `document.l10n` as soon as the first FTL file is inserted and allow for root adding/removing right after:


```
connectedCallback() {
  MozXULElement.insertFTLIfNeeded("browser/editBookmarkOverlay.ftl");
  document.l10n.connectRoot(this.shadowRoot);
  document.l10n.translateFragment(this.shadowRoot);
}
```

The issue with that `translateFragment` requires (at the moment) the JSM file to be loaded. So to prevent JSM from having to be loaded (which is what we do to avoid perf hit on browser.xhtml), I'd have to root `translate*` and `format*` methods via a Promise that gets resolved when JSM gets loaded, and then it can be delegated to JSM's `translate*` and `format*` promises.

This is quite a bit of work, which I will do if we don't find a better solution.

> Would it make sense to make document.l10n available and "live" always for all documents, similar to document.styleSheets? 

No, that would mean that you need to initialize DocumentL10n, DOMLocalization, Localization and, at the moment Localization.jsm for all instances of `Document` and we have hunderds of those on the startup path of the product.
L10n affects a small number of them and should be lazy.

We could make `document.l10n` lazily initialize it, but the remaining question is if we need to load JSM as soon as the first interaction with `DOMLocalization` happens.

We have at the moment two classes of operations on `DOMLocalization`:
1) Root and Resource management - `AddResourceId`, `RemoveResourceId`, `ConnectRoot`, `DisconnectRoot`.
2) Translation and Formatting related - `FormatMessages`, `TranslateElements`, `TranslateFragments`, `TranslateRoots`

The former can be performed without loading of JSM since they're stored on the C++ side. The latter require the JSM to be loaded.

Further, for performance reasons, we need to kick-off fetching of I/O eagerly, so we can't just say "once the first `TranslateFragment` gets called, initialize JSM" - we need to "initialize JSM and fetch I/O" as soon as possible and hope that by the time document is parsed the I/O is done.

So, if we want to allow people to add/remove roots and resources, but delay loading of JSM for (2), we need to be able to be in a state where you can call `document.l10n.connectRoot` but you cannot call `translateFragment` yet.

Alternatively, we can always load JSM, or we can remove JSM (I'm working on that), or we can reduce JSM to be stateless and then you could hook all methods of `Localization` to be pending on JSM being initialized, and then they become available immediatelly, but resolve only after the JSM is loaded.

Back to Bug 1627809 Comment 19