Skip to content

Instantly share code, notes, and snippets.

@miohtama
Forked from mmerickel/localized_routes.py
Last active November 5, 2016 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miohtama/b93fd1ab11353f86e2da2b484d761358 to your computer and use it in GitHub Desktop.
Save miohtama/b93fd1ab11353f86e2da2b484d761358 to your computer and use it in GitHub Desktop.
localized routes in pyramid
"""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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment