Skip to content

Commit

Permalink
Introduce private messages.
Browse files Browse the repository at this point in the history
Fix projectfluent#62.

Private messages are similar to regular messages but they can only be
used as references in other messages. Their identifiers start with at
least one dash `-`, e.g. `-brand-name`. The runtime cannot retrieve
private messages directly. They are best used to define glossary terms
which can be used consistently across the localization of the entire
product.

Private messages can store some grammatical information about themselves
in tags. Private messages are not allowed to have attributes.
  • Loading branch information
stasm committed Nov 30, 2017
1 parent b9552ae commit 5ba0357
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 38 deletions.
3 changes: 2 additions & 1 deletion guide/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

* [Hello world](hello.md)
* [Writing Text](text.md)
* [Referencing Messages](references.md)
* [External Data](external.md)
* [Referencing Messages](references.md)
* [Selectors](selectors.md)
* [Variants](variants.md)
* [Private Messages](private.md)
* [Tags](tags.md)
* [Attributes](attributes.md)
* [Sections](sections.md)
Expand Down
2 changes: 2 additions & 0 deletions guide/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ messages.
This feature is particularly useful in translating more complex widgets since,
thanks to all attributes being stored on a single unit, it's easier for editors,
comments, and tools to identify and work with the given message.

Attributes may not be defined on [private messages](private.html).
11 changes: 8 additions & 3 deletions guide/external.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Interpolation and External Arguments

Strings in FTL 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 arguments into the
translation. External arguments are provided by the developer and may change
on runtime.

```
welcome = Welcome { $user }
unreadEmails = { $user } has { $emailCount } unread emails.
Expand All @@ -11,9 +19,6 @@ unreadEmails = { $user } has { $emailCount } unread emails.
}
```

Another common use case for a placeable is to put an external argument,
provided by the developer, into the string.

There are all kinds of external data that might be useful in providing a good
localization: user names, number of unread messages, battery level, current
time, time left before an alarm goes off, etc.
Expand Down
19 changes: 19 additions & 0 deletions guide/private.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Private Messages

```
-brand-name = Firefox
app-title = { -brand-name }
has-updated = { -brand-name } has been updated.
```

Private messages are similar to regular messages but they can only be used as
references in other messages. Their identifiers start with at least one dash
`-` like in the example above: `-brand-name`. The runtime cannot retrieve
private messages directly. They are best used to define terms which can be
used consistently across the localization of the entire product.

Private messages can store some grammatical information about themselves in
[tags](tags.html) which are the topic of the next chapter.

Private messages are not allowed to have [attributes](attributes.html).
29 changes: 17 additions & 12 deletions guide/references.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
# Message References

```
brandName = Loki
installing = Installing { brandName }.
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.
```

Strings in FTL may use special syntax to incorporate small pieces of
programmable interface. Those pieces are denoted with curly braces `{` and `}`
and are called placeables.
Referencing other messages generally helps to keep certain translations
consistent across the interface and makes maintenance easier.

One example of a placeable is a reference to another message.
It is also particularly handy for keeping branding separated from the rest of
the translations, so that it can be changed easily when needed, e.g. during
the build process of the application. This use-case is best served by
defining a [private message](private.html) with a leading dash `-`, like
`-brand-name` in the example below.

Referencing other messages generally helps to keep certain translations
consistent across the interface and makes maintenance easier. It is also
particularly handy for keeping branding separated from the rest of the
translations, so that it can be changed easily when needed, e.g. during the
build process of the application.
```
-brand-name = Firefox
installing = Installing { -brand-name }.
```

The use of the private message indicates to tools and to the localization
runtime that `-brand-name` is not supposed to be used directly in the product
but rather should be referenced in other messages.
24 changes: 13 additions & 11 deletions guide/tags.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
# Tags

```
brand-name = Aurora
-brand-name = Aurora
#żeński
has-updated = { brand-name ->
[męski] { brand-name} został zaktualizowany.
[żeński] { brand-name } została zaktualizowana.
*[inny] Program { brand-name } został zaktualizowany.
has-updated =
{ -brand-name ->
[męski] { -brand-name} został zaktualizowany.
[żeński] { -brand-name } została zaktualizowana.
*[inny] Program { -brand-name } został zaktualizowany.
}
```

Sometimes translations might vary depending on some grammatical trait of
another message. In the example above the form of the past tense of _has been
updated_ depends on the grammatical gender of `brand-name`.
Sometimes translations might vary depending on some grammatical trait of a
private message used to create them. In the example above the form of the
past tense of _has been updated_ depends on the grammatical gender of
`-brand-name`.

In such cases you can _tag_ messages with simple one-word _hashtags_ and then
define different translations based on these tags. You define them with `#`
which must start on a new line under the message, indented.
In such cases you can _tag_ private messages with simple one-word _hashtags_
and then define different translations based on these tags. You define them
with `#` which must start on a new line under the message, indented.

Hashtags are specific to your language's grammar and don't have to be in
English. In the example above, _żeński_ means _feminine_, _męski_ is
Expand Down
7 changes: 4 additions & 3 deletions guide/variants.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Variants

```
brand-name = {
-brand-name =
{
*[nominative] Aurora
[genitive] Aurore
[dative] Aurori
Expand All @@ -10,15 +11,15 @@ brand-name = {
[instrumental] Auroro
}
about = O { brand-name[locative] }
about = O { -brand-name[locative] }
```

As we stated at the beginning of this guide, messages primarily consist of
string values. A single string value can have multiple branches, or variants,
which are chosen based on the value of a selector. In some cases, however, we
don't need any selector and instead just want to define multiple variants of
the message and use them from within other messages. For instance, in languages
that use noun declension, `brand-name` may need to be declined when referred to
that use noun declension, `-brand-name` may need to be declined when referred to
from other messages.

FTL lets you define variants without a selector. Think of them as facets of the
Expand Down
9 changes: 8 additions & 1 deletion spec/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

## Unreleased

-
- Added private messages. (#62)

Private messages start their identifiers with at least one dash `-`. Tags
are only allowed on private messages. Attributes are only allowed on
public messages.

Private messages cannot be retrieved by the `MessageContext` runtime.
Tools may introduce different checks for private and public messages.

## 0.4.0 (November 14, 2017)

Expand Down
6 changes: 5 additions & 1 deletion spec/fluent.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ module Fluent
{
res = Resource(entry* body, comment? comment, span? span)

entry = Message(iden id, pat? value, attr* attributes, tag* tags, comment? comment)
entry = BaseMessage(base_message)
| Section(symb name, comment? comment)
| Comment(comment)
| Junk(str content)
attributes (annot* annotations, span? span)

base_message = Message(pat? value, attr* attributes)
| PrivateMessage(pat value, tag* tags)
attributes (iden id, comment? comment)

annot = Annotation(str code, str* args, str message, span? span)
span = Span(int start, int end)

Expand Down
16 changes: 10 additions & 6 deletions spec/fluent.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ NL ::= line-break
__ ::= break-indent

identifier ::= [a-zA-Z] [a-zA-Z0-9_-]*
external ::= '$' identifier
external-identifier ::= '$' identifier
private-identifier ::= '-'+ identifier
message-identifier ::= identifier | private-identifier

/* exclude whitespace and [ \ ] { } */
word ::= (((char - line-break) - inline-space) - [#x5b#x5c#x5d#x7b#x7d])+
Expand All @@ -41,7 +43,9 @@ tag-list ::= NL (__ tag)+
attribute ::= NL __ '.' identifier value
attribute-list ::= attribute+

message ::= identifier ((value tag-list?) | (value? attribute-list))
message ::= identifier ((value attribute-list?) | (value? attribute-list))
| private-identifier value tag-list?

value ::= _? '=' __? pattern
pattern ::= (text | placeable)+
/* text can only include newlines if they're followed by an indent */
Expand All @@ -59,8 +63,8 @@ placeable ::= '{' __? (inline-expression | block-expression) __? '}'

inline-expression ::= quoted-text
| number
| identifier
| external
| external-identifier
| message-identifier
| attribute-expression
| variant-expression
| call-expression
Expand All @@ -69,8 +73,8 @@ block-expression ::= select-expression
| variant-list

select-expression ::= inline-expression __ '->' __ variant-list
attribute-expression ::= identifier '.' identifier
variant-expression ::= identifier '[' _? variant-key _? ']'
attribute-expression ::= message-identifier '.' identifier
variant-expression ::= message-identifier '[' _? variant-key _? ']'
call-expression ::= builtin '(' __? (argument ( __? ',' __? argument)*)? __? ')'
argument ::= inline-expression
| named-argument
Expand Down

0 comments on commit 5ba0357

Please sign in to comment.