Closed Bug 1165332 Opened 9 years ago Closed 8 years ago

Switch the MMI UI code to L20n for localization

Categories

(Firefox OS Graveyard :: Gaia::Dialer, defect)

defect
Not set
normal

Tracking

(Not tracked)

RESOLVED WONTFIX

People

(Reporter: gsvelto, Unassigned)

References

Details

Attachments

(1 file)

+++ This bug was initially created as a clone of Bug #1093266 +++

MMI code uses a whole bunch of JS-based hacks to concatenate multi-line translated strings and other similar horrors. Besides being non-reactive to language changes it also requires us to maintain (and test!) a lot of purely localization-related JS code. We should replace that code with proper use of L20n macros and templates and get rid of the deprecated mozL10n.get calls.
While hacking together a patch I've met a few use cases I'm not sure how to address. First of all the use of a variable that needs to be translated. For example let's say the header of a panel has the following:

<title "{{ $sim_number }} {{ $service_code }}">

service_code needs to be passed in as a variable but it also needs to be translated (i.e., the value is an l10n-id itself). How should I deal with this? Shall I use an index and embed the translations for the various possibilities? E.g.:

<l10n_service_code[service_code] {
  call_forwarding: "Call forwarding",
  call_barring:    "Call barring",
  ...
}>
<notification_title "{{ $sim_number }} {{ l10n_service_code }}">

And then in the code:

mozL10n.setAttributes('notification_title', {
  service_code: 'call_forwarding',
  sim_number: 1
});

Second problem, I've got a few places where we list a number of entries that need to be translated. The result looks like this usually:

Service enabled for:
Voice
Data
SMS

However, the list of elements can be in any order and the number of elements can be different every time. How should I deal with this case? A crude solution would be to have an entry per possible translatable entry and then just fill with blank spots the ones missing by using indexes to enable/disable them, e.g.:

<service_enabled_for """
  Service enabled for
  {{ voice }}
  {{ data }}
  {{ sms }}
""">

<voice[voice_enabled] {
  true:   "Voice",
  *false: ""
}>

<data[data_enabled] {
  true:   "Data",
  *false: ""
}>

<sms[sms_enabled] {
  true:   "SMS",
  *false: ""
}>

However this should leave empty spots in the displayed strings, e.g.:

mozL10n.setAttributes(node, 'service_enabled_for', { voice_enabled: 'true', sms_enabled: 'true' });

Should output:

Service enabled for:
Voice

SMS

It also feels terribly clunky. Is there a better way?
Flags: needinfo?(gandalf)
(In reply to Gabriele Svelto [:gsvelto] from comment #1)
> <l10n_service_code[service_code] {
>   call_forwarding: "Call forwarding",
>   call_barring:    "Call barring",
>   ...
> }>
> <notification_title "{{ $sim_number }} {{ l10n_service_code }}">
> 
> And then in the code:
> 
> mozL10n.setAttributes('notification_title', {
>   service_code: 'call_forwarding',
>   sim_number: 1
> });

Almost!

Index on the entity would make sense if you wanted to refer to l10n_service_code directly, but it seems that it's just a local entity (not used by the developer) referenced from a global entity (notification_title), so it's better to keep it as a has without index, and use property expression:

> <l10n_service_code {
>   call_forwarding: "Call forwarding",
>   call_barring:    "Call barring",
>   ...
> }>
> <notification_title "{{ $sim_number }} {{ l10n_service_code[$service_code] }}">

But, in this case, you can just make notification_title a multivariant string:

<notification_title[$service_code] {
  call_forwarding: "{{ $sim_number }} Call forwarding",
  call_barring:    "{{ $sim_number }} Call barring",
}>

Boom! :)

 
> Second problem, I've got a few places where we list a number of entries that
> need to be translated. The result looks like this usually:

That's an interesting case. I don't know if we have a good solution for that. I know that for the future we have been considering some string operations like join, or for loops, but I don't think we have anything in the syntax.

Stas, Axel, what do you guys think about the second case?
Flags: needinfo?(stas)
Flags: needinfo?(l10n)
Flags: needinfo?(gandalf)
(In reply to Zibi Braniecki [:gandalf][:zibi] from comment #2)

> <notification_title[$service_code] {
>   call_forwarding: "{{ $sim_number }} Call forwarding",
>   call_barring:    "{{ $sim_number }} Call barring",
> }>

I'd like to offer a counter argument to this because I feel like this isn't the best solution we can come up with.  Check out this chat Zibi and I had on IRC for background: https://pastebin.mozilla.org/8833645

In L20n, hash (dict) values are under localizers' control.  The localizer can decide how many members there are in a hash depending on any number of locale-specific conditions (like plurals or genders).  In the example above the hash members are given by the developer which means that the developer (and en-US) dictate which members must be present in the translated hash.  A good rule of thumb for deciding if something should be a hash value is:  will this still work if a localizer decides this is not a hash but a simple string value in their language?  This does not hold above.

Furthermore, redundancy is good in localization b/c it allows for greater flexibility on the localizers' side.  I'd rewrite the example as follows:

let titles = {
  call_forwarding: 'notification_title_forwarding',
  call_barring: 'notification_title_barring',
};

mozL10n.setAttributes(titles[service_code], { sim_number: 1 });

<notification_title_forwarding "{{ $sim_number }} Call forwarding">
<notification_title_barring "{{ $sim_number }} Call barring">

Keeping the needinfo on me for the second question for now.
So, this code looks awesome, but it uses some features of l20n that we did not land yet:

1) triple-quote strings. That's easy to add
2) Macros. That requires the whole expression syntax. We will want to land it soon, but I wanted to ensure we have good performance markers compared to .properties before I include full expression syntax.
3) default values for hash. Those are already in in the full parser, but not in the subset that landed on master

Stas, given that there seem to be a usecase, would you like me to start adding those in v3 parser?
I'm happy to know I've got most things right even though I've used features which aren't available right now. The original code is pretty messy and I planned on refactoring it as we go but first I really wanted to toy with l20n and see how I could use it to fix most of the uses of mozL10n.get() we had in there.
I've got a new version of the patch in the pipe and I've just realized that when I fixed bug 1031175 I've regressed the way errors are handled. Before we displayed a translation of the error message but now we're just displaying the status message. The fact that nobody noticed is probably a good metric of how much this stuff is being excercised :)
The second case seems to be brittle UX-wise, if we're putting newlines into localizers hands. Probably confusing as heck.

Note, your empty-line problem disappears if you put the newline into the enabled-or-empty string instead of the template.

I'd go for full markup, though, if you can, and then dynamically show or hide the localized list entries.
Flags: needinfo?(l10n)
(In reply to Axel Hecht [:Pike] from comment #8)
> The second case seems to be brittle UX-wise, if we're putting newlines into
> localizers hands. Probably confusing as heck.

Yeah, the idea was not to have explicit newlines anywhere. Even when they're not confusing for the localizers they usually end up regressing stuff UX-wise eventually (already had to fix at least a couple of bugs due to them).

> I'd go for full markup, though, if you can, and then dynamically show or
> hide the localized list entries.

I think I'll go down that route, it seems like the only truly robust solution.
Removing the needinfo on me; we're discussing this in https://groups.google.com/forum/#!topic/mozilla.tools.l10n/AJh5O822GgQ.
Flags: needinfo?(stas)
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: