Skip to content

Commit

Permalink
Require the message body to be indented
Browse files Browse the repository at this point in the history
Fix #12, #17, #18.

With this change, the entire body of a message must be indented. This makes
error recovery very easy: finding the next message definition is as simple as
finding the next identifier with no indentation.

It also opens up a number of opportunities: we can remove the `|` syntax for
multiline blocks of text and allow line breaks inside of placeables safely.

The change also allows the value to be defined on a new line, making the
following examples equivalent:

    lipsum = Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi
        pellentesque congue metus, non mattis sem faucibus sit amet.

    lipsum =
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi
        pellentesque congue metus, non mattis sem faucibus sit amet.

Lastly, quoted patterns are only available inside of placeables, cannot contain
aother placeables and cannot be used directly as values.

The exact semantics of \ escapes will be defined in #22.
  • Loading branch information
stasm committed Feb 24, 2017
1 parent e5da507 commit 45cb43a
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 68 deletions.
2 changes: 1 addition & 1 deletion guide/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ emails = You have { $unreadEmails } unread emails.
emails2 = You have { NUMBER($unreadEmails) } unread emails.
last-notice =
| Last checked: { DATETIME($lastChecked, day: "numeric", month: "long") }.
Last checked: { DATETIME($lastChecked, day: "numeric", month: "long") }.
```

```json
Expand Down
16 changes: 8 additions & 8 deletions guide/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,16 @@ the purpose of choosing the correct plural category:

```
liked-count = { $num ->
[0] No likes yet.
[one] One person liked your message
*[other] { $num } people liked your message
}
[0] No likes yet.
[one] One person liked your message
*[other] { $num } people liked your message
}
liked-count2 = { NUMBER($num) ->
[0] No likes yet.
[one] One person liked your message
*[other] { $num } people liked your message
}
[0] No likes yet.
[one] One person liked your message
*[other] { $num } people liked your message
}
```

### `DATETIME`
Expand Down
12 changes: 6 additions & 6 deletions guide/selectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

```
emails = { $unreadEmails ->
[one] You have one unread email.
*[other] You have { $unreadEmails } unread emails.
}
[one] You have one unread email.
*[other] You have { $unreadEmails } unread emails.
}
```

