2016-11-05 94 views
1

我剛剛創建了基本金字塔「hello world」模板項目並添加了i18n支持。我用gettext使用Python 3.5和Chameleon模板(.pt)。如何將語言代碼添加到金字塔中的URL?

我目前可以通過.ini文件更改語言。

現在我想使它動態並從URL中讀取語言代碼。因此,網址更改爲/<language code>/page/{possible params},例如/fi/home。我不想將{language}添加到現有路由/視圖中,以便隱藏語言代碼參數,除非在模板/視圖中創建指向其他頁面的鏈接,否則視圖不知道任何內容。

編輯:下面是一個使用tweens我試圖通過米克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頁。

回答

0

下面是一個例子溶液,嚴格地限於的語言感知路徑(沒有定位綁定,等等)的範圍:

"""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()