On Wed, Jul 15, 2015 at 10:52 PM, Zibi Braniecki <
[email protected]> wrote:

> Cool stuff Stas!
>

Thanks for a super-quick reply!  This is fantastic feedback.


> On Wednesday, July 15, 2015 at 10:34:39 AM UTC-7, Staś Małolepszy wrote:
> > I made a thought exercise of imaging what it would be like to design the
> > L20n syntax from scratch, today.
> >
> > I was guided by the following goals:
> >
> >  - Make the most commonly used syntax easy on the eyes and easy to
> > understand.
>
> My only concern with regards to using '{', '}' for expanders is that it's
> much more common to use it in a string than '{{', '}}'. Which means that
> now you have to escape a normal character because of its special function
> in L20n.
>

That's the point, actually :)  By forcing { and } to be always escaped we
can make sure that literal { } are either meaningful or are errors.  We
don't have this luxury with <> now.


>
> I searched through our translations and what comes to mind are:
>
>  - CSS in L10n will have to be unescaped
>  - JS Template strings will have to be unescaped because they use `Hello,
> ${user.name}` notation
>  - Some of our build tools use ${AB-CD}
>  - In one place Gaia Email app uses {name}
>
> https://github.com/mozilla-b2g/gaia/blob/1ee07b1bf55894dc7bad8e4a2e31d77c59cf4106/apps/email/locales/email.en-US.properties#L664
>
> Overall, it doesn't look bad. I'm a bit worried about overlapping syntax
> with ES6 Templates.
>

Yeah, good point.  I'm not too worried about Bash variables or that one
vvariable in Gaia's Email.  I'm not sure about Jinja or es6 templates.
Would they be orthogonal to L20n or complementary? Does it even make sense
to have (escaped) es6 templates in translations?


>
> >  - Improve error recovery and make it easier to use HTML in translations.
>
> Here I feel like we're fixating on HTML. If L20n syntax is supposed to be
> language agnostic and useful for different environments, then fixating on
> making it convinient for HTML may be risky. How will it work for Rust?
> Python? Jinja? CSS?
>

This is again a good point and I'm aware that there is world out there
beyond HTML :) That said, I think it's well aligned with Mozilla's mission
to push for HTML as the de facto standard of building localizable UI.  And
while I'm not ruling out Rust or Python, I want to focus on making a
localization library for the Web in the first step.  If we keep dreaming
about being the ultimate tool for all needs, we risk getting blocked and
not having a ready solution for our first target: the Web.  HTML is the
stepping stone.


>
> I'm also of course curious how will Hashes look like.
>

It's in the gist:

; index is defined in []
; hashes are defined as series of hash pairs {}
; the default hash pair is marked with {* }
; hash keys are symbols or strings

{ notifications [(plural n)]
  {* one "{ n } notification"}
  {many "{ n } notifications"}
  {"two words" "{ n } notifications"}}

I went for the hash-pair approach instead of key-value-map one to emphasize
the fact that variants are independent units of translation. They're
different facets of the entity and I wanted to make that clearer with a
syntax that's similar to the syntax of the whole entity.



>
> >  - Make it easy to parse complex expressions.  They are important for the
> > advanced features of L20n, but cost a lot in terms of parsing and
> resolving.


> I don't like this change.
>

Let's discuss! :)


>
> First, I believe that we should avoid naming pollution which I believe we
> should achieve by using namespaces.
>
> @intl.*
> @cldr.*
> @gaia.*
>

I like namespacing, but 1) I'm afraid of creating spurious hierarchies with
one elemnent and 2) it can be achieved by convention, e.g. intl-datetime.


>
> On top of that, I'm don't think that lisp style expressions are helping
> here.
> I've been using lisp style expressions in multiple environments and I
> always felt like they're alien compared to classic C syntax.
>

Consider this:  you can probably write an entire S-expression parser in 100
lines of code.  They're super-easy to implement too, which will make the
resolver simpler.  We want expressions to support complex logic and in L20n
1.0 we paid for them while arguably they aren't used much.  Only a handful
of localizer-engineers will write new expression code.  So I think there's
a benefit of providing complex expressions without bundling a complex
implementation.  I don't think C-like expressions give us that edge at all.


>
> First, I believe it's harder to notice an error and harder to create a
> useful recovery message. Consider:
>
> `callExpr param` - all possible combinations of mistakes -
> `callExpr,param`, 'callExpr.param`, etc.
> `callExpr(param)` - we can easily report to the user sth like
> `callExpr[param)` and suggest a solution
>

A form always looks the same (operand ...args).  There are fewer kinds of
parsing errors.  OTOH, we're able to catch more errors in the runtime: e.g.
(entity 1) should return "Invalid argument type passed to &entity".


>
> Secondly, by far the language that localizers will know the most is
> JavaScript or some expression subset of CSS3/CSS4 (which follows JS
> syntax). Lowering entry barrier by presenting them familiar syntax to code
> the may know even if they only know a little is a huge benefit.
>

> While it may be a matter of habit and preference, I believe that imposing
> something likely less familiar to localizers for disputable benefit is a
> wrong design decision.
>

Our C-style expressions are very limited:  they're always a single
expression which makes the ternary if the only way to branch, and that's
tedious.  I think S-expressions give use a bit more flexibility by allowing
different interpretations of the arguments passed into form, like in (cond
...) which takes an even number of args and pairs them together to create a
multi-branch if-else.

I also noticed that while S-expression can get out of hand in real-world
code, we only mostly need them for arithmetic operations (and possibly
simple string manipulation in the future).  And once you get pass RPN,
they're even simpler than C-style syntax! See the next paragraph for code
samples.

>
> As a mental experiment, design polish cldr.plural macro with your syntax
> and show it to a sample of localizers compared to current L20n expression
> syntax one.
> What do you think they'll likely find more familiar? Where do you think
> they'll likely make more mistakes in?
>

I did that!  I'm sure I'm not being objective here, but the new syntax
looks leaner to me.

https://gist.github.com/stasm/c99010a8ab6d467562ba#file-plural-new-clj
https://gist.github.com/stasm/c99010a8ab6d467562ba#file-plural-old-php
(also in tinker: http://goo.gl/X4pvwe)


>
> >  - Allow to use dashes in entity names.
>
> I would not claim it to be a major win especially since it would require
> localizers to switch between JS syntax and lips syntax for things like `{-
> email-count emails-total}`
>

Why would they switch to JS?


>
> Also, teaching people that a variable may be `email` and a variable may be
> `count` and that we do have substration operator `-` but that `email-count`
> is not an expression but an entity ID is imho very confusing.
>

The subtraction operator can only be found as the callee in form, so it's
really more like an operand or simply a function call:  (- a b).


>
> >  - Make it possible to reference entities by dynamic names unknown at
> parse
> > time.
>
> I like this feature, but not sure if there's a real use case for that and
> if so, I'd expect it to be rare enough that we shouldn't design syntax
> around it imho. (in other words, {{ :[variable] }} would do)
>

I've noticed this could be helpful when you'd want to dynamically choose an
entity in some other translation:  maybe byte units, maybe city names,
maybe something else.  People seem to want a data-store-like structure that
they can retrieve things from. Without dynamic references to entities, they
resort to using hash value, which is bad because hashes are for variants of
the same thing, or to attributes, which also wrong because why would these
translations pretend to be metadata of some made-up entity?  I think all of
those should be separate private entities and it should be easy to access
them without knowing the identifier a priori.


>
> >  - Make it clearer that translation variants are different permutations
> of
> > the same translation data and as such, they are different than attributes
> > and are not part of the social contract.
>
> I like it, although I'd like to combine it with globals, which I think are
> valuable to preserve.
>

I'm keeping globals in form of library-provided symbols!  &defmacro or &and
are what we call globals in 1.0 and 2.0.  The only convenience is that you
don't have to type the & if you're calling them in an S-expr:  (and &true
&true).

I'm also not sure if ":" is better than "$", especially if we want to use
> ':' to denote value variants. Because in that narrative that makes entities
> variants of context?
>

Great point, I had this same doubt myself.  I went for : for entity
references to make them visually lightweight but distinct. For variant
access I considered / but I though we might want to use it when we
implement imports, like this:

(import "../other/common.l20n" "common")
{ hello "Hello, { :common/user }." }



> My suggestion:
>
>  - $entity1:masculine
>  - $entity1.ariaLabel
>  - @cldr.plural
>  - user.name


How about the... hash? :)

:entity#one#feminine
:entity.aria-label
&cldr-plural   (when used not as callee)
(cldr-plural 3)
user.name

Also note that all of these shorthands will require a little bit of special
parsing because they're not S-expressions.  We could work around this
problem (at least for now) by only allowing access via dedicated symbols:

(variant :entity "one" "feminine")
(attr :entity "aria-label")
(attr user "name")

Or by making them callable (it's a bit awkward, I'll admit, but simple!):

(#feminine (#one :entity))
(.aria-label :entity)
(.name user)

This is btw what Clojure does, too.  It works because behind the scenes,
keywords and property accessors (.prop) implement the IFn protocol and they
can look themselves up in the argument if called as a function.

Last but not least, I'd like to keep @ out of the syntax and use it for
docstrings like @param.


> All in all, I'm all in favor of revisiting the syntax and I think it's a
> good moment for that. I'd love us to get to Gaia devs and localizers and
> ask them for feedback. I'd love them to tinker with our current syntax and
> tell us where they have problems and come up with ideas. I think it's a
> perfect moment for last revision of the syntax and probably the last one
> before we have to make a call and stabilize it if we want to start using it
> in time for Firefox OS 2.5.
>
>
Yay!  Let's keep the ball rolling. I think we learned a lot from previous
attempts and from Gaia, but there's also the uncharted territory of the
untapped potential, so to speak.

Thanks again,
-stas
_______________________________________________
tools-l10n mailing list
[email protected]
https://lists.mozilla.org/listinfo/tools-l10n

Reply via email to