Project Fluent

repository·main·Indexed 23 days ago

https://github.com/projectfluent/fluent

A localization system designed to handle natural language complexities in translations. This repository provides the specification and reference implementation for the Fluent Syntax (FTL), which supports features such as gender, plurals, and conjugations. It includes a parser-combinator architecture, a CLI tool for parsing FTL files into JSON ASTs, and a tool to generate EBNF from grammar.js. While this is the reference implementation, official production implementations are available for JavaScript (fluent.js), Python (python-fluent), and Rust (fluent-rs).

Tokens
9.7K
Snippets
29
Records
59
Agent score
81%

What's inside Fluent

  1. What is Fluent and FTL?

    main

    Fluent is a localization system designed to leverage the expressive power of natural language.

    FTL (Fluent Translation List) is the specific syntax used to describe translation resources within Project Fluent. It allows for complex, natural-sounding translations that go beyond simple key-value pairs.

  2. Understand Fluent Syntax (FTL)

    main
    Fluent Syntax (FTL), which stands for Fluent Translation List, is the syntax used for describing translation resources in Project Fluent. The grammar for FTL is formally defined using EBNF (Extended Backus-Naur Form) and is available in the fluent.ebnf file within the repository. For a detailed explanation of how to write and structure FTL files, refer to the official Fluent Syntax Guide.
  3. What are Terms in Fluent

    main

    Terms are special identifiers used to define vocabulary and glossary items that can be reused consistently across a product.

    Key characteristics:

    • Identifiers: Must start with a single dash - (e.g., -brand-name).
    • Usage: They can only be used as references within other messages; the runtime cannot retrieve terms directly.
    • Purpose: Best used for defining core concepts or brand names that appear in multiple messages.
    -brand-name = Firefox
    
    about = About { -brand-name }.
    update-successful = { -brand-name } has been updated.
  4. Understand Fluent Syntax compatibility types

    main

    Fluent defines three types of changes that affect how translation files are parsed and authored:

    • Backwards incompatible changes: Changes that cause old files to fail parsing in current versions (e.g., removing a feature and reporting a SyntaxError).
    • Extensions: Changes that introduce new syntax that was previously forbidden. These make current files incompatible with old parsers, but old files remain compatible with current parsers.
    • Deprecations: Non-breaking changes that encourage modern syntax while providing a transition period. Deprecations signal that a feature will be removed in a future major version.
  5. Use placeables to interpolate variables and terms

    main

    In Fluent, placeables are small pieces of programmable interface denoted by curly braces { and }. They allow you to inject dynamic content into translations at runtime.

    There are two primary ways to use placeables:

    1. Variables: Use a $ prefix (e.g., { $variableName }) to interpolate values provided by the developer at runtime. These are ideal for user-specific data like names or titles.
    2. Terms/References: Use a - prefix (e.g., { -term-name }) to interpolate the value of another message or term defined within the Fluent files.
    // Using a variable
    remove-bookmark = Really remove { $title }?
    
    // Using a term reference
    -brand-name = Firefox
    installing = Installing { -brand-name }.
  6. Use quoted text for special characters in Fluent

    main

    While most Fluent translations can be written as regular text without delimiters, quoted text (delimited by double quotes) is used to insert characters that have special meaning in Fluent's syntax.

    Common use cases for quoted text include:

    • Inserting curly braces: Since { and } are used for placeables, use {"{"} or {"}"} to include literal braces.
    • Preserving leading whitespace: Use {" "} at the start of a message to prevent Fluent from stripping leading blanks.
    • Preventing attribute/variant triggers: If a line starts with a dot (.), star (*), or bracket ([), Fluent may interpret it as an attribute or variant. Wrap these characters in quoted text within a placeable (e.g., {"["}) to treat them as literal text.

    Note: Quoted text cannot contain interpolations/placeables itself; it is treated as a literal string when interpolated into regular text via the {"..."} syntax.

    opening-brace = This message features an opening curly brace: {"{"}.
    closing-brace = This message features a closing curly brace: {"}"}.
    
    blank-is-removed =     This message starts with no blanks.
    blank-is-preserved = {"    "}This message starts with 4 spaces.
    
    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)
  7. Understand the Resource AST node structure

    main

    The Resource node is the root of the AST. It contains the parsed content of the file and includes the original source string for error reporting purposes.

    Key properties:

    • type: Always 'Resource'.
    • body: An array of Entry nodes.
    • comment: The top-level comment, if any.
    • source: The original source string.
  8. Understand the basic unit of translation: Messages

    main

    In Fluent, the fundamental building block is a message. A message is a container used to identify, store, and recall translation information.

    Each message consists of:

    1. An identifier: A unique name (e.g., hello) used by developers to bind the message to a specific location in the software.
    2. A value: The actual text to be displayed (e.g., Hello, world!).

    In its simplest form, a message is defined by an identifier, an equals sign (=), and a text value. The value begins at the first non-blank character after the = sign.

    hello = Hello, world!
  9. Understand the Fluent Syntax (FTL)

    main

    Fluent uses a specific format called FTL (Fluent Syntax) to describe localization resources. FTL is designed to be human-readable while providing the expressive power necessary to handle complex natural language features such as:

    • Gender: Handling different grammatical genders.
    • Plurals: Managing singular and plural forms.
    • Conjugations: Managing verb and noun variations.
    • Other linguistic complexities: Addressing various nuances of natural language that simple key-value pairs cannot capture.
  10. Understand the difference between well-formed and valid Fluent syntax

    main

    Fluent distinguishes between two levels of correctness for resources:

    1. Well-formed: The resource conforms to the formal Fluent grammar (EBNF). It follows the structural rules of the language.
    2. Valid: The resource is both well-formed AND semantically correct. A resource can be well-formed but fail validation if it violates semantic rules.

    Why this matters: Some Fluent implementations might skip the semantic validation step for performance reasons. If you are using an implementation that only checks for well-formedness, you should validate your Fluent resources as a separate build-time or compile-time step to ensure they are semantically valid.

  11. Expect breaking changes in Fluent 2.0

    main

    A future 2.0 release is intended to break backward compatibility with the 1.x series. The primary purpose of 2.0 is to remove the deprecations accumulated during the 1.x lifecycle.

    Goals of the 2.0 transition:

    • Establish a fresh baseline for the Fluent 2.x standard.
    • Reduce cognitive complexity and improve learnability by cleaning up the syntax.
    • Allow implementations to optimize performance and streamline codebases by removing legacy support.