python - How to add language code to URL in Pyramid? -
i've created basic pyramid "hello world" template project , added i18n support. i'm using python 3.5 , chameleon templates (.pt
) gettext.
i can change language through .ini
file.
now make dynamic , read language code url. urls changed /<language code>/page/{possible params}
example /fi/home
. don't want add {language}
existing routes/views language code parameter hidden , views don't know except when creating links other pages in templates/views.
edit: here's attempt using tweens mentioned mikko ohtamaa:
added __init__.py
:
config.add_tween('myapp.tweens.localizertween')
tweens.py
:
import logging pyramid.registry import registry 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 , len(request.path) > 3: request.locale_name = request.path[1:].split("/", 1)[0] else: # redirect default language pyramid.settings import aslist import pyramid.httpexceptions 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
redirect default language gives exception:
pyramid.httpexceptions.httpfound: resource found @
trying set new path gives:
attributeerror: can't set attribute
if comment out request.path = newpath
, go /fi/
, /en/
404 page in correct language.
here example solution, strictly limited scope of language aware paths (no localization bindings, etc):
"""self-contained language aware path routing example pyramid.""" urllib.parse import urlunparse urllib.parse import urlparse wsgiref.simple_server import make_server pyramid.config import configurator pyramid.httpexceptions import httpfound pyramid.request import request pyramid.response import response def redirect_to_default_language(request: request): """a view redirects path language-free urls 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 have /{lang}/ prefix added them. optionally, if default language set, we'll create redirect url without language path component url language path component. """ orig_factory = factory def wrapper_factory(request): lang = request.matchdict['lang'] # determine if supported lang , convert locale, # defaulting default language if requested 1 # not supported 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 figure out how convert request._locale_ 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 default language routes if config.registry.settings.get("default_language"): # todo: works 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' # use current language # , automatically populate /{lang}/ matchdict # in wrapper_pregenerator() another_url = request.route_url("greeter", name="mikko") text = """{} 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 {}?'.format(name)) if __name__ == '__main__': config = configurator() # map /lang/ free urls language config.registry.settings["default_language"] = "en" # set config.add_localized_route config.add_directive('add_localized_route', add_localized_route) # parameterless routing # create # - / # - /fi/ # - /en/ # patterns config.add_localized_route('home', '/') config.add_view(home, route_name='home') # match dict routing # 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 web server app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever()
Comments
Post a Comment