On 06/10/2016 12:49 PM, Gijs Kruitbosch wrote:
On 10/06/2016 09:51, zbranie...@mozilla.com wrote:
While working on the new localization API (See Intent to Implement
post from yesterday), we're developing bindings into UI languages
used by Firefox and we have some decisions to make that could be
better answered by this group.

The general API is declarative and DOM-based.  Instead of forcing
developers to programmatically create string bundles, request raw
strings from them and manually interpolate variables, L20n uses a
Mutation Observer which is notified about changes to data-l10n-*
attributes.  The complexity of the language negotiation, resource
loading, error fallback and string interpolation is hidden in the
mutation handler.  Most of our questions in this email relate to what
the best way to declare resources is.

Mutation observers or mutation events? How do you decide which elements you 
observe? Observing the entire DOM tree seems like it'd likely be terrible
for performance once we start mutating the DOM. Have you done any measurements 
on the performance of this approach when large amounts of DOM are
inserted (ie not about:support :-) )? How do you decide on which documents you 
add these observers to?

MutationObservers are async
From JS side, but they are sync from browser engine point of view since MO 
callbacks are called at microtask check point.
(end of outermost script execution or end of task)


, and dtd localization in XHTML is currently synchronous on parsing. That seems 
like a large change that will cause a lot
of problems relating to reflow / flashes of unlocalized content

Why would it cause reflows or flashes of unlocalized content?

(keep in mind we use l10n data for style as well), tests that expect synchronous
changes as a result of actions, as well as issues where we would want the 
localized changes in elements that aren't in the page DOM (so constructed in
JS, but not included in the DOM (yet)). You don't mention a JS/C++ API, which 
we need for e.g. strings we pass to message boxes or into the argument
strings for about:neterror/about:certerror. What are your plans in that 
department?

1) HTML API

Our HTML API has to allow us to create a set of localization bundle
objects, each with a unique name, that aggregate a set of
localization sources.  It also has to allow us to annotate elements
with L10n ID/Args pairs and potentially with L10n Bundle reference
id.

Currently, our proposal looks like this:

<html> <head> <link rel="localization" name="main"
href="./locales/resource1.ftl"/> <link rel="localization" name="main"
href="./locales/resource2.ftl"/>

<link rel="localization" name="menu"
href="./locales/resource3.ftl"/> <link rel="localization" name="menu"
href="./locales/resource4.ftl"/> </head> <body> <h1
data-l10n-id="mainTitle" data-l10n-args="{\"user\": \"John\"}"
data-l10n-bundle="main" /> </body> </html>

Resource URIs are identifiers resolved by a localization registry
which -- similar to the chrome registry -- knows which languages are
available in the current build and optionally knows about other
locations to check for resources (other Gecko packages, langpacks,
remote services etc.). Localization bundles can query the registry
multiple times to get alternative versions of a resource, a feature
which makes it possible to provide a runtime fallback mechanism for
missing or broken translations.

We're considering allowing names to be omitted which would imply the
"default" bundle to reduce the noise for scenarios where only a
single l10n bundle is needed.  There's also a document.l10n
collection which stores all localization bundles by name, manages the
Mutation Observer and listens to languagechange events.

The open questions are:

* Would it be better to instead use custom elements like
<l10n-bundle> <l10n-source src="…"/> </l10n-bundle>?

Less markup is better, so please don't wrap in more custom elements.

I don't have a strong opinion on custom elements over <link> ones, though I'd 
note that there's existing architecture for link elements being
added/modified/removed that fire specific events to chrome code that you may be 
able to leverage.

 > * Are data-l10n-* for attributes OK?

Seems OK to me.

  * Is there a better way to store
arguments than stringified JSON?  We considered storing arguments as
separate attributes (e.g. data-l10n-arg-user="John") but that would
make it impossible to the Mutation Observer to know what to observe.
* Any other feedback on the design?

The escaped-JSON-in-markup looks very painful. In fact, it looks wrong as it 
is, the correct escaping in HTML would be something like:

data-l10n-args="{&quot;user&quot;: &quot;John&quot;}"

It's not clear to me why we need a key/value object rather than a sequence as 
we use now. Perhaps just a semicolon-separated string with \; as an
escape for literal ; ? That'd certainly be easier to read/write.

Otherwise, it also seems wrong to require the bundle name (data-l10n-bundle) on 
every localized element. The observer should be able to simply iterate
through the stringbundles in declaration order until it finds a matching symbol.

2) XUL API

For XUL, we would like to use custom elements for bundles which are
bound by XBL. The binding looks for <source> elements and creates a
localization bundle object which is also available via the
document.l10n collection.

<window> <localization name="browser"> <source
src="./locales/resource1.ftl" /> <source
src="./locales/resource2.ftl" /> </localization> <label
data-l10n-bundle="browser" data-l10n-id="foo></label> </window>

The open questions are:

* Can we use custom elements like <localization> in XUL?

I think so. Again, I'd prefer not to have a wrapper element.

* Is there a more canonical way to do this?

Besides "use a DTD file"? Not that I'm aware of. Note that XUL also supports 
<stringbundle>, and I don't know if there isn't a reason to reuse those
tag names.

* Are there plans to replace XBL components with Web Components?

Last I checked web components were not ready yet (ie bits were either not 
implemented or not enabled by default all the way through to release). I am
not aware of concrete plans, but that is by no means conclusive proof that such 
plans do not exist.

* Is it okay to use the "name" attribute in XUL for the <localization> object?

I don't see any reason not to, but Neil Deakin would be able to give you a more 
authoritative answer.

* Is it okay to use data-l10n-* attributes for localizable elements? Or perhaps 
l10n-*
would be sufficient?

data- has the nice property in HTML that there is automatic easy access as 
element properties (on element.dataset) but this doesn't seem to
exist/happen for XUL. At that point, I would expect that not using the prefix 
might be easier to read. On the other hand, inconsistency with the HTML
case might also be confusing. YMMV depending on whether you use/need/like the 
"data-" prefix / dataset properties for HTML.

3) XBL API

For XBL, we plan to use the same XUL bindings but inside of the
anonymous content.  Again, this creates a localization bundle object
which is available via the document.l10n collection.

<content> <xul:localization name="tabbrowser"> <xul:source
src="/browser/tabbrowser.ftl"/> </xul:localization> <xul:label
data-l10n-bundle="tabbrowser" data-l10n-id="foo"></xul:label>
</content>

Open questions:

* We understand that this creates and destroys the element each time
the parent is bound/unbound. Is there UI that does that on a
timing-sensitive path extensively? That'd be good to measure.

I'm not sure. I'd assume that you can/want/should just cache the contents of 
bundles in a JSM or equivalent, though, so that the actual element
instantiation should be reasonably quick once the resource has loaded? This 
would also help in the case where you have 500 identical XUL elements that
are all bound to include the same localization resource...

4) Performance measuring

We need to evaluate the performance impact of the change. So far
we've been able to measure the loading time of about:support with
DTD/StringBundle vs L20n using the  Performance Timing API and the
results are promising (perf win!), but we don't know how
representative it is for Firefox startup and memory.

Question: Which performance tests should we run to ensure that L20n
is indeed not regressing performance of Firefox?

tpaint, ts_paint, sessionrestore, sessionrestore_no_auto_restore, tsvg-opacity, 
tart, cart

(and their e10s equivalents, of course) would be my prime suspects. IIRC these come under 
"other,svgr" in try syntax, but trychooser can confirm this
for you (hover over suites tells you what tests they run).

See https://wiki.mozilla.org/Buildbot/Talos/Tests for descriptions, which also 
explains why I'm listing tsvg-opacity. :-)

~ Gijs

_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to