fluent.syntax

The Python parser, serializer, and AST toolkit for reading, writing, and transforming Fluent localization files.

Library
PyPI
v0.19.0
244stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
49/100Fair
Development Activity16
Maintenance32
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
79/100Good
Architecture85
Code Quality92
Innovation62
Learning Curve75

fluent.syntax is the foundational parsing layer of the Project Fluent Python ecosystem. It turns Fluent (.ftl) source text into a fully-typed abstract syntax tree, serializes that tree back to spec-compliant Fluent source, and exposes Visitor/Transformer classes for walking and rewriting the tree — the same ergonomics Python developers already know from the standard library’s ast module.

It underpins fluent.runtime (the localization library that actually resolves translated strings at runtime) and any tooling — linters, formatters, migration scripts, editor plugins — that needs to read or manipulate .ftl files programmatically rather than treat them as opaque text.

What You Get

  • A recursive-descent FluentParser that turns Fluent source text into a typed ast.Resource tree
  • A FluentSerializer that converts an AST back into spec-compliant Fluent source text
  • Visitor and Transformer base classes for read-only traversal or in-place rewriting of the AST, modeled on Python’s own ast.NodeVisitor/ast.NodeTransformer
  • Full AST coverage of the Fluent grammar: messages, terms, attributes, patterns, placeables, select expressions, comments, and junk (malformed) entries
  • Optional source Span tracking on every node for building tools that need accurate source positions
  • to_json/from_json helpers for serializing the AST itself to and from JSON
  • Full type hints and a py.typed marker for static-analysis-friendly integration

Common Use Cases

  • Powering fluent.runtime’s message resolution by parsing .ftl translation files into an AST it can evaluate
  • Building linters or validators that catch malformed Fluent syntax before it ships
  • Writing migration or refactoring scripts that programmatically rewrite .ftl files (renaming messages, restructuring attributes) via Transformer
  • Building editor tooling (syntax highlighting, autocomplete, go-to-definition) that needs accurate source spans for Fluent files
  • Round-tripping Fluent files through automated formatters that reparse and reserialize source to a canonical style

Under The Hood

Architecture The package is organized as a tight, layered pipeline with a small surface area: stream.py provides a character-level ParserStream/FluentParserStream cursor, parser.py’s FluentParser consumes that stream via a recursive-descent grammar (decorated with a with_span wrapper that attaches source positions to every node), ast.py defines the resulting BaseNode-derived tree (with clone, equals, to_json/from_json built in), and serializer.py’s FluentSerializer walks that same tree back into source text. visitor.py adds an orthogonal Visitor/Transformer layer that traverses any AST via vars() introspection rather than hardcoded per-node logic, so it stays correct as the grammar evolves. The __init__.py facade exposes just parse()/serialize() plus the AST module for typical callers, while fluent.runtime and other consumers reach into the lower layers directly. Because ast.BaseNode’s field introspection is load-bearing for cloning, equality, JSON (de)serialization, and traversal alike, it’s the one abstraction the rest of the package is built around.

Tech Stack Pure Python 3.9+ with zero runtime dependencies — only the standard library (re, json, typing, sys). It ships a py.typed marker, meaning it’s fully type-hinted and safe for downstream static analysis. The build backend is setuptools via a standard pyproject.toml, and the project (part of the python-fluent monorepo alongside fluent.runtime and fluent.pygments) uses uv for dependency and environment management in CI.

Code Quality Testing is extensive and fixture-driven: tests/syntax/ pairs .ftl source fixtures with expected .json AST output across dedicated suites for structure, references, literals, entries, serialization, equality, AST JSON round-tripping, and visitor behavior, including deliberately malformed input to exercise junk-node recovery. CI runs flake8 and mypy for linting and type checking, then runs the full pytest suite across a matrix of three operating systems and six Python versions (3.9–3.14), plus a separate compatibility job that installs older published fluent.syntax releases against the current fluent.runtime to catch cross-version breakage. Naming is consistent and idiomatic (snake_case functions, PascalCase AST classes), and parse failures are represented explicitly via a typed ParseError rather than swallowed.

What Makes It Unique Rather than a generic parser-combinator toolkit, this is a purpose-built implementation of Fluent’s specific grammar — including its distinctive select-expression/plural-variant branching, the message/term distinction, and attribute placeables — with per-node source spans available throughout, which is what makes source-accurate tooling (editors, linters, formatters) practical to build on top of it. Its Visitor/Transformer pair deliberately mirrors the ergonomics of Python’s own ast.NodeVisitor/ast.NodeTransformer, so anyone who has written a Python AST transform already knows how to extend Fluent files programmatically.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search