返回介绍

命令行增强

发布于 2025-01-02 21:53:55 字数 3935 浏览 0 评论 0 收藏 0

你可能会同意我的看法,pybabel 命令有点长,难以记忆。 我将利用这个机会向你展示如何创建与 flask 命令集成的自定义命令。 到目前为止,你已经看到我使用 Flask-Migrate 扩展提供的 flask runflask shell 和几个 flask db 子命令。 将应用特定的命令添加到 flask 实际上也很容易。 所以我现在要做的就是创建一些简单的命令,并用这个应用特有的参数触发 pybabel 命令。 我要添加的命令是:

  • flask translate init LANG 用于添加新语言
  • flask translate update 用于更新所有语言存储库
  • flask translate compile 用于编译所有语言存储库

babel export 步骤不会设置为一个命令,因为生成 messages.pot 文件始终是运行 initupdate 命令的先决条件,因此这些命令的执行将会生成翻译模板文件作为临时文件。

Flask 依赖 Click 进行所有命令行操作。 像 translate 这样的命令是几个子命令的根,它们是通过 app.cli.group() 装饰器创建的。 我将把这些命令放在一个名为 app/cli.py 的新模块中:

app/cli.py :翻译命令组

from app import app

@app.cli.group()
def translate():
    """Translation and localization commands."""
    pass

该命令的名称来自被装饰函数的名称,并且帮助消息来自文档字符串。 由于这是一个父命令,它的存在只为子命令提供基础,函数本身不需要执行任何操作。

updatecompile 很容易实现,因为它们没有任何参数:

app/cli.py :更新子命令和编译子命令:

import os

# ...

@translate.command()
def update():
    """Update all languages."""
    if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'):
        raise RuntimeError('extract command failed')
    if os.system('pybabel update -i messages.pot -d app/translations'):
        raise RuntimeError('update command failed')
    os.remove('messages.pot')

@translate.command()
def compile():
    """Compile all languages."""
    if os.system('pybabel compile -d app/translations'):
        raise RuntimeError('compile command failed')

请注意,这些函数的装饰器是如何从 translate 父函数派生的。 这似乎令人困惑,因为 translate() 是一个函数,但它是 Click 构建命令组的标准方式。 与 translate() 函数相同,这些函数的文档字符串在 --help 输出中用作帮助消息。

你可以看到,对于所有命令,运行它们并确保返回值为零(这意味着命令没有返回任何错误)。 如果命令错误,那么我会引发一个 RuntimeError ,这会导致脚本停止。 update() 函数在同一个命令中结合了 extractupdate 步骤,如果一切都成功的话,它会在更新完成后删除 messages.pot 文件,因为当再次需要这个文件时,可以很容易地重新生成 。

init 命令将新的语言代码作为参数。 这是其执行流程:

app/cli.py :Init 子命令。

import click

@translate.command()
@click.argument('lang')
def init(lang):
    """Initialize a new language."""
    if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'):
        raise RuntimeError('extract command failed')
    if os.system(
            'pybabel init -i messages.pot -d app/translations -l ' + lang):
        raise RuntimeError('init command failed')
    os.remove('messages.pot')

该命令使用 @click.argument 装饰器来定义语言代码。 Click 将命令中提供的值作为参数传递给处理函数,然后将该参数并入到 init 命令中。

启用这些命令的最后一步是导入它们,以便注册命令。 我决定在顶级目录的 microblog.py 文件中执行此操作:

microblog.py :注册命令。

from app import cli

这里我唯一需要做的就是导入新的 cli.py 模块,不需要做任何事情,因为导入操作会导致命令装饰器运行并注册命令。

此时,运行 flask --help 将列出 translate 命令作为选项。 flask translate --help 将显示我定义的三个子命令:

(venv) $ flask translate --help
Usage: flask translate [OPTIONS] COMMAND [ARGS]...

  Translation and localization commands.

Options:
  --help  Show this message and exit.

Commands:
  compile  Compile all languages.
  init     Initialize a new language.
  update   Update all languages.

所以现在工作流程就简便多了,而且不需要记住长而复杂的命令。 要添加新的语言,请使用:

(venv) $ flask translate init <language-code>

在更改 _()_l() 语言标记后更新所有语言:

(venv) $ flask translate update

在更新翻译文件后编译所有语言:

(venv) $ flask translate compile

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文