```json
Expand Down Expand Up @@ -34,7 +34,7 @@ unformatted number:

```
your-score = { NUMBER($score, minimumFractionDigits: 1) ->
[0.0] You scored zero points. What happened?
*[other] You scored { NUMBER($score, minimumFractionDigits: 1) } points.
}
[0.0] You scored zero points. What happened?
*[other] You scored { NUMBER($score, minimumFractionDigits: 1) } points.
}
```
23 changes: 8 additions & 15 deletions guide/text.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
# Working With Text: Multiline and Quotes
# Working With Text

```
about = About Our Software
description =
| Loki is a simple micro-blogging
| app written entirely in <i>HTML5</i>.
| It uses FTL to implement localization.
more-info = " Read more about us! "
Loki is a simple micro-blogging
app written entirely in <i>HTML5</i>.
It uses FTL to implement localization.
```

The value of an FTL message is usually a simple string.
The value of an FTL message is usually a simple string. It begins after the
`=` and may continue over multiple lines as long as it is indented by at least
one space.

By default, a string begins after a `=` and ends with the end of line. You can
also define easy-to-read, multiline strings with a pipe mark-up, as can be seen
in the `description` message.

FTL ignores leading whitespaces in front of the value allowing localizers to
align their messages for readability. For multiline strings, whitespaces both
before and after the pipe are ignored. In rare cases where leading whitespaces
should be part of the value, FTL allows for special quote delimited strings as
can be seen in the `more-info` message.
Leading and trailing white-space is ignored.
14 changes: 7 additions & 7 deletions guide/variants.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

```
brand-name = {
*[nominative] Aurora
[genitive] Aurore
[dative] Aurori
[accusative] Auroro
[locative] Aurori
[instrumental] Auroro
}
*[nominative] Aurora
[genitive] Aurore
[dative] Aurori
[accusative] Auroro
[locative] Aurori
[instrumental] Auroro
}
about = O { brand-name[locative] }
```
Expand Down
7 changes: 7 additions & 0 deletions spec/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

- Require the message body to be indented.

Quoted strings are now only valid in placeables and cannot contain other
placeables.

Remove `|` for multiline blocks.

- (f176deb) Fix #30. Allow more characters in keys, and trim whitespace
around them

Expand Down
3 changes: 1 addition & 2 deletions spec/fluent.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ module Fluent
pat = Pattern(expr* elements, bool quoted)

-- Expressions
expr = Pattern(pat)
| String(string)
expr = String(string)
| Number(number)
| MessageReference(iden id)
| ExternalArgument(iden id)
Expand Down
67 changes: 38 additions & 29 deletions spec/fluent.ebnf
Original file line number Diff line number Diff line change
@@ -1,41 +1,50 @@
body ::= (entry NL)* entry? EOF
body ::= (_* NL)* (entry NL)* entry? EOF
entry ::= comment
| section
| message

comment ::= ('//' [^#xA#xD]* NL)+
section ::= '[[' __ word (__ word)* __ ']]'
comment ::= ('//' (char - NL)* )+
section ::= '[[' _? word (_ word)* _? ']]'

char ::= [https://www.w3.org/TR/REC-xml/#NT-Char]
__ ::= [#x20#x9]* /* space, tab */
NL ::= [#xA#xD]+ /* line feed, carriage return */

/* special chars: { } [ \ ] */
special ::= [#x5b#x5c#x5d#x7b#x7d]

/* line feed, carriage return; space, tab */
line-break ::= [#xA#xD]+
inline-space ::= [#x20#x9]+

/* if you break lines you need to indent afterwards */
break-indent ::= (line-break* inline-space)+

_ ::= inline-space
NL ::= line-break
__ ::= break-indent

identifier ::= [a-zA-Z_?-] [a-zA-Z0-9_?-]*
external ::= '$' identifier
word ::= [^#x20#x9#xA#xD#x5b#x5c#x5d]+ /* exclude: white space, [, \, ] */
word ::= (((char - line-break) - inline-space) - special)+
builtin ::= [A-Z_?-]+
number ::= [0-9]+ ('.' [0-9]+)?

variant-key ::= number | variant-symbol
variant-symbol ::= word (__ word)*
variant ::= '[' variant-key ']' __ pattern NL
default-variant ::= '*' variant
variant-list ::= NL (__ variant)* __ default-variant (__ variant)*

attribute ::= '.' identifier __ '=' __ pattern NL
attribute-list ::= NL (__ attribute)+

message ::= identifier __ '=' __ (pattern attribute-list? | attribute-list)
pattern ::= unquoted-pattern
| quoted-pattern
unquoted-pattern ::= (unquoted-text | placeable | block-text)+
quoted-pattern ::= '"' (quoted-text | placeable)* '"'
unquoted-text ::= ([^{] | '\{')+
quoted-text ::= ([^{"] | '\{' | '\"')+
block-text ::= NL __ '|' unquoted-pattern

placeable ::= '{' __ (expression | select-expression | variant-list) __ '}'
expression ::= quoted-pattern
variant-symbol ::= word (_ word)*
variant ::= NL __ '[' _? variant-key _? ']' __ pattern
default-variant ::= NL __ '*[' _? variant-key _? ']' __ pattern
variant-list ::= variant* default-variant variant*

attribute ::= NL __ '.' identifier value
attribute-list ::= attribute+

message ::= identifier (value attribute-list? | attribute-list)
value ::= _? '=' __? pattern
pattern ::= (text | placeable)+
text ::= ((char - line-break) - special | break-indent | '\' special)+
quoted-text ::= '"' (text | '\"')+ '"'

placeable ::= '{' __? (expression | select-expression | variant-list) __? '}'
expression ::= quoted-text
| number
| identifier
| external
Expand All @@ -44,10 +53,10 @@ expression ::= quoted-pattern
| call-expression
| placeable

select-expression ::= expression __ ' ->' __ variant-list
select-expression ::= expression __ '->' __ variant-list
attribute-expression ::= identifier '.' identifier
variant-expression ::= identifier '[' __ variant-key __ ']'
call-expression ::= builtin '(' __ (argument ( __ ',' __ argument)*)? __ ')'
variant-expression ::= identifier '[' _? variant-key _? ']'
call-expression ::= builtin '(' __? (argument ( __? ',' __? argument)*)? __? ')'
argument ::= expression
| named-argument
named-argument ::= identifier __ ':' __ ('"' quoted-text? '"' | number)
named-argument ::= identifier __? ':' __? (quoted-text | number)

0 comments on commit 45cb43a

Please sign in to comment.