编辑:您能否仔细阅读我的问题?这个问题是具体的,而不是正如所说的那样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():
答案 0 :(得分:5)
好的,你已经有了语言前缀。因此,您需要为下一部分提供多种翻译。
使用多条路线或转换器的最简单方法:
@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
是有效的网址,但您也可以尝试使用自己的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)