Re: Questions about bindings for L20n

2016-06-15 Thread zbraniecki
On Tuesday, June 14, 2016 at 11:51:16 AM UTC+1, Joe Walker wrote:
> I don't think you can say "It's sync unless  in which case it's
> async".
> If that's that case then from the API consumers point of view, then (deep
> voodoo withstanding) it's async.

As weird as it sounds, I believe that you actually can in this case.

Because the API is declarative, we can translate DOM synchronously and if we 
encounter an error, we can either synchronously or asynchronously get the 
fallback.

Which means that we're only dealing with async (potentially) when we hit an 
error scenario.

Dealing with worse performance in error scenarios is still significantly better 
than the current situation where we just crash.

And as Axel pointed out, we can do the error scenario sync or async, depending 
on our decisions that don't affect our architecture.

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


Re: Questions about bindings for L20n

2016-06-14 Thread Joe Walker
On Tue, Jun 14, 2016 at 7:00 AM Axel Hecht  wrote:

> On 14/06/16 05:06, zbranie...@mozilla.com wrote:
> > On Monday, June 13, 2016 at 9:39:32 AM UTC+1, Gijs Kruitbosch wrote:
> >  > Separately, the documentation put forth so far seems to indicate that
> >> the localization itself is also async, on top of the asyncness of the
> >> mutationobserver approach, and that could potentially result in flashes
> >> of unlocalized content, depending on "how" asynchronous that API really
> >> ends up being. (AFAIK, if the API returned an already-resolved promise,
> >> there might be less chance of that than if it actually went off and did
> >> IO off-main-thread, then came back with some results.)
> >
> > The DOM localization that is used in response to MutationObserver is
> sync.
> >
>
> ... unless strings trigger a load, either if the initial suite of
> localizations isn't loaded yet, or the loaded strings trigger a runtime
> error, which requires more l10n files to be loaded. That's obviously
> cached, so it happens at first occasion.
>

I don't think you can say "It's sync unless  in which case it's
async".
If that's that case then from the API consumers point of view, then (deep
voodoo withstanding) it's async.

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


Re: Questions about bindings for L20n

2016-06-13 Thread Axel Hecht

On 14/06/16 05:06, zbranie...@mozilla.com wrote:

On Monday, June 13, 2016 at 9:39:32 AM UTC+1, Gijs Kruitbosch wrote:
 > Separately, the documentation put forth so far seems to indicate that

the localization itself is also async, on top of the asyncness of the
mutationobserver approach, and that could potentially result in flashes
of unlocalized content, depending on "how" asynchronous that API really
ends up being. (AFAIK, if the API returned an already-resolved promise,
there might be less chance of that than if it actually went off and did
IO off-main-thread, then came back with some results.)


The DOM localization that is used in response to MutationObserver is sync.



... unless strings trigger a load, either if the initial suite of 
localizations isn't loaded yet, or the loaded strings trigger a runtime 
error, which requires more l10n files to be loaded. That's obviously 
cached, so it happens at first occasion.


Axel

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


Re: Questions about bindings for L20n

2016-06-13 Thread wax miguel
looking forward! thanks!

On 14/06/2016, zbranie...@mozilla.com  wrote:
> On Monday, June 13, 2016 at 9:39:32 AM UTC+1, Gijs Kruitbosch wrote:
>  > Separately, the documentation put forth so far seems to indicate that
>> the localization itself is also async, on top of the asyncness of the
>> mutationobserver approach, and that could potentially result in flashes
>> of unlocalized content, depending on "how" asynchronous that API really
>> ends up being. (AFAIK, if the API returned an already-resolved promise,
>> there might be less chance of that than if it actually went off and did
>> IO off-main-thread, then came back with some results.)
>
> The DOM localization that is used in response to MutationObserver is sync.
>
> zb.
> ___
> dev-platform mailing list
> dev-platform@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform
>


-- 
https://google.com.ph
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Questions about bindings for L20n

2016-06-13 Thread zbraniecki
On Monday, June 13, 2016 at 9:39:32 AM UTC+1, Gijs Kruitbosch wrote:
 > Separately, the documentation put forth so far seems to indicate that 
> the localization itself is also async, on top of the asyncness of the 
> mutationobserver approach, and that could potentially result in flashes 
> of unlocalized content, depending on "how" asynchronous that API really 
> ends up being. (AFAIK, if the API returned an already-resolved promise, 
> there might be less chance of that than if it actually went off and did 
> IO off-main-thread, then came back with some results.)

The DOM localization that is used in response to MutationObserver is sync.

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


Re: Questions about bindings for L20n

2016-06-13 Thread Gijs Kruitbosch

On 10/06/2016 23:01, zbranie...@mozilla.com wrote:

On Friday, June 10, 2016 at 10:37:04 AM UTC-7, Gijs Kruitbosch wrote:


This async-ness will not be acceptable in all circumstances. As a
somewhat random example: how would we localize the 'slow script' dialog,
for which we have to pause script and then show the dialog?


Agree, there are exceptions, and we may have to provide sync version (which 
will have limited functionality) for such cases.

For this particular case, the way we approached it in FxOS was to do something 
like replacing:

window.alert(l10n.get("slowScriptTitle"));

with:

l10n.formatValue("slowScriptTitle").then(val => window.alert(val));


Would that not work?


I don't know, you'd have to ask people who are more intimately familiar 
with how our slow script interrupt code works. It's in C++, so I'm not 
sure how your example maps. Intuitively, I am worried it might not work 
- we're trying to stop script from running, and so waiting on a promise 
and then running script on the same (UI) thread feels interesting. Maybe 
it's solvable with *shudder* another nested event loop to wait for that 
promise, or something.



Another example: in docshell, some error page URLs are currently generated
synchronously in some circumstances (invalid host/uris, for instance).
Making such a location change asynchronous just because of localization
is going to break a *lot* of assumptions, not to mention require
rewriting a bunch of yucky docshell code that will then probably break
some more assumptions...


Yay! :)

If you're saying that we're generating URLs with localized messages in them, 
then I'd question to design...


http://searchfox.org/mozilla-central/rev/ff5673acd6a38a43bc250a2baa47df8fe6ef7859/docshell/base/nsDocShell.cpp#5150-5151

http://searchfox.org/mozilla-central/rev/ff5673acd6a38a43bc250a2baa47df8fe6ef7859/docshell/base/nsDocShell.cpp#5291-5294

Nobody I know of particularly likes this code (I believe this to be true 
much more generally than this particular quirk of it, for that matter - 
error page handling is "interesting".), but it does exist, yes. The 
problem is that the error page is unprivileged and so doesn't have 
access to the stringbundles one would like to use, so it's not entirely 
trivial to fix. Certainly not unchangeable, though...


~ Gijs
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Questions about bindings for L20n

2016-06-13 Thread Gijs Kruitbosch

On 10/06/2016 22:56, smaug wrote:

, 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?


AIUI, if I insert content that needs localizing with these attributes 
into the DOM tree of a document, and then read any salient property of 
that document/tree that triggers a reflow (scrollHeight, anything off 
the bounding client rect, etc.), that will cause a sync reflow before 
the localized content is there, and it will likely produce different 
values from what we want when localization is in place.


Separately, the documentation put forth so far seems to indicate that 
the localization itself is also async, on top of the asyncness of the 
mutationobserver approach, and that could potentially result in flashes 
of unlocalized content, depending on "how" asynchronous that API really 
ends up being. (AFAIK, if the API returned an already-resolved promise, 
there might be less chance of that than if it actually went off and did 
IO off-main-thread, then came back with some results.)


~ Gijs
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Questions about bindings for L20n

2016-06-10 Thread zbraniecki
On Friday, June 10, 2016 at 10:37:04 AM UTC-7, Gijs Kruitbosch wrote:

> This async-ness will not be acceptable in all circumstances. As a 
> somewhat random example: how would we localize the 'slow script' dialog, 
> for which we have to pause script and then show the dialog? 

Agree, there are exceptions, and we may have to provide sync version (which 
will have limited functionality) for such cases.

For this particular case, the way we approached it in FxOS was to do something 
like replacing:

window.alert(l10n.get("slowScriptTitle"));

with:

l10n.formatValue("slowScriptTitle").then(val => window.alert(val));


Would that not work?

> Another example: in docshell, some error page URLs are currently generated 
> synchronously in some circumstances (invalid host/uris, for instance). 
> Making such a location change asynchronous just because of localization 
> is going to break a *lot* of assumptions, not to mention require 
> rewriting a bunch of yucky docshell code that will then probably break 
> some more assumptions...

Yay! :)

If you're saying that we're generating URLs with localized messages in them, 
then I'd question to design...

But as I said, we may have to provide a compatibility layer where we'll have 
sync variant for those scenarios and discourage it for new code.

> It's much easier to just say "we'll make 
> everything async" when you have a greenfield project like b2g than to 
> retrospectively jam it into 20 years of history (ie Gecko).

It probably is, but you don't want to know how much time it took me to 
transition even the relatively young project from sync to async! ;)
 
> Not all JS and C++ code that will want to localize things has access to 
> a document object, and for all consumers to have to create one just to 
> use localization features would be cumbersome (and, as I understand it, 
> would not work without also inserting all the stringbundle things you'd 
> need). Please can we make sure that we have a pure-JS/C++ API that is 
> usable without having to have a document? (Currently, you can create 
> nsIStringBundle instances via XPCOM, and PluralForm can be used as a jsm 
> but not from C++, which also already causes headaches.)

We'll definitely have pure JS code. We're going to land JSM code, and as I 
said, Intl stuff (like PluralRules) will be available straight from 
SpiderMonkey (Intl.PluralRules). Although in L20n world, as an engineer you 
won't ever need to use PluralRules manually :)

For C++, we may wrap the JS API and expose it in C++, but we may also try to 
migrate l10n in C++ up the layer and make C++ code carry l10nIds, and JS UI 
code localize them.

> I'm quite worried some of this won't be workable. For instance, XUL 
> panels make decisions about how big they need to be based on their 
> contents. We'll need to ensure that the content in such panels is 
> present and localized before attempting to show the panel. We can't just 
> add the attributes, show the panel, and hope for the best. If we insert 
> extra turns of the event loop in here because we're ending up waiting 
> for localization, that'll make it harder to deal with state changes (I 
> clicked this button twice, is the popup open or closed? etc. etc.)

That's a great point. As I said in my previous email I'd love a way to prevent 
frame creation until JS init code is done.

We may also decide to move the MutationObserver part in Gecko to ContentSink, 
or design an API that we'll plug into our DOM that will work better for us than 
Mutation Observer.

So far MO works well and gives us the results we need.

> This is still problematic in terms of markup though. It's not uncommon 
> to have 3 or more DTDs in a file, and I can just use an entity without 
> asking what bundle it's from. Having to specify it for any "non-main" 
> bundle would be problematic. Why can't we just fall back to using the 
> other available bundles?

By default you will have all your "DTD"s in the "main" bundle, and we'll loop 
over them to localize your elements. So that works the way you expect it.

On top of that, you'll be able to also specify more bundles with more source 
files. That's where named ones come in.

Thanks,
zb.
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


Re: Questions about bindings for L20n

2016-06-10 Thread smaug

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:

   

  

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
  ?


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

I don't have a strong opinion on custom elements over  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="{"user": "John"}"

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  elements and creates a
localization bundle object which is also available via the
document.l10n collection.

 

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


* Is there a more canonical

Re: Questions about bindings for L20n

2016-06-10 Thread zbraniecki
Hi Gijs,

On Friday, June 10, 2016 at 2:49:16 AM UTC-7, Gijs Kruitbosch wrote:

> 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?

We're using Mutation Observers, and we haven't observed (no punt intended) any 
performance impact yet. We've been using them on the slowest devices that FxOS 
has been designed for, and they performed surprisingly well.

While working on with Mutation Observers I tried to evaluate the potential to 
optimize them to increase the signal/noise ratio of callbacks, and talked to 
people like Olly and Anne about potential improvements that would work better 
for our use case [0].

The general response to my questions was -
a) Seems like Microsoft's NodeWatch proposal [1]
b) They asked us to show them an example of where the current API is slow for 
our use case and they'll help us develop a better one.

So far we failed to find a case where MutationObserver would have a noticable 
negative impact on performance.

Would you by any chance know any piece of Firefox which does large amounts of 
DOM insertions that we could test against?

 
> MutationObservers are async, 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 
> (keep in mind we use l10n data for style as well)


Correct. It's a major change.

Similarly to performance concerns, FOUCs are on our mind, and we've been 
working on this technology initially targeting very slow devices. We've been 
able to get no-FOUC experience so far, but we know it's not deterministic.

We're in a position similar to many other developers who want to use JS to 
alter DOM before frame creation and layout happen. [2]

> , tests that expect synchronous changes as a result of actions

We'll have to fix the tests. Yes.

> , 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)).

That's actually fairly well solved in our approach. By default localization 
happens only when you inject your DOMFragment into DOM, but you can also 
manually fire "translateFragment" which will do this on a disconnected fragment.

> 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?

Two fold.

First of all, we are planning a pure JS API. In fact, we have Node as our 
target, which obviously doesn't use any DOM.

The API is not finalized, but it'll allow you to do the same thing you do in 
DOM from JS:

var bundle = new LocalizationBundle([
  'path/to/source1',
  'path/to/source2'
]);

bundle.formatValue('entityId').then(val => console.log(val));

On top of that we'll probably provide some synchronous way to get the value, if 
only for the compatibility mode, but we'll actively discourage using it, and 
using it will make the code not benefit from the features of the framework.

Secondly, we'll be advocating people to move the localization to the front-end 
of their code. Except of a few cases, there's no reason to localize a message 
deep in your code, and carry a translated string around, while instead the 
entityId should be carried around and resolved only in the UI.
 
> Less markup is better, so please don't wrap in more custom elements.

So, you're saying that:

 // implcit bundle 'main'
 // implicit bundle 'main'



is preferred over:


  
  


  
  


?


> 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.

semicolon-separated string would be flat. Stringified JSON allows us to build 
deeper structures.

We provide a wrapper API to facilitate that:

document.l10n.setAttributes(element, 'l10nId', {
  user: {
'name': "John",
'gender': "male"
  }
});

will assign data-l10n-id and data-l10n-args to the element, while

const {
  l10nId,
  l10nArgs
} = document.l10n.getAttributes(element);

handles the reverse.

> 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.

It will iterate over sources in a single l10n-bundle.
In most cases, you will only have one l10n-bundle per document, so no need to 
explicitly name it or refer to it.

If you want a separate another 

Re: Questions about bindings for L20n

2016-06-10 Thread Gijs Kruitbosch

On 10/06/2016 17:26, smalolep...@mozilla.com wrote:

These are all valid concerns.  The API is async by design, which allow us to 
also do runtime fallback on missing or broken translations.

document.l10n.get('main').formatValue('hello', { user: '…' }).then(hello => 
…);


This async-ness will not be acceptable in all circumstances. As a 
somewhat random example: how would we localize the 'slow script' dialog, 
for which we have to pause script and then show the dialog? Another 
example: in docshell, some error page URLs are currently generated 
synchronously in some circumstances (invalid host/uris, for instance). 
Making such a location change asynchronous just because of localization 
is going to break a *lot* of assumptions, not to mention require 
rewriting a bunch of yucky docshell code that will then probably break 
some more assumptions... It's much easier to just say "we'll make 
everything async" when you have a greenfield project like b2g than to 
retrospectively jam it into 20 years of history (ie Gecko).


Not all JS and C++ code that will want to localize things has access to 
a document object, and for all consumers to have to create one just to 
use localization features would be cumbersome (and, as I understand it, 
would not work without also inserting all the stringbundle things you'd 
need). Please can we make sure that we have a pure-JS/C++ API that is 
usable without having to have a document? (Currently, you can create 
nsIStringBundle instances via XPCOM, and PluralForm can be used as a jsm 
but not from C++, which also already causes headaches.)



In this example 'main' is the name of the bundle and 'hello' is an identifier 
of a translation.  We used this API in Firefox OS and it has proven to be 
versatile and easy to use.  It turns out that there are very few use-cases when 
it's necessary to use this API.  Usually it OK to pass string _identifiers_ 
around and only elem.setAttribute('data-l10n-id', id) when it's time to show it 
to the user.

Same goes for tests:  if we have good tests for the Mutation Observer, then in 
other tests we could just test if the data-l10n-id was properly set.


I'm quite worried some of this won't be workable. For instance, XUL 
panels make decisions about how big they need to be based on their 
contents. We'll need to ensure that the content in such panels is 
present and localized before attempting to show the panel. We can't just 
add the attributes, show the panel, and hope for the best. If we insert 
extra turns of the event loop in here because we're ending up waiting 
for localization, that'll make it harder to deal with state changes (I 
clicked this button twice, is the popup open or closed? etc. etc.)



Having it on an element has one more interesting consequence:  it's widely understood 
that you need to wait for DOMContentLoaded or readystate === 'interactive' to query 
the element and start using the API.  With document.l10n.get() it might look like 
those bundles are available synchronously while in reality we still need to query the 
 to even create them.


This isn't really true. If I have a 

Re: Questions about bindings for L20n

2016-06-10 Thread smalolepszy
Thanks for a lot of great feedback, Gijs!

W dniu piątek, 10 czerwca 2016 11:49:16 UTC+2 użytkownik Gijs Kruitbosch 
napisał:

> 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?

We use Mutation Observers. Actually, just one per document, which observes 
document.documentElement for subtree inserts and changes to the data-l10n-* 
attributes.  I don't currently have perf numbers for large DOM inserts but 
generally we've been very satisfied with this approach in Firefox OS.  We saw 
perf wins even on low-memory handsets.  I'm sure we'll measure a lot more once 
we're closer to having a working fork of Firefox.

> MutationObservers are async, 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 
> (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?

These are all valid concerns.  The API is async by design, which allow us to 
also do runtime fallback on missing or broken translations.

document.l10n.get('main').formatValue('hello', { user: '…' }).then(hello => 
…);

In this example 'main' is the name of the bundle and 'hello' is an identifier 
of a translation.  We used this API in Firefox OS and it has proven to be 
versatile and easy to use.  It turns out that there are very few use-cases when 
it's necessary to use this API.  Usually it OK to pass string _identifiers_ 
around and only elem.setAttribute('data-l10n-id', id) when it's time to show it 
to the user.

Same goes for tests:  if we have good tests for the Mutation Observer, then in 
other tests we could just test if the data-l10n-id was properly set.

We could expose something like document.l10n.translateFragment to deal with 
node trees which are not yet attached to the DOM, although working on 
data-l10n-id and then just translating once (via the observer) when the nodes 
are inserted would be our preferred approach.

FOUCs can also be a problem and something that's constantly on our radar.  The 
Firefox OS experience allows us to be optimistic, and we're sure to follow up 
with much more perf testing in the near future to make sure we don't regress.

 
> > 1) HTML API

> >
> > The open questions are:
> >
> > * Would it be better to instead use custom elements like
> >   ?
> 
> Less markup is better, so please don't wrap in more custom elements.

The idea of  element came about when considering where to expose 
the JS API (like formatValue above).  Similar to  in XUL, one 
idea was to expose it on the element itself: 
document.querySelector('l10n-bundle').formatValue(…).  As you can see, we 
solved it with document.l10n.get() for now.

Having it on an element has one more interesting consequence:  it's widely 
understood that you need to wait for DOMContentLoaded or readystate === 
'interactive' to query the element and start using the API.  With 
document.l10n.get() it might look like those bundles are available 
synchronously while in reality we still need to query the  to even 
create them.

> I don't have a strong opinion on custom elements over  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.

That's great to know, we're definitely interested in this!

> 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.

That's an interesting alternative.  One reason we went for named args is that 
they make it much easier for localizers to understand what they're translating.

> 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.

Yes, that's definitely the plan and it's even implemented right now.  The 
default bundle is called 'main' and data-l10n-bundle="main" is implied if 
missing from the localizable node.


> > 2) XUL API

> I think so. Again, I

Re: Questions about bindings for L20n

2016-06-10 Thread Neil Deakin

On 2016-06-10 4:51 AM, 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.



The one thing I would recommend you do (and I mentioned this many years 
ago when this was first proposed) is to not use the jargon terms 'l10n' 
or 'l20n' anywhere. They are hard to type and hard to read. Three of the 
four characters in 'l10n' are indistinguishable from similar characters 
in some fonts which can lead to hard to detect bugs.


You should instead spell out words such as 'locale' making it clearer to 
a casual reader the meaning.




  


  
  

Yes. Is there a need for two different elements? The HTML case doesn't 
have this. You could also just use the existing stringbundle element and 
make it handle a different file syntax, perhaps.




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


Yes


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



You should just use bundle="browser". I'm not sure what the data 
attribute is meant to represent here, but the attribute name should be 
simpler as mentioned above (XUL attributes don't have hyphens in them 
either)


It's hard to give concrete suggestions when only some examples are 
given. It would help if you posted a more descriptive proposal of what 
all these elements/attributes do for each language. Maybe this is 
already available?


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


Re: Questions about bindings for L20n

2016-06-10 Thread Gijs Kruitbosch

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, 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 
(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:

   

  

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
  ?


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

I don't have a strong opinion on custom elements over  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="{"user": "John"}"

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  elements and creates a
localization bundle object which is also available via the
document.l10n collection.

 

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 , 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 re

Questions about bindings for L20n

2016-06-10 Thread zbraniecki
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.


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:


  





  
  

  


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  
 ?
 * Are data-l10n-* for attributes OK?
 * 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?



2) XUL API

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


  


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



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.


  

  
  


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.

 * Mutations inside of the anonymous content are caught be the document.l10n's 
observer;  are there plans to unify this with how mutations are handled in 
shadow DOM where observers observing non-anonymous content aren't notified 
about mutations in the anonymous content?



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?


That's it for now. We appreciate your feedback and comments!
Your L10n Team
___
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform