Categories: L20n

Recent syntax changes to L20n

Localizers and developers alike are instructed on some of L20n’s basic syntactic elements. Both can learn how these changes in syntax will affect L10n on each side of the fence. Since the examples provided below may be complicated for some localizers to fully understand, please contact Stas with any questions you have.

As L20n nears the 1.0 release, it matures as a programming language and a localization platform.  The feature set stabilizes, and with it, the syntax gains its final form.  In this post, I’d like to take some time to summarize the recent changes to L20n’s syntax and explain the rationale behind them.

Referencing entities and context variables

We noticed a need to distinguish between references to other entities and macros, defined in the localization files, and the context variables provided by the developer at run-time.

Consequently, we introduced the $ prefix to tell the context variables from other references.   In the example below, notice how $numOpenTabs, whose value is given by the developer, is referenced by typing {{ $numOpenTab }}. On the other hand, brandName, which is another entity defined in the same file, is referenced via {{ brandName }}.

    <plural($n) { $n == 1 ? 'one' : 'many' }>
    <brandName "Firefox">
    <quitConfirm[plural($numOpenTabs)] {
      one: "Close one open tab and quit {{ brandName }}.",
      many: "Close {{ $numOpenTabs }} open tabs and quit {{ brandName }}.",

Find more examples and background information in my blog post entitled Syntax changes to L20n data types.

Global variables

The introduction of globals gives L20n a media-query-like features. Localizers will be able to adjust the translations to the run-time conditions, such as the screen width and the current time.

    <doNotTrack[@screenWidth <= 480 ? "short" : "long"] {
      short: "Tell sites not to track me",
      long: "Tell websites I do not want to be tracked."

Check out other code examples in my blog post entitled Media queries for L20n with globals.

Default hash values

Another set of syntax changes makes L20n more robust by improving error recovery and reducing redundancy.

In the following code sample, note the asterisk prefix (*) for the nominative hash key.  The prefix denotes a default value for the hash.  If brandName is referenced without specifying a hash key, the value corresponding to the nominative key will be returned, thus guaranteeing that {{ brandName }} will resolve to a string.

    <brandName {
     *nominative: "Firefox",
      genitive: "Firefox's"

    <about1 "About {{ brandName.nominative }}">
    <about2 "About {{ brandName }}">  // produces the same as about1

Local entities and attributes

The last but not the least set of changes relate to the scope of entities, macros and attributes.

Assuming that the “regular” entities are all public (accessible by tools and the developers), L20n will also allow entities with a local scope, prefixed with an underscore (_).

These entities will only be visible to the localizers of the current locale.  Developers will not be able to ask the L20n API for their values, and tools will not report on their status as compared to the source locale.

Localizers will be able to create local helper entities and macros, in order to improve consistency of translations and further reduce redundancy.

Consider the example below.  By defining a local entity called _cancel, the localizer is able to abstract the translation of four other entities and store the related logic (the @os index) in a single place.

    <_cancel[@os] {
     *default: "Anuluj",
      mac: "Poniechaj"
    <installCancel "{{ _cancel }}">
    <syncConnectCancel "{{ _cancel }}">
    <saveFileCancel "{{ _cancel }}">
    <printDialogCancel "{{ _cancel }}">

Find out more about the default values and the local scope in my blog post entitled Default values and local entities and attributes in L20n.

Related reading & discussion

If you’re interested by L20n, be sure to read the wiki or to post in the newsgroup.

No comments yet

Post a comment

Leave a Reply

Your email address will not be published. Required fields are marked *