Skip to content

Commit

Permalink
Merge pull request #224 from stasm/guide-0.8
Browse files Browse the repository at this point in the history
Update the syntax guide to Syntax 0.8
  • Loading branch information
stasm authored Dec 13, 2018
2 parents 7f48a9b + a1169e8 commit b0440f0
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 84 deletions.
7 changes: 5 additions & 2 deletions guide/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Summary

* [Hello world](hello.md)
* [Hello, world!](hello.md)
* [Writing Text](text.md)
* [Placeables](placeables.md)
* [Special Characters](special.md)
* [Multiline Text](multiline.md)
* [Variables](variables.md)
* [Referencing Messages](references.md)
* [Selectors](selectors.md)
* [Variants](variants.md)
* [Attributes](attributes.md)
* [Terms](terms.md)
* [Variants (Deprecated)](variants.md)
* [Comments](comments.md)
* [Built-in Functions](builtins.md)
* [Functions](functions.md)
Expand Down
30 changes: 19 additions & 11 deletions guide/hello.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
# Hello World
# Hello, world!

In Fluent, the basic unit of translation is called a message.
The simplest example of a message looks like this:
In Fluent, the basic unit of translation is called a message. Messages are
containers for information. You use messages to identify, store, and recall
translation information to be used in the product. The simplest example of a
message looks like this:

```
hello = Hello, World!
hello = Hello, world!
```

Messages are containers for information. You use messages to identify, store,
and recall translation information to be used in the software's UI.

Each message has an identifier that allows the developer to bind it to the place
in the software where it will be used. The above message is called `hello`.

In its simplest form, a message has just a single string value; here *Hello,
World!*. Most of the messages you will work with in Fluent will look similar to
this. Some will be more complex, have more than one value variant, or use
expressions to select the right variant depending on the circumstances.
In its simplest form, a message has just a single text value. In the example
above the value is *Hello, world!*. The value begins at the first non-blank
character after the `=` sign, but there are rare exceptions related to
multiline text values. The next chapter ([Writing Text](text.html)) has all
the details.

The majority of messages in Fluent will look similar to the one above. Fluent
has been designed to keep these simple translations simple. Sometimes,
however, messages need more complexity. Throughout this guide, you'll learn
how to adjust messages to the grammar of your language and the requirements
of the localized product.

Read on to learn how to read and write Fluent!
105 changes: 105 additions & 0 deletions guide/multiline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Multiline Text

Text can span multiple lines as long as it is indented by at least one space.
Only the space character (`U+0020`) can be used for indentation. Fluent
treats tab characters as regular text.

```
single = Text can be written in a single line.
multi = Text can also span multiple lines
as long as each new line is indented
by at least one space.
block =
Sometimes it's more readable to format
multiline text as a "block", which means
starting it on a new line. All lines must
be indented by at least one space.
```

In almost all cases, patterns start at the first non-blank character and
end at the last non-blank character. In other words, the leading and
trailing blanks are ignored. There's one exception to this rule, due to
another rule which we'll cover below (in the `multiline2` example).

```
leading-spaces = This message's value starts with the word "This".
leading-lines =
This message's value starts with the word "This".
The blank lines under the identifier are ignored.
```

Line breaks and blank lines are preserved as long as they are positioned
inside of multiline text, i.e. there's text before and after them.

```
blank-lines =
The blank line above this line is ignored.
This is a second line of the value.
The blank line above this line is preserved.
```

In multiline patterns, all common indent is removed when the text value is
spread across multiple indented lines.

```
multiline1 =
This message has 4 spaces of indent
on the second line of its value.
```

We can visualize this behavior in the following manner and we'll use this
convention in the rest of this chapter:

```
# █ denotes the indent common to all lines (removed from the value).
# · denotes the indent preserved in the final value.
multiline1 =
████This message has 4 spaces of indent
████····on the second line of its value.
```

This behavior also applies when the first line of a text block is indented
relative to the following lines. This is the only case where a sequence of
leading blank characters might be preserved as part of the text value, even
if they're technically in the leading position.

```
multiline2 =
████··This message starts with 2 spaces on the first
████first line of its value. The first 4 spaces of indent
████are removed from all lines.
```

Only the indented lines comprising the multiline pattern participate in this
behavior. Specifically, if the text starts on the same line as the message
identifier, then this first line is not considered as indented, and is
excluded from the dedentation behavior. In such cases, the first line (the
unindeted one) still has its leading blanks ignored—because patterns start
on the first non-blank character.

```
multiline3 = This message has 4 spaces of indent
████····on the second line of its value. The first
████line is not considered indented at all.
# Same value as multiline3 above.
multiline4 = This message has 4 spaces of indent
████····on the second line of its value. The first
████line is not considered indented at all.
```

Note that if a multiline pattern starts on the same line as the identifier
and it only consists of one more line of text below it, then the indent
common to all _indented_ lines is equal to the indent of the second line,
i.e. the only indented line. All indent will be removed in this case.

```
multiline5 = This message ends up having no indent
████████on the second line of its value.
```
33 changes: 33 additions & 0 deletions guide/placeables.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Placeables

Text in Fluent may use special syntax to incorporate small pieces of
programmable interface. Those pieces are denoted with curly braces `{` and
`}` and are called placeables.

It's common to use placeables to interpolate external
[variables](variables.html) into the translation. Variable values are
provided by the developer and they will be set on runtime. They may also
dynamically change as the user uses the localized product.

```
# $title (String) - The title of the bookmark to remove.
remove-bookmark = Really remove { $title }?
```

It's also possible to [interpolate other messages and terms](references.html)
inside of text values.

```
-brand-name = Firefox
installing = Installing { -brand-name }.
```

Lastly, placeables can be used to insert [special characters](special.html)
into text values. For instance, due to placeables using `{` and `}` as
delimiters, inserting a literal curly brace into the translation requires
special care. Quoted text can be effectively used for the purpose:

```
opening-brace = This message features an opening curly brace: {"{"}.
closing-brace = This message features a closing curly brace: {"}"}.
```
2 changes: 1 addition & 1 deletion guide/references.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Another use-case for placeables is referencing one message in another one.

```
menu-save = Save
help-menu-save = Click "{ menu-save }" to save the file.
help-menu-save = Click { menu-save } to save the file.
```

Referencing other messages generally helps to keep certain translations
Expand Down
116 changes: 116 additions & 0 deletions guide/special.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Special Characters

In Fluent, text is the most important part of the file. As such, it doesn't
have any special syntax: you can just write it without any delimiters (e.g.
quotes) and you can use characters from all Unicode planes. Regular text
should be enough to store the vast majority of translations. In rare cases
when it's not, another type of text can be used: quoted text.

## Quoted Text

Quoted text uses double quotes as delimiters and cannot contain line breaks.
Like other types of expressions, it can be used inside of placeables (e.g.
`{"abc"}`). It's rarely needed but can be used to insert characters which are
otherwise considered special by Fluent in the given context. For instance,
due to placeables using `{` and `}` as delimiters, inserting a literal curly
brace into the translation requires special care. Quoted text can be
effectively used for the purpose:

```
opening-brace = This message features an opening curly brace: {"{"}.
closing-brace = This message features a closing curly brace: {"}"}.
```

In the example above the `{"{"}` syntax can be read as a piece of quoted text
`"{"` being interpolated into regular text via the placeable syntax: `{…}`.
As can be seen from this example, curly braces carry no special meaning in
quoted text. As a result, quoted text cannot feature any interpolations.

The same strategy as above can be used to ensure blank space is preserved in
the translations:

```
blank-is-removed = This message starts with no blanks.
blank-is-preserved = {" "}This message starts with 4 spaces.
```

In very rare cases, you may need to resort to quoted text to use a literal
dot (`.`), star (`*`) or bracket (`[`) when they are used as the first
character on a new line. Otherwise, they would start a new attribute or a new
variant.

```
leading-bracket =
This message has an opening square bracket
at the beginning of the third line:
{"["}.
```

```
attribute-how-to =
To add an attribute to this messages, write
{".attr = Value"} on a new line.
.attr = An actual attribute (not part of the text value above)
```

## Escape Sequences

Quoted text supports a small number of escape sequences. The backslash
character (`\`) starts an escape sequence in quoted text. In regular text,
the backslash is just the literal character with no special meaning.

| Escape sequence | Meaning |
|-----------------|---------|
| `\"` | The literal double quote. |
| `\uHHHH` | A Unicode character in the U+0000 to U+FFFF range. |
| `\UHHHHHH` | Any Unicode character. |
| `\\` | The literal backslash. |

Escape sequences are rarely needed, but Fluent supports them for the sake of
edge cases. In real life application using the actual character in the
regular text should be preferred.

```
# This is OK, but cryptic and hard to read and edit.
literal-quote1 = Text in {"\""}double quotes{"\""}.
# This is preferred. Just use the actual double quote character.
literal-quote2 = Text in "double quotes".
```

Quoted text should be used sparingly, most often in scenarios which call for
a special character, or when enclosing a characters in `{"` and `"}` makes
them easier to spot. For instance, the non-breaking space character looks
like a regular space in most text editors and it's easy to miss in a
translation. A Unicode escape sequence inside of a quoted text may be used
to make it stand out:

```
privacy-label = Privacy{"\u00A0"}Policy
```

A similar approach will make it clear which dash character is used in the
following example:

```
# The dash character is an EM DASH but depending on the font face,
# it might look like an EN DASH.
which-dash1 = It's a dash—or is it?
# Using a Unicode escape sequence makes the intent clear.
which-dash2 = It's a dash{"\u2014"}or is it?
```

Any Unicode character can be used in regular text values and in quoted text.
Unless readability calls for using the escape sequence, always prefer the
actual Unicode character.

```
# This will work fine, but the codepoint can be considered
# cryptic by other translators.
tears-of-joy1 = {"\U01F602"}
# This is preferred. You can instantly see what the Unicode
# character used here is.
tears-of-joy2 = 😂
```
Loading

0 comments on commit b0440f0

Please sign in to comment.