python - 使用 URL 处理器正确格式化规范的 URL 结构

标签 python internationalization flask culture

编辑:您能更仔细地阅读我的问题吗?这个问题是具体的而不是duplicated如前所述。显然我读了这个question发布前。


此演示代码来自 docs ,lang 参数之后的片段将是静态的。因此,在英语 /en/about 中,例如在葡萄牙语中 /pt/about。嗯,正确的应该是 /pt/sobre

关于使用 URL 处理器实现这一点的正确方法有什么想法吗?

from flask import Flask, g

app = Flask(__name__)

@app.url_defaults
def add_language_code(endpoint, values):
    if 'lang_code' in values or not g.lang_code:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

@app.route('/<lang_code>/')
def index():
    ...

@app.route('/<lang_code>/about')
def about():

最佳答案

好的,您已经有了语言前缀。所以你需要为下一部分准备几个翻译。

使用多个路由或转换器的最简单方法:

@app.route('/<lang_code>/about')
@app.route('/<lang_code>/sobre')
def about():
    pass

@app.route('/<lang_code>/<any(about,sobre):about>')
def about(about):
    pass

但很难支持和添加新语言。

第二种方式是改变路由方法翻译特殊词或添加特殊翻译处理器转换器,最后更有趣和含蓄:

from werkzeug.routing import AnyConverter


languages = ['en', 'pt']


def translate_url(word, language):
    if language == 'pt' and word == 'about':
        return 'sobre'
    return word


class TranslateConverter(AnyConverter):

    def __init__(self, map, item):
        AnyConverter.__init__(self, map, *[translate_url(item, language) 
                                           for language in languages])


app.url_map.converters['tr'] = TranslateConverter


@app.route('/<lang_code>/<tr(about):about>')
def about(about):
    pass

但是这个例子有下一个问题:

/en/about
/en/sorbe
/pt/about
/pt/sorbe

是有效的 url,但您也可以尝试使用自己的 Rule 类 (Flask.url_rule_class),在 match 方法中您可以处理这个案例:

from werkzeug.routing import AnyConverter, Rule


class TranslateConverter(AnyConverter):

    def __init__(self, map, item):
        self.language_pairs = {language: translate_url(item, language)
                               for language in languages}
        AnyConverter.__init__(self, map, *tuple(self.language_pairs.values()))


class TranslateCorrelationRule(Rule):

    def match(self, path):
        result = Rule.match(self, path)
        if result is None:
            return result
        lang_code = result.get('lang_code')
        if lang_code is None:
            return result
        for name, value in self._converters.items():
            if not isinstance(value, TranslateConverter):
                continue
            if value.language_pairs[lang_code] != result[name]:
                return
        return result


app.url_map.converters['tr'] = TranslateConverter
app.url_rule_class = TranslateCorrelationRule

如果您要简化此示例的 url_for 用法,您可以使用下一个示例:

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    if not values:
        return
    g.lang_code = values.pop('lang_code', None)
    for key, value in values.items():
        if key.startswith('_'):
            values.pop(key)


class TranslateCorrelationRule(Rule):

    def _update_translate_values(self, values):
        lang_code = values.get('lang_code', getattr(g, 'lang_code', None))
        if lang_code is None:
            return values
        values = values.copy()
        for argument in self.arguments:
            if argument in values:
                continue
            converter = self._converters[argument]
            if not isinstance(converter, TranslateConverter):
                continue
            values[argument] = converter.language_pairs[lang_code]
        return values

    def suitable_for(self, values, method=None):
        return Rule.suitable_for(self, self._update_translate_values(values),
                                 method)

    def build(self, values, append_unknown=True):
        return Rule.build(self, self._update_translate_values(values),
                          append_unknown)

关于python - 使用 URL 处理器正确格式化规范的 URL 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23929076/

相关文章:

Python Curl 到 Elastic Search 问题

python - 遇到 "NameError"问题

ruby-on-rails - 如何识别未使用的 i18n key ?

python - Flask:连接到 sqlite

python - 将 alembic 与多个数据库一起使用

python - 使用 Waitress、Flask 和 Python 将请求记录到文件

python - 计算一年中的周数(处理一年中的第一周)

python - ValueError : Initializer for variable cudnn_gru/opaque_kernel/is from inside a control-flow construct, 例如循环或条件

jquery - 设置和获取日期选择器日期的可靠的跨浏览器方法

javascript - RTL 语言 : comma-separated lists