Skip to main content

Extract fluent keys from python code and organize them in .ftl files

Project description

FTL-Extract

Description

FTL-Extract is a Python package that extracts Fluent keys from .py files and generates .ftl file with extracted keys.

The ftl CLI is implemented in Rust and ships as a native binary inside the Python wheel.


Installation

Use the package manager pip to install FTL-Extract.

$ pip install FTL-Extract

Or use modern tool like UV to install FTL-Extract.

$ uv add --dev FTL-Extract

Usage

First of all, you should create locales directory in your project.

$ mkdir project_path/locales

Then, you can use the following command to extract keys from your code.

$ ftl extract project_path/code_path project_path/locales

By default, FTL-Extract will create a directory named en and put all keys into _default.ftl file.

You can also keep command defaults in pyproject.toml:

[tool.ftl-extract.extract]
code-path = "project_path/code_path"
locales-path = "project_path/locales"
languages = ["en", "uk"]
i18n-keys-append = ["LF", "LazyProxy"]
ignore-attributes-append = ["core"]
exclude-dirs-append = ["./tests/*"]
ignore-kwargs = ["when"]
comment-junks = true
comment-keys-mode = "comment"
line-endings = "lf"
cache = true

[tool.ftl-extract.stub]
locales-path = "project_path/locales/en"
stub-path = "project_path/code_path/stub.pyi"
export-tree = false

[tool.ftl-extract.check]
locales-path = "project_path/locales"
code-path = "project_path/code_path"
languages = ["uk"]
checks = ["all"]
suggest-from = ["en"]
fail-on = ["error"]
report-path = "reports/ftl-check"
report-format = "json"

Then run commands without repeating the configured paths:

$ ftl extract
$ ftl stub
$ ftl check

By default, ftl searches for pyproject.toml from the current directory upward. Use --config to select a specific file:

$ ftl --config ./pyproject.toml extract

CLI arguments override values from pyproject.toml; built-in defaults are used when neither is provided.

To print a ready-to-edit configuration sample, use:

$ ftl config sample
$ ftl config sample --command extract

In some cases, you may want to extract keys to specific .ftl files. So, there is new keyword argument _path in i18n.get and i18n.<key>.

# Before
i18n.get("key-1", arg1="value1", arg2="value2")

# After
i18n.get("key-1", arg1="value1", arg2="value2", _path="dir/ftl_file.ftl")

# Also
i18n.key_1(arg1="value1", arg2="value2", _path="dir/ftl_file.ftl")

# Or
i18n.some.key_1(arg1="value1", arg2="value2", _path="dir/ftl_file.ftl")

💁‍♂️ Explanation of the ftl extract command

$ ftl extract project_path/code_path project_path/locales
  • project_path/code_path - path to the project directory where the code is located.
  • project_path/locales - path to the project directory where the .ftl files will be located.

📚 Additional arguments

  • -l or --language - add a new language to the project.
  • -k or --i18n-keys - add additional i18n keys to the extractor.
  • -K or --i18n-keys-append - add additional i18n keys to the extractor and append them to the default list.
  • -p or --i18n-keys-prefix - add a prefix to the i18n keys. For example, self.i18n.<key>().
  • -e or --exclude-dirs - exclude specific directories from the extraction process.
  • -E or --exclude-dirs-append - add more directories to exclude from the extraction process.
  • -i or --ignore-attributes - ignore specific attributes of the i18n.* like i18n.set_locale.
  • -I or --append-ignore-attributes - add more attributes to ignore to the default list.
  • --ignore-kwargs - ignore specific kwargs of the i18n_keys like when=... in aiogram_dialog.I18nFormat(..., when=...).
  • --comment-junks - comments errored translations in the .ftl file.
  • --default-ftl-file - specify the default .ftl file name.
  • --comment-keys-mode - specify the comment keys mode. It will comment keys that are not used in the code or print warnings about them. Available modes: comment, warn.
  • -v or --verbose - print additional information about the process.
  • --dry-run - run the command without making any changes to the files.
  • --cache - cache extracted Python keys between runs and reuse them when source file metadata and extractor options are unchanged. By default, the cache is stored in .ftl-extract-cache/extract-<package-version>-v<schema-version>.bin.
  • --cache-path - custom cache directory or file path. Directory paths store the cache as extract-<package-version>-v<schema-version>.bin. Passing this option enables the cache.
  • --clear-cache - delete the existing extraction cache before running.

💁‍♂️ Explanation of the ftl stub command

$ ftl stub 'project_path/locales/<locale>' 'project_path/code_path'
  • project_path/locales/<locale> - path to the locales directory where the <locale> directory (e.g. en) contains .ftl files located.
  • project_path/code_path - path to the directory where the stub.pyi will be located.

💁‍♂️ Explanation of the ftl check command

$ ftl check project_path/locales --code-path project_path/code_path -l uk --suggest-from en
  • project_path/locales - path to the locales root directory that contains locale folders like en, uk, etc.

📚 Additional arguments

  • --check - validation to run. Supported checks: all, untranslated, syntax, references, missing, stale, kwargs. If omitted, all checks run.
  • --code-path - path to Python code. Required for --check missing, --check stale, and --check kwargs.
  • -l or --language - check only selected locales. Can be passed multiple times.
  • --suggest-from - locale(s) used to suggest non-placeholder translations for missing items. Can be passed multiple times.
  • --fail-on - minimum diagnostic severity that should return exit code 1, for example --fail-on error. --fail-on warn also fails on errors.
  • --report-path - optional report file path for batch processing reports. If no extension is provided, .txt or .json is appended automatically based on --report-format.
  • --report-format - report file format: terminal or json (default: json).

In default/all mode, ftl check runs syntax validation first. If syntax errors are found, the remaining checks are skipped until the Fluent files are fixed, and the command still returns a normal check report. The process exit code is controlled by fail-on.

The stale check treats a message referenced by another .ftl message as used, even when Python code does not call it directly.

Breaking change: ftl untranslated has been removed. Use ftl check --check untranslated instead.

Config examples for each check

Run every available check. This is also the default when checks is omitted:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
code-path = "app/bot"
languages = ["uk", "pl"]
checks = ["all"]
suggest-from = ["en"]
fail-on = ["error"]
report-path = "reports/ftl-check"
report-format = "json"

Check only untranslated placeholders. This check does not need code-path:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
languages = ["uk", "pl"]
checks = ["untranslated"]
suggest-from = ["en"]
fail-on = ["error"]
report-format = "terminal"

Check only Fluent syntax errors. This check does not need code-path:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
languages = ["uk", "pl"]
checks = ["syntax"]
fail-on = ["error"]
report-format = "terminal"

Check only missing message and term references inside .ftl files. This check does not need code-path:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
languages = ["uk", "pl"]
checks = ["references"]
fail-on = ["error"]
report-format = "terminal"

Check keys used in Python but missing from locale files. This check requires code-path:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
code-path = "app/bot"
languages = ["uk", "pl"]
checks = ["missing"]
suggest-from = ["en"]
fail-on = ["error"]
report-format = "terminal"

Check stale .ftl messages that are not used by Python. This check requires code-path:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
code-path = "app/bot"
languages = ["uk", "pl"]
checks = ["stale"]
fail-on = ["error"]
report-format = "terminal"

Check Python keyword arguments against Fluent variables. This check requires code-path:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
code-path = "app/bot"
languages = ["uk", "pl"]
checks = ["kwargs"]
fail-on = ["error"]
report-format = "terminal"

Run a custom subset:

[tool.ftl-extract.check]
locales-path = "app/bot/locales"
code-path = "app/bot"
languages = ["uk", "pl"]
checks = ["syntax", "references", "missing", "kwargs"]
suggest-from = ["en"]
fail-on = ["error"]
report-path = "reports/ftl-check"
report-format = "json"

🙈 Ignore marker for intentional placeholders

If a key is intentionally the same as its message id (for example, brand or domain terms like balance = balance), add a message comment marker above it:

# ftl-extract: ignore-untranslated
balance = balance

This key will be skipped by ftl check --check untranslated.

FAQ

❓ - How to add more languages to the project ?

# Here we add 3 languages: English, Ukrainian and Polish
$ ftl extract project_path/code_path project_path/locales -l en -l uk -l pl

❓ - How to detect another i18n keys like LazyProxy or L ?

# Here we extract ftl keys from i18n-keys like `LF`, `LazyProxy` and `L`
$ ftl extract project_path/code_path project_path/locales -K LF -K LazyProxy -K L

How I use FTL-Extract in most of my projects

$ ftl extract \
  'app/bot' \
  'app/bot/locales' \
  -l 'en' \
  -l 'uk' \
  -K 'LF' \
  -I 'core' \
  -E './tests/*' \
  --ignore-kwargs 'when' \
  --comment-junks \
  --comment-keys-mode 'comment' \
  --cache \
  --verbose

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ftl_extract-0.12.0a1.tar.gz (68.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ftl_extract-0.12.0a1-py3-none-win_amd64.whl (2.4 MB view details)

Uploaded Python 3Windows x86-64

ftl_extract-0.12.0a1-py3-none-musllinux_1_2_x86_64.whl (2.3 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ftl_extract-0.12.0a1-py3-none-musllinux_1_2_aarch64.whl (2.2 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ftl_extract-0.12.0a1-py3-none-manylinux_2_28_x86_64.whl (2.3 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64

ftl_extract-0.12.0a1-py3-none-manylinux_2_28_aarch64.whl (2.1 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

ftl_extract-0.12.0a1-py3-none-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file ftl_extract-0.12.0a1.tar.gz.

File metadata

  • Download URL: ftl_extract-0.12.0a1.tar.gz
  • Upload date:
  • Size: 68.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ftl_extract-0.12.0a1.tar.gz
Algorithm Hash digest
SHA256 41b88de1457f746e7bea1d5e7b1a6c3781837eec51ae754e38cc84ad00174888
MD5 f9fac04f80db3ffdaeeda8bf9209b45a
BLAKE2b-256 f70e3c6036f2789167e4e9615bc6a83ec4c426276db287dcad515550b84c2e9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1.tar.gz:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftl_extract-0.12.0a1-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for ftl_extract-0.12.0a1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 0c1006c8e2b8c093d354c4efba0a6c4f30488019ab19ef96165871d314a24552
MD5 7a9df61c8bc299a829b1b232edc0dbc4
BLAKE2b-256 45aee58b5ac1b7235a12095c3da1e22bdf3b86af29e2dcb8ee25fea1fb9ab963

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1-py3-none-win_amd64.whl:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftl_extract-0.12.0a1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ftl_extract-0.12.0a1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3520370ed5a4b0641390b9b662f715dc3b557c5b62625f18bfc266ac19ee2845
MD5 414a4a3b07a487419910c539b908ade2
BLAKE2b-256 17a94dd7f732bbc465dcb7b2bc04ffd0c39abf67a582be943e852524869c10f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1-py3-none-musllinux_1_2_x86_64.whl:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftl_extract-0.12.0a1-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ftl_extract-0.12.0a1-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 46d379442e41140d80500aae691936636209f904837939c3e8ae07955160699d
MD5 d5bcb215663b66da83caf929d875d8fa
BLAKE2b-256 bf9051bc5965d134c2b4e59657bdc3e543989ad3b6bdcdeb082215a7fd93aedf

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1-py3-none-musllinux_1_2_aarch64.whl:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftl_extract-0.12.0a1-py3-none-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for ftl_extract-0.12.0a1-py3-none-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 804e1d9b86dc74b88cc558ce58d647dae70101ec658a2c9d49c8eb623a900732
MD5 b4530a1b001e9ee2d7db72d9f536fb5d
BLAKE2b-256 6413592d3ff9de969454c44ebc7da5f41db305458152c85dce3eab6b351cdeb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1-py3-none-manylinux_2_28_x86_64.whl:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftl_extract-0.12.0a1-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for ftl_extract-0.12.0a1-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e6e0034e0bf7fd2417e5b99007de26cbd18b0911cb68924898fb689c4c2ccdd7
MD5 004d4ec9caa3db50d914ad7decb1c0f1
BLAKE2b-256 c6f547aa4739c1bcd2613a9145bf122968340442621611900556eab30b39f0fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1-py3-none-manylinux_2_28_aarch64.whl:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftl_extract-0.12.0a1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ftl_extract-0.12.0a1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9622bc5951b4b79d2626a1a13affc1e036d391bcbc7d31870b28394be87de577
MD5 bf22db8b564477050c032d52f170eec6
BLAKE2b-256 c5626bbd7db4bcc503ccd46dbe4888e8475f34c686e2ddd34b1a6b298cb7e975

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftl_extract-0.12.0a1-py3-none-macosx_11_0_arm64.whl:

Publisher: pypi-release.yml on andrew000/FTL-Extract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page