如何在金字塔中的URL中添加语言代码?

拉斯皮

我刚刚创建了基本的金字塔“ hello world”模板项目,并添加了i18n支持。我正在使用.pt带有gettext的Python 3.5和Chameleon模板()。

我目前可以通过.ini文件更改语言

现在,我想使其动态化并从URL中读取语言代码。因此,URL更改/<language code>/page/{possible params}为例如/fi/home我不想添加{language}到现有的路线/视图中,从而隐藏了语言代码参数,并且除了在模板/视图中创建指向其他页面的链接之外,视图对此一无所知。

编辑:这是我尝试使用Mikko Ohtamaa提到的补间

已添加到__init__.py

config.add_tween('myapp.tweens.LocalizerTween')

tweens.py

import logging

from pyramid.registry import Registry
from pyramid.request import Request

log = logging.getLogger(__name__)


class LocalizerTween(object):
  """
  Set translator based on URL
  """
  def __init__(self, handler, registry: Registry):
    self.handler = handler
    self.registry = registry

  def __call__(self, request: Request):
    if request.path.count("/") > 1 and len(request.path) > 3:
      request.locale_name = request.path[1:].split("/", 1)[0]
    else:
      # Redirect to default language
      from pyramid.settings import aslist
      import pyramid.httpexceptions as exc
      raise exc.HTTPFound("/" + aslist(request.registry.settings['pyramid.default_locale_name'])[0] + "/")

    newpath = request.path[1:]
    newpath = newpath[newpath.find("/"):]
    log.debug("new path: %s", newpath)

    request.path = newpath

    response = self.handler(request)
    return response

重定向到默认语言会产生异常:

pyramid.httpexceptions.HTTPFound: The resource was found at

尝试设置新路径会给出:

AttributeError: can't set attribute

如果我注释掉request.path = newpath,去/fi//en/我得到了正确的语言,404页。

米克米·奥塔玛(Mikko Ohtamaa)

这是一个示例解决方案,严格限于语言感知路径的范围(无本地化绑定等):

"""Self-contained language aware path routing example for Pyramid."""

from urllib.parse import urlunparse
from urllib.parse import urlparse
from wsgiref.simple_server import make_server

from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound
from pyramid.request import Request
from pyramid.response import Response


def redirect_to_default_language(request: Request):
    """A view that redirects path language-free URLs to the default language URLs.

    E.g. /greeter/foobar -> /en/greeter/foobar
    """

    default_language = request.registry.settings["default_language"]

    parts = urlparse(request.url)
    new_path = "/{}{}".format(default_language, parts.path)
    new_parts = [parts[0], parts[1], new_path, parts[3], parts[4], parts[5]]
    language_redirected_url = urlunparse(new_parts)
    return HTTPFound(language_redirected_url)


def add_localized_route(config, name, pattern, factory=None, pregenerator=None, **kw):
    """Create path language aware routing paths.

    Each route will have /{lang}/ prefix added to them.

    Optionally, if default language is set, we'll create redirect from an URL without language path component to the URL with the language path component.
    """
    orig_factory = factory

    def wrapper_factory(request):
        lang = request.matchdict['lang']
        # determine if this is a supported lang and convert it to a locale,
        # likely defaulting to your default language if the requested one is
        # not supported by your app
        request.path_lang = lang

        if orig_factory:
            return orig_factory(request)

    orig_pregenerator = pregenerator

    def wrapper_pregenerator(request, elements, kw):
        if 'lang' not in kw:
            # not quite right but figure out how to convert request._LOCALE_ back into a language url
            kw['lang'] = request.path_lang
        if orig_pregenerator:
            return orig_pregenerator(elements, kw)
        return elements, kw

    if pattern.startswith('/'):
        new_pattern = pattern[1:]
    else:
        new_pattern = pattern

    new_pattern = '/{lang}/' + new_pattern

    # Language-aware URL routed
    config.add_route(name, new_pattern, factory=wrapper_factory, pregenerator=wrapper_pregenerator, **kw)

    # Add redirect to the default language routes
    if config.registry.settings.get("default_language"):
        # TODO: This works only for the most simplest routes
        fallback_route_name = name + "_language_redirect_fallback"
        config.add_route(fallback_route_name, pattern)
        config.add_view(redirect_to_default_language, route_name=fallback_route_name)


def home(request):
    """Example of language aware parameterless routing."""

    if request.path_lang == "fi":
        msg = 'Hyvää päivää!'
    else:
        msg = 'Hello sir'

    # This will use current language
    # and automatically populate /{lang}/ matchdict
    # as in wrapper_pregenerator()
    another_url = request.route_url("greeter", name="mikko")

    text = """{}

    Also see {}
    """.format(msg, another_url)

    return Response(text)


def greeter(request):
    """Example of language aware matchdict routing."""
    name = request.matchdict["name"]
    if request.path_lang == "fi":
        return Response('Mitä kuuluu {}?'.format(name))
    else:
        return Response('How are you {}?'.format(name))


if __name__ == '__main__':
    config = Configurator()

    # Map all /lang/ free URLs to this language
    config.registry.settings["default_language"] = "en"

    # Set up config.add_localized_route
    config.add_directive('add_localized_route', add_localized_route)

    # Parameterless routing
    # This will create
    # -  /
    # - /fi/
    # - /en/
    # patterns
    config.add_localized_route('home', '/')
    config.add_view(home, route_name='home')

    # Match dict routing
    # This will create
    # - /greet/mikko
    # - /en/greet/mikko
    # - /fi/greet/mikko
    # patterns
    config.add_localized_route('greeter', '/greet/{name}')
    config.add_view(greeter, route_name='greeter')

    # Run the web server
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章