Write introduction to Fluent for Firefox Developers

RESOLVED FIXED in Firefox 60

Status

()

enhancement
P3
normal
RESOLVED FIXED
Last year
Last year

People

(Reporter: zbraniecki, Assigned: zbraniecki)

Tracking

(Blocks 1 bug)

unspecified
mozilla60
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(firefox60 fixed)

Details

Attachments

(1 attachment)

We need an introduction to Fluent document for Firefox Developers.
Blocks: 1365426
Priority: -- → P3
Comment hidden (mozreview-request)
Assignee: nobody → gandalf
Status: NEW → ASSIGNED
Comment hidden (mozreview-request)
Comment hidden (mozreview-request)

Comment 6

Last year
mozreview-review
Comment on attachment 8955027 [details]
Bug 1438655 - Add Introduction to Fluent for Firefox Developers.

https://reviewboard.mozilla.org/r/224206/#review230890

Content and syntax wise I think it looks great. 

I still found a few nits, and tried to mark as issues only the ones that actually need fixing. Others are open to discussion.

I'm not a huge fan of Title Case, but I think we should stick to it for all titles (or none).

::: intl/l10n/docs/fluent_tutorial.rst:18
(Diff revision 4)
> +
> +
> +Using Fluent in Gecko
> +=====================
> +
> +`Fluent`_ is a modern localization system currently being carefully introduced into

carefully -> progressively?

::: intl/l10n/docs/fluent_tutorial.rst:32
(Diff revision 4)
> +XUL context.
> +
> +From there we plan to focus on two areas:
> +
> + - `Unprivileged Contexts`_
> + - `System Addons`_

Add-ons

::: intl/l10n/docs/fluent_tutorial.rst:36
(Diff revision 4)
> + - `Unprivileged Contexts`_
> + - `System Addons`_
> +
> +The end goal is replacing all uses of DTD and StringBundle within Firefox's codebase.
> +
> +If you want to use Fluent and your code involves one of those areas, we'd like to work

those areas -> the areas currently unsupported

::: intl/l10n/docs/fluent_tutorial.rst:159
(Diff revision 4)
> +      <span>Please, read the <a>privacy policy</a>.</span>
> +
> +The above, of course, is a particular selection of complex strings intended to exemplify
> +the new features and concepts introduced by Fluent.
> +
> +In order to ensure the quality of the output, a lot of new quality checks and tooling

new quality check -> new checks 

(to avoid the repetition)

::: intl/l10n/docs/fluent_tutorial.rst:165
(Diff revision 4)
> +has been added to the build system.
> +`Pontoon`_, the main localization tool used to translate Firefox, has been rebuilding
> +its user experience to support localizers in their work.
> +
> +
> +Social contract

case: Social Contract

::: intl/l10n/docs/fluent_tutorial.rst:180
(Diff revision 4)
> +.. important::
> +
> +  An important part of the contract is that the developer commits to treat the
> +  localization output as `opaque`. That means that no concatenations, replacements
> +  or splitting should happen after the translation is completed to generate the
> +  desidered output.

typo: desired

::: intl/l10n/docs/fluent_tutorial.rst:192
(Diff revision 4)
> +variant selection techniques are used is up to a localizer and their particular translation.
> +From the developer perspective, Fluent returns a final string to be presented to
> +the user, with no l10n logic required in the running code.
> +
> +
> +Markup localization

case: Markup Localization

::: intl/l10n/docs/fluent_tutorial.rst:240
(Diff revision 4)
> +  <label data-l10n-id="search-input" data-l10n-attrs="style" />
> +
> +The above example adds an attribute `style` to be allowed on this
> +particular `label` element.
> +
> +In the previous example you can also notice an attribute `data-l10n-args`, which is

Notice in the previous example the attribute `data-l10n-args`, which is…

::: intl/l10n/docs/fluent_tutorial.rst:249
(Diff revision 4)
> +used DTD, because such variables will usually have to be computed from the runtime code.
> +
> +__ https://www.w3.org/TR/2011/WD-html5-20110525/text-level-semantics.html
> +
> +
> +Runtime localization

case: Runtime Localization

::: intl/l10n/docs/fluent_tutorial.rst:285
(Diff revision 4)
> +  }
> +
> +__ https://github.com/projectfluent/fluent/wiki/Good-Practices-for-Developers
> +
> +
> +Non-markup localization

case: Non-Markup Localization

::: intl/l10n/docs/fluent_tutorial.rst:305
(Diff revision 4)
> +DOM annotation is not possible.
> +
> +.. note::
> +
> +  This API is currently only available as asynchronous. In case of Firefox,
> +  the only non-DOM localizable calls are ones where the output goes to

are ones where -> are used where

::: intl/l10n/docs/fluent_tutorial.rst:315
(Diff revision 4)
> +Internationalization
> +====================
> +
> +The majority of internationalization issues are implicitly handled by Fluent without
> +any additional requirement. Full Unicode support, `bidirectionality`__, and
> +correct number formatting just works without any additional work required

just works -> just work

::: intl/l10n/docs/fluent_tutorial.rst:331
(Diff revision 4)
> +
> +A message like this localized to American English will correctly wrap the user
> +name in directionality marks allowing the layout engine to determine how to
> +display the bidirectional text.
> +
> +On the other hand, the same message localized to Arabic will use eastern arabic

eastern arabic numerals -> the Eastern Arabic numeral

Wasn't so sure about "Eastern", but https://www.proofreadnow.com/blog/bid/30440/North-East-South-or-West-Capitalize-or-Not

::: intl/l10n/docs/fluent_tutorial.rst:365
(Diff revision 4)
> +      }
> +
> +Fluent guesses that since the variant selection is performed based on a number,
> +its `plural category`__ should be retrieved.
> +
> +If the given translation doesn't need pluralization for the given string (for example

the given string -> the string 

(avoid given…given)

::: intl/l10n/docs/fluent_tutorial.rst:408
(Diff revision 4)
> +
> +When it comes to formatting data, Fluent allows the developer to provide
> +a set of parameters for the formatter, and the localizer can fine tune some of them.
> +This technique is called `partial arguments`__.
> +
> +For example, when formatting a date, developer can just pass a JS `Date` object,

developer -> the developer (for consistency with the rest of the doc)

::: intl/l10n/docs/fluent_tutorial.rst:451
(Diff revision 4)
> +
> +__ http://projectfluent.org/fluent/guide/functions.html#partial-arguments
> +__ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
> +__ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
> +
> +Registering new l10n files

Case: Registering New L10n Files

::: intl/l10n/docs/fluent_tutorial.rst:454
(Diff revision 4)
> +__ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
> +
> +Registering new l10n files
> +==========================
> +
> +In the previous system, in order to add a new localization file you had to register

This section moves from using "The developer" to "You". The only other place where this happens is at the very beginning, but I think it makes sense there (targets one developer writing the patch, and asking for review).

In the previous system, a new localization file had to be registered in order to
add it in the jar.mn file for packaging.

::: intl/l10n/docs/fluent_tutorial.rst:460
(Diff revision 4)
> +it in the `jar.mn` file for packaging.
> +
> +Fluent uses a wildcard statement marking all files in a given `/localization/` directory
> +to be packaged into the build.
> +
> +That means that, if you're just adding a new file into a component of Firefox already

That means that, if a new file is added to a component of Firefox already
covered by Fluent like `browser`, it's enough to add the new file to the
repository in a path like `browser/locales/en-US/browser/component/file.ftl` and
the toolchain will handle it.

::: intl/l10n/docs/fluent_tutorial.rst:482
(Diff revision 4)
> +that the localization happens before first paint.
> +
> +The URI provided to the :html:`<link/>` element are relative paths within the localization
> +system.
> +
> +Notice that only registration of the script is synchronous. All of the I/O and

registration -> the registration
All the I/O and translations happen

Notice that only the registration of the script is synchronous. All the I/O and
translation happen asynchronously.

::: intl/l10n/docs/fluent_tutorial.rst:511
(Diff revision 4)
> +
> +	let [isDefaultMsg, isNotDefaultMsg] =
> +		myL10n.formatValues(["is-default", "is-not-default"]);
> +
> +
> +Designing localizable APIs

Case: Designing Localizable APIs

::: intl/l10n/docs/fluent_tutorial.rst:556
(Diff revision 4)
> +  
> +  equals(element.textContent.contains("John"));
> +
> +.. important::
> +
> +  Testing against whole values is brittle and will break when we insert unicode

I think Unicode (uppercase), given the rest of the doc.

::: intl/l10n/docs/fluent_tutorial.rst:560
(Diff revision 4)
> +
> +  Testing against whole values is brittle and will break when we insert unicode
> +  bidirectionality marks into the result string or adapt the output in other ways.
> +
> +
> +Inner structure of Fluent

Case: Inner Structure of Fluent

::: intl/l10n/docs/fluent_tutorial.rst:576
(Diff revision 4)
> +consumers directly.
> +
> +In the future we intend to offer this layer for standardization and it may become
> +part of the `mozIntl.*` or even `Intl.*` API sets.
> +
> +That part of the codebase is also the first that we'll be looking to oxidize.

Can we just say "port to Rust" instead of "oxidize", or does it imply more? 

I know the target is Firefox developers, but this really seems like unnecessary jargon.

::: intl/l10n/docs/fluent_tutorial.rst:617
(Diff revision 4)
> +.. _Fluent: http://projectfluent.org/
> +.. _DTD: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/Localization
> +.. _StringBundle: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/Property_Files
> +.. _Firefox Preferences: https://bugzilla.mozilla.org/show_bug.cgi?id=1415730
> +.. _Unprivileged Contexts: https://bugzilla.mozilla.org/show_bug.cgi?id=1407418
> +.. _System Addons: https://bugzilla.mozilla.org/show_bug.cgi?id=1425104<Paste>

Extra `<Paste>` at the end

::: intl/l10n/docs/fluent_tutorial.rst:617
(Diff revision 4)
> +.. _Fluent: http://projectfluent.org/
> +.. _DTD: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/Localization
> +.. _StringBundle: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/Property_Files
> +.. _Firefox Preferences: https://bugzilla.mozilla.org/show_bug.cgi?id=1415730
> +.. _Unprivileged Contexts: https://bugzilla.mozilla.org/show_bug.cgi?id=1407418
> +.. _System Addons: https://bugzilla.mozilla.org/show_bug.cgi?id=1425104<Paste>

Will need to fix the reference here too (Add-ons)

::: intl/l10n/docs/index.rst:6
(Diff revision 4)
> +======
> +Fluent
> +======
> +
> +Fluent is a new localization system by Mozilla which aims to unify all localization
> +models used by Mozilla.

I would try to get rid of two "by Mozilla" so close to each other. Also, IMO it replaces them, more than unifying them.

Maybe:

Fluent is a new localization system, developed by Mozilla, which aims to replace
all existing localization models currently used at Mozilla.
Comment hidden (mozreview-request)
Thanks Flod! Updated the patch to your feedback!

Comment 9

Last year
mozreview-review
Comment on attachment 8955027 [details]
Bug 1438655 - Add Introduction to Fluent for Firefox Developers.

https://reviewboard.mozilla.org/r/224206/#review231030

Thanks, one final nit but it looks great

::: intl/l10n/docs/fluent_tutorial.rst:288
(Diff revisions 4 - 5)
>    }
>  
>  __ https://github.com/projectfluent/fluent/wiki/Good-Practices-for-Developers
>  
>  
> -Non-markup localization
> +Non-Markup localization

Still missing one uppercase: Localization
Attachment #8955027 - Flags: review?(francesco.lodolo) → review+
Comment on attachment 8955027 [details]
Bug 1438655 - Add Introduction to Fluent for Firefox Developers.

https://reviewboard.mozilla.org/r/224206/#review231052

Hello, here are some comments. Thanks

::: intl/l10n/docs/fluent_tutorial.rst:92
(Diff revision 5)
> +
> +
> +Product Quality
> +------------------
> +
> + - A robust, multilevel, `error fallback system`__ prevents XML errors (YSOD) and runtime errors

YSOD should be defined. I know what it means but many others won't.

::: intl/l10n/docs/fluent_tutorial.rst:188
(Diff revision 5)
> +
> +In return, localizers enter the social contract by promising to provide an accurate
> +and clean translation of the messages that match the request.
> +
> +The developer is not to be bothered with inner logic and complexity that the
> +localization will use to construct the response. Whether declensions or other

Nit: Linking to a definition of "declension" would be nice.

::: intl/l10n/docs/fluent_tutorial.rst:226
(Diff revision 5)
> +Fluent will overlay the translation onto the source fragment preserving attributes like
> +:code:`class` and :code:`href` from the source and adding translations for the elements
> +inside.

It would be great to show an example of the FTL that would be used here

::: intl/l10n/docs/fluent_tutorial.rst:261
(Diff revision 5)
> +
> +In almost every case the JS runtime code will operate on a particular document, either
> +XUL, XHTML or HTML.
> +
> +If the document has its markup already localized, then Fluent exposes a new
> +attribute on the :js:`document` element - :js:document.l10n`.

There is a syntax issue here… I think you're missing a backtick for document.l10n

::: intl/l10n/docs/fluent_tutorial.rst:460
(Diff revision 5)
> +Fluent uses a wildcard statement marking all files in a given `/localization/` directory
> +to be packaged into the build.
> +
> +That means that, if a new file is added to a component of Firefox already
> +covered by Fluent like `browser`, it's enough to add the new file to the
> +repository in a path like `browser/locales/en-US/browser/component/file.ftl` and

I'm confused by the use of slashes around "/localization/" as it seems like it's indicating a file but then the examples uses "/locales/". Maybe replace "`/localization/` directory" with "localization directory (e.g. `/browser/locales/`)"

::: intl/l10n/docs/fluent_tutorial.rst:482
(Diff revision 5)
> +The URI provided to the :html:`<link/>` element are relative paths within the localization
> +system.

This leaves me with more questions than answers. I can guess that this means that the paths are relative to all localization directories but that should just be specified if true.

Comment 11

Last year
mozreview-review
Comment on attachment 8955027 [details]
Bug 1438655 - Add Introduction to Fluent for Firefox Developers.

https://reviewboard.mozilla.org/r/224206/#review231100

I don't have much experience with localization in Firefox. I've used gettext in Python (on Sumo), which deals with pluralization, but not declension, gender, etc. (at least in Sumo's usage). I have a few comments, but I don't see any of them as blockers, and the documentation gave me a pretty good idea of how I would use Fluent. As a disclaimer, I've been following Fluent for a while, so I was already pretty familiar with the system.

One concern that I have is "flashing" of UIs with missing text or unlocalized text. I assume this is something that Fluent deals with, but these docs didn't do much to explain what or how. It is touched on very briefly in "Registering New L10n Files", but I still worry about it. Mostly I'd just like to see an acknowledgement of the issue, and maybe explain what Fluent does to deal with it.

::: intl/l10n/docs/fluent_tutorial.rst:128
(Diff revision 5)
> +consider reading through the `Fluent Syntax Guide`_ to understand
> +a more complex example like:
> +
> +.. code-block:: properties
> +
> +  ### Those messages correspond to security and privacy user interface.

This line would read more naturally to me as "These messages correspond..." instead of "Those messages correspond".

::: intl/l10n/docs/fluent_tutorial.rst:191
(Diff revision 5)
> +
> +The developer is not to be bothered with inner logic and complexity that the
> +localization will use to construct the response. Whether declensions or other
> +variant selection techniques are used is up to a localizer and their particular translation.
> +From the developer perspective, Fluent returns a final string to be presented to
> +the user, with no l10n logic required in the running code.

This paragraph is confusing to me. I'm not sure what the "l10n logic required" would be, or what "inner logic and complexity" would be involved. Providing anti-examples might be bad in documentation, but in this case it might help to clarify Fluent's benefits?

::: intl/l10n/docs/fluent_tutorial.rst:247
(Diff revision 5)
> +
> +Notice in the previous example the attribute :code:`data-l10n-args`, which is
> +a JSON object storing variables exposed by the developer to the localizer.
> +
> +It is very rare that this attribute is needed for localizations which previously
> +used DTD, because such variables will usually have to be computed from the runtime code.

It is unclear to me which field is referenced here. I would either combine this paragraph with the previous one-sentence paragraph if you are referring to `data-l10n-args`, or move this paragraph earlier to link it more closely with `data-l10n-attrs`, if that is the referenced field.

::: intl/l10n/docs/fluent_tutorial.rst:496
(Diff revision 5)
> +
> +The above method creates a single localization context per document. This is the
> +default and will be sufficient for most scenarios.
> +
> +If the developer needs an additional, separate context, they can create it using
> +a `Localization` class:

It isn't cear to me what a context is, or why I would want a custom one. It may be good to go into more depth here.

::: intl/l10n/docs/fluent_tutorial.rst:496
(Diff revision 5)
> +
> +The above method creates a single localization context per document. This is the
> +default and will be sufficient for most scenarios.
> +
> +If the developer needs an additional, separate context, they can create it using
> +a `Localization` class:

Is it possible to have a custom context for a document when using markup localization?
Comment hidden (mozreview-request)
Thank you Matt and Mike!

Applied your feedback where appropriate and am going to land it now.

We'll be improving the docs over the coming weeks so if you notice something missing, please let us know!
Comment hidden (mozreview-request)

Comment 15

Last year
Pushed by zbraniecki@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/e0a165295ef8
Add Introduction to Fluent for Firefox Developers. r=flod

Comment 16

Last year
mozreview-review
Comment on attachment 8955027 [details]
Bug 1438655 - Add Introduction to Fluent for Firefox Developers.

https://reviewboard.mozilla.org/r/224206/#review231174

I know this already landed, but it's easy to comment in mozreview, and it can be used for the next round of updates.

::: intl/l10n/docs/fluent_tutorial.rst:188
(Diff revisions 5 - 7)
>  
>  In return, localizers enter the social contract by promising to provide an accurate
>  and clean translation of the messages that match the request.
>  
> -The developer is not to be bothered with inner logic and complexity that the
> -localization will use to construct the response. Whether declensions or other
> +In previous localization systems, developers were responsible for differentiating
> +string variant based on a platform via pre-processing instructions, or

variant based on a platform -> variants based on the platform

::: intl/l10n/docs/fluent_tutorial.rst:242
(Diff revisions 5 - 7)
> +      <span>Please, read the <a>privacy policy</a>.</span>
> +
> +
>  Fluent will overlay the translation onto the source fragment preserving attributes like
>  :code:`class` and :code:`href` from the source and adding translations for the elements
> -inside.
> +inside. The end result will look like this:

end result -> resulting localized content ?

::: intl/l10n/docs/fluent_tutorial.rst:277
(Diff revisions 5 - 7)
>  a JSON object storing variables exposed by the developer to the localizer.
>  
> -It is very rare that this attribute is needed for localizations which previously
> -used DTD, because such variables will usually have to be computed from the runtime code.
> +This is the main channel for the developer to provide additional variables
> +to be used in the localization.
> +
> +It is very rare that the arguments are needed for localizations which previously

I'd try to simplify this a bit. 

Arguments are rarely needed for situations where it’s currently possible to use
DTD, since such variables would need to be computed from the code at runtime.
It's worth noting that, when the :code:`l10n-args` are set in
the runtime code, they are in fact encoded as JSON and stored together with
:code:`l10n-id` as an attribute of the element.

::: intl/l10n/docs/fluent_tutorial.rst:561
(Diff revisions 5 - 7)
> +.. admonition:: Example
> +
> +  An example of a use case is the Preferences UI in Firefox which uses the
> +  main context to localize the UI but also to build a search index.
> +
> +  It is common to build such search index both in a current langauge and additionally

typo: language

also "a current language" -> "the current language"

::: intl/l10n/docs/fluent_tutorial.rst:562
(Diff revisions 5 - 7)
> +
> +  An example of a use case is the Preferences UI in Firefox which uses the
> +  main context to localize the UI but also to build a search index.
> +
> +  It is common to build such search index both in a current langauge and additionally
> +  in English since a lot of documentation and online help exists in that language.

Add a comma before since, exists -> exist

in that language -> only in English (I think it's confusing right now which language this refers to)

::: intl/l10n/docs/fluent_tutorial.rst:564
(Diff revisions 5 - 7)
> +  main context to localize the UI but also to build a search index.
> +
> +  It is common to build such search index both in a current langauge and additionally
> +  in English since a lot of documentation and online help exists in that language.
> +
> +  A developer may create manually a new context with the same resources as the main one

I think you can drop 'uses' at the end of the first sentence.
Thanks Flod! I'll keep the comments here and we can use them when we'll be updating the tutorial.
https://hg.mozilla.org/mozilla-central/rev/e0a165295ef8
Status: ASSIGNED → RESOLVED
Closed: Last year
Resolution: --- → FIXED
Target Milestone: --- → mozilla60
```
@stas> https://firefox-source-docs.mozilla.org/intl/l10n/l10n/fluent_tutorial.html#partial-arguments should use "month:" rather than "month=" in the DATETIME example
```
You need to log in before you can comment on or make changes to this bug.