{"id":1460,"date":"2020-05-26T16:58:45","date_gmt":"2020-05-26T16:58:45","guid":{"rendered":"http:\/\/blog.mozilla.org\/l10n\/?p=1460"},"modified":"2020-05-26T16:58:45","modified_gmt":"2020-05-26T16:58:45","slug":"how-to-unleash-the-full-power-of-fluent-as-a-localizer","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/l10n\/2020\/05\/26\/how-to-unleash-the-full-power-of-fluent-as-a-localizer\/","title":{"rendered":"How to unleash the full power of Fluent as a localizer"},"content":{"rendered":"<p><a href=\"https:\/\/projectfluent.org\/\">Fluent<\/a> is an extremely powerful system, providing localizers with a level of flexibility that has no equivalent in other localization systems. It can be as straightforward as older formats, thanks to <a href=\"https:\/\/pontoon.mozilla.org\/\">Pontoon<\/a>\u2019s streamlined interface, but it requires some understanding of the syntax to fully utilize its potential.<\/p>\n<p>Here are a few examples of how you can get the most out of Fluent. But, before jumping in, you should get familiar with our documentation about <a href=\"https:\/\/mozilla-l10n.github.io\/localizer-documentation\/tools\/fluent\/index.html\">Fluent syntax for localizers<\/a>, and make sure to know how to switch to the <a href=\"https:\/\/mozilla-l10n.github.io\/localizer-documentation\/tools\/pontoon\/ui.html#fluent---ftl-files\">Advanced FTL mode<\/a>, to work directly with the syntax of each message.<\/p>\n<h2>Plurals<\/h2>\n<p>Plural forms are a really <a href=\"https:\/\/unicode-org.github.io\/cldr-staging\/charts\/37\/supplemental\/language_plural_rules.html\">complex subject<\/a>; some locales don\u2019t use any (e.g. Chinese), English and most Romance languages use two (one vs many), others use all the six forms defined by CLDR (e.g. Arabic). Fluent gives you all the flexibility that you need, without forcing you to provide all forms if you don\u2019t need them (unlike Gettext, for example).<\/p>\n<p>Consider this example displayed in Pontoon for Arabic:<\/p>\n<p><a href=\"https:\/\/blog.mozilla.org\/l10n\/files\/2020\/05\/arabic_plurals.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-1461\" src=\"https:\/\/blog.mozilla.org\/l10n\/files\/2020\/05\/arabic_plurals-600x397.png\" alt=\"Screenshot of a plural string in Pontoon for Arabic\" width=\"600\" height=\"397\" srcset=\"https:\/\/blog.mozilla.org\/l10n\/files\/2020\/05\/arabic_plurals-600x397.png 600w, https:\/\/blog.mozilla.org\/l10n\/files\/2020\/05\/arabic_plurals-252x167.png 252w, https:\/\/blog.mozilla.org\/l10n\/files\/2020\/05\/arabic_plurals-768x508.png 768w, https:\/\/blog.mozilla.org\/l10n\/files\/2020\/05\/arabic_plurals.png 1530w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/a>The underlying reference message is:<\/p>\n<pre># Variables:\r\n# $numBreachesResolved (Number) - Number of breaches marked as resolved by the user on Monitor.\r\n# $numBreaches (Number) - Number of breaches in which a user's data was involved, detected by Monitor.\r\nmonitor-partial-breaches-title =\r\n    { $numBreaches ->\r\n       *[other] { $numBreachesResolved } out of { $numBreaches } breaches marked as resolved\r\n    }\r\n<\/pre>\n<p>You can see it if you switch to the FTL advanced mode, and temporarily <i>COPY<\/i> the English source.<\/p>\n<p>This gives you a lot of information:<\/p>\n<ul>\n<li>It\u2019s a message with plurals, although only the <code>other<\/code> category is defined for English.<\/li>\n<li>The <code>other<\/code> category is also the default, since it\u2019s marked with an asterisk.<\/li>\n<li>The value of <code>$numBreaches<\/code> defines which plural form will be used.<\/li>\n<\/ul>\n<p>First of all, since you only have one form, you can decide to remove the select logic completely. This is equivalent to:<\/p>\n<pre>monitor-partial-breaches-title = { $numBreachesResolved } out of { $numBreaches } breaches marked as resolved<\/pre>\n<p>You might ask: why is there a plural in English then? That\u2019s a great question! It\u2019s just a small hack to trick Pontoon into displaying the UI for plurals.<\/p>\n<p>But there\u2019s more: what if this doesn\u2019t work for your language? Consider Italian, for example: to get a more natural sounding sentence, I would translate it as \u201c10 breaches out of 20 marked as resolved\u201d. There are two issues to solve: I need <code>$numBreachesResolved<\/code> (number of solved breaches) to determine which plural form to use, not the total number, and I need a singular form. While I can\u2019t make these changes directly through Pontoon\u2019s UI, I can still write my own syntax:<\/p>\n<pre>monitor-partial-breaches-title =\r\n    { $numBreachesResolved ->\r\n        [one] { $numBreachesResolved } violazione su { $numBreaches } contrassegnata come risolta\r\n       *[other] { $numBreachesResolved } violazioni su { $numBreaches } contrassegnate come risolte\r\n    }\r\n<\/pre>\n<p>Notice the two relevant changes:<\/p>\n<ul>\n<li>There is now a <code>one<\/code> form (used for 1 in Italian).<\/li>\n<li><code>$numBreachesResolved<\/code> is used to determine which plural form is selected (<code>$numBreachesResolved -><\/code>).<\/li>\n<\/ul>\n<h2>Terms<\/h2>\n<p>We recently started migrating <a href=\"https:\/\/pontoon.mozilla.org\/projects\/mozillaorg\/\">mozilla.org<\/a> to Fluent, and there are a lot of terms defined for specific feature names and brands. Using terms instead of hard-coding text in strings helps ensure consistency and enforce branding rules. The best example is probably the term for <i>Firefox Account<\/i>, where the \u201caccount\u201d part is localizable.<\/p>\n<pre>-brand-name-firefox-account = Firefox Account\r\n<\/pre>\n<p>In Italian it\u2019s translated as \u201caccount Firefox\u201d. But it should be \u201cAccount Firefox\u201d if used at the beginning of a sentence. How can I solve this, without removing the term and getting warnings in Pontoon? I can define a parameterized term.<\/p>\n<pre>-brand-name-firefox-account =\r\n    { $capitalization ->\r\n       *[lowercase] account Firefox\r\n        [uppercase] Account Firefox\r\n    }\r\n<\/pre>\n<p>In this example, the default is lowercase, since it\u2019s the most common form in Italian. By using only the term reference <code>{ -brand-name-firefox-account }<\/code>, it will be automatically displayed as \u201caccount Firefox\u201d.<\/p>\n<pre>login-button = Accedi al tuo { -brand-name-firefox-account }\r\n<\/pre>\n<p>What if I need the uppercase version?<\/p>\n<pre>login-title = { -brand-name-firefox-account(capitalization: \"uppercase\") }\r\n<\/pre>\n<p>You can find more information about terms, as well as other examples, in <a href=\"https:\/\/mozilla-l10n.github.io\/localizer-documentation\/tools\/fluent\/basic_syntax.html#terms-and-parameterized-terms\">our documentation<\/a>. And don\u2019t forget to check the <a href=\"https:\/\/mozilla-l10n.github.io\/styleguides\/mozilla_general\/#brands-copyright-and-trademark\">rules about brand names<\/a>.<\/p>\n<h2>Things you shouldn\u2019t translate<\/h2>\n<p>Variables and placeables should not be translated. The good news is that they\u2019re easy to spot, since they\u2019re surrounded by curly parentheses:<\/p>\n<ul>\n<li>Variable reference: <code>{ $somevariable }<\/code><\/li>\n<li>Term reference: <code>{ -someterm }<\/code><\/li>\n<li>Message reference: <code>{ somemessage }<\/code><\/li>\n<\/ul>\n<p>The content between parentheses must be kept as in the English source string.<\/p>\n<p>The same is valid for the <code>data-l10n-name<\/code> attribute in HTML elements. Consider for example:<\/p>\n<pre>update-downloading = &lt;img data-l10n-name=\"icon\"\/>Downloading update \u2014 <label data-l10n-name=\"download-status\"\/>\r\n<\/pre>\n<p>The only thing to translate in this message is \u201cDownloading update -\u201d. \u201cIcon\u201d and \u201cdownload-status\u201d should be kept untranslated.<\/p>\n<p>The rule of thumb is to pay extra attention when there are curly parentheses, since they\u2019re used to identify special elements of the syntax.<\/p>\n<p>Another example:<\/p>\n<pre>menu-menuitem-preferences =\r\n   { PLATFORM() ->\r\n       [windows] Options\r\n      *[other] Preferences\r\n   }\r\n<\/pre>\n<p><code>PLATFORM()<\/code> is a <a href=\"https:\/\/mozilla-l10n.github.io\/localizer-documentation\/tools\/fluent\/functions.html\">function<\/a>, and should not be translated. <code>windows<\/code> and <code>other<\/code> are variant names, and should be kept unchanged as well.<\/p>\n<p>One other thing to look out for are style attributes, since they\u2019re used for CSS rules.<\/p>\n<pre>downloads-panel-list =\r\n    .style = width: 70ch\r\n<\/pre>\n<p><code>width: 70ch<\/code> is a CSS rule to define the width of an element, and should be kept untranslated. The only thing that you might want to change is the actual value, for example to make it larger (<code>width: 75ch<\/code>). Note that <code>ch<\/code> is a <a href=\"https:\/\/developer.mozilla.org\/docs\/Learn\/CSS\/Building_blocks\/Values_and_units\">unit of measure used in CSS<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fluent is an extremely powerful system, providing localizers with a level of flexibility that has no equivalent in other localization systems. It can be as straightforward as older formats, thanks &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/l10n\/2020\/05\/26\/how-to-unleash-the-full-power-of-fluent-as-a-localizer\/\">Read more<\/a><\/p>\n","protected":false},"author":663,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[286410,137,610],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/posts\/1460"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/users\/663"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/comments?post=1460"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/posts\/1460\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/media?parent=1460"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/categories?post=1460"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/l10n\/wp-json\/wp\/v2\/tags?post=1460"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}