language switcher works

This commit is contained in:
Christoph J. Scherr 2023-05-30 23:11:27 +02:00
parent c3ff2408a6
commit f4ca9a8835
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
10 changed files with 223 additions and 34 deletions

View File

@ -31,6 +31,10 @@ DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = []
# Allow inclusion of stuff from these origins
CORS_ALLOWED_ORIGINS = [
"https://static.cscherr.de",
]
# Application definition # Application definition
@ -54,6 +58,7 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'start.middleware.LangBasedOnUrlMiddleware',
] ]
ROOT_URLCONF = 'gawa.urls' ROOT_URLCONF = 'gawa.urls'
@ -115,7 +120,14 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/ # https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'de-De' from django.utils.translation import gettext_lazy as _
LANGUAGES = [
("de", _("German")),
("en", _("English")),
]
LANGUAGE_CODE = 'de'
# treat this ^^^ as the default # treat this ^^^ as the default
prefix_default_language = False prefix_default_language = False

View File

@ -14,14 +14,14 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.conf.urls import url
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path
urlpatterns = [ urlpatterns = [
path("", include("start.urls")), url(r'^i18n/', include('django.conf.urls.i18n')),
path("blog/", include("blog.urls")),
path('admin/', admin.site.urls),
] ]
urlpatterns += i18n_patterns( urlpatterns += i18n_patterns(
path("", include("start.urls")), path("", include("start.urls")),
path("blog/", include("blog.urls")), path("blog/", include("blog.urls")),

20
gawa/start/middleware.py Normal file
View File

@ -0,0 +1,20 @@
from django.utils import translation
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
class LangBasedOnUrlMiddleware(MiddlewareMixin):
@staticmethod
def process_request(request):
if hasattr(request, 'session'):
active_session_lang = request.session.get(translation.LANGUAGE_SESSION_KEY)
if active_session_lang == request.LANGUAGE_CODE:
return
if any(request.LANGUAGE_CODE in language for language in settings.LANGUAGES):
translation.activate(request.LANGUAGE_CODE)
request.session[translation.LANGUAGE_SESSION_KEY] = request.LANGUAGE_CODE

View File

@ -0,0 +1,25 @@
# Generated by Django 3.2.19 on 2023-05-30 17:08
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='MainSearchEntry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('subtitle', models.CharField(max_length=50)),
('desc', models.CharField(max_length=250, unique=True)),
('date', models.DateField(blank=True)),
('link', models.URLField()),
],
),
]

View File

@ -1,3 +1,16 @@
from django.db import models from django.db import models
# Create your models here. class MainSearchEntry(models.Model):
"""
This model will be searched for by the searchbox that is in every upper part of the website.
The view making use of it is MainSearchView.
Any model object that I implement as searchable should eventually have an entry here.
"""
title = models.CharField(max_length=50)
subtitle = models.CharField(max_length=50)
desc = models.CharField(max_length=250, unique=True)
# may be empty/blank for some entries
date = models.DateField(blank=True)
# every searchable object should have some url associated with it.
link = models.URLField()

View File

@ -1,17 +1,18 @@
{% load i18n %} {% load i18n %}
{% load helper_tags %}
{% load static %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{% block languagecode %}{% endblock languagecode %}"> <html lang="{% block languagecode %}{% endblock languagecode %}">
<head> <head>
<title>{% block title %}{% endblock title %}</title> <title>{% block title %}{% endblock title %}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-lg bg-body-tertiary"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="{% url 'StartIndex' %}"> <a class="navbar-brand" href="{% url 'start:index' %}">
<img src="https://static.cscherr.de/images/profile/profile-margin.png" alt="Logo" height="30" class="d-inline-block align-text-top"> <img src="https://static.cscherr.de/images/profile/profile-margin.png" alt="Logo" height="30" class="d-inline-block align-text-top">
{% translate "cscherr.de" noop %} {% translate "cscherr.de" noop %}
</a> </a>
@ -21,36 +22,55 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> <ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" aria-current="page" href="{% url 'StartIndex' %}">{% translate "Start" %}</a> <a class="nav-link active" aria-current="page" href="{% url 'start:index' %}">{% translate "Start" %}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'BlogIndex' %}">{% translate "Blog" %}</a> <a class="nav-link" href="{% url 'BlogIndex' %}">{% translate "Blog" %}</a>
</li> </li>
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown Debug
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li> <li><a class="dropdown-item" href="http://localhost:8082" target="_blank">DB</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li> <li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item dropdown">
{% get_available_languages as languages %}
{% get_current_language as LANGUAGE_CODE %}
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
{{ LANGUAGE_CODE }}
</a>
<ul class="dropdown-menu">
{% for lang_code, lang_name in languages %}
<li><a class="dropdown-item"
href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% change_lang lang_code %}?{{ request.GET.urlencode }}">
{{ lang_name }}</a></li>
{% endfor %}
<li><hr class="dropdown-divider"></li> <li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li> <li><a class="dropdown-item" href="#">Something else here</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
{% block MainSearchFormSpace %} {% block MainSearchFormSpace %}
<form class="d-flex" role="search" action="{% url 'StartMainSearch' %}" method="GET"> <form class="d-flex" role="search" action="{% url 'start:search' %}" method="GET">
{{ MainSearchForm }} {{ MainSearchForm }}
<button class="btn btn-outline-success" type="submit">Search</button> <button class="btn btn-outline-dark bg-success" type="submit">Search</button>
</form> </form>
{% endblock MainSearchFormSpace %} {% endblock MainSearchFormSpace %}
</div> </div>
</div> </div>
</nav> </nav>
{% get_available_languages as languages %}
{% for lang_code, lang_name in languages %}
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% change_lang lang_code %}">sus</a>
{% endfor %}
<main> <main>
{% block main %}{% endblock main %} {% block main %}{% endblock main %}
</main> </main>
<footer class="text-center text-lg-start bg-white text-muted"> <footer class="text-center text-lg-start bg-dark text-light">
<div class="container overflow-hidden text-center"> <div class="container overflow-hidden text-center">
<div class="row gy-5"> <div class="row gy-5">
<div class="col-6"> <div class="col-6">
@ -61,7 +81,7 @@
</div> </div>
</div> </div>
</div> </div>
<section class="bg-secondary-subtle"> <section class="">
<div class="container overflow-hidden text-center"> <div class="container overflow-hidden text-center">
<div class="row gy-5"> <div class="row gy-5">
<div class="col-6"> <div class="col-6">
@ -121,12 +141,12 @@
</div> </div>
</div> </div>
</section> </section>
<div class="text-center p-4" style="background-color: rgba(0, 0, 0, 0.025);"> <div class="text-center p-4 bg-black">
© 2023 Christoph J. Scherr © 2023 Christoph J. Scherr
<br> <br>
<a class="text-reset fw-bold" href="https://www.cscherr.de/">cscherr.de</a> <a class="text-reset fw-bold" href="https://www.cscherr.de/">cscherr.de</a>
</div> </div>
</footer> </footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body> </body>
</html> </html>

View File

@ -4,18 +4,48 @@
{% block languagecode %}{{ LANGUAGE_CODE }}{% endblock languagecode %} {% block languagecode %}{{ LANGUAGE_CODE }}{% endblock languagecode %}
{% block title %}{% translate "cscherr.de" %} - {% translate "startpage" %}{% endblock title %} {% block title %}{% translate "cscherr.de" %} - {% translate "startpage" %}{% endblock title %}
{% block main %} {% block main %}
<div class="container-xxl px-4"> <div class="container-xl">
<div class="jumbotron text-center"> <div class="jumbotron text-center">
<h1>My First Bootstrap Page</h1> <h1>{% translate "cscherr.de" %}</h1>
<p>Resize this responsive page to see the effect!</p> <p>Untertitel</p>
</div> </div>
<article>
<div class="row text-center gy-5"> <div class="row text-center gy-5">
<div class="col"> <div class="col">
{% lorem 1 b %} <h4>
{% translate "Wer bin ich?" %}
<small class="text-body-secondary">{% translate "Professionell" %}</small>
</h4>
<p>
{% blocktranslate %}
Ich bin Christoph J. Scherr und studiere dual Informatik mit der Spezialisierung
Cybersecurity an der <a href="https://www.mannheim.dhbw.de/startseite">DHBW Mannheim</a>.
<br>
<br>
Mein dualer Partner ist die <a href="https://www.newtec.de">NewTec GmbH</a>, ein
mittelständisches Unternehmen aus Pfaffenhofen in Bayern. Dort arbeite Ich vorallem an
Safety nahen embedded Systemen.
<br>
<br>
Auch in meiner Freizeit arbeite Ich gerne mit Computern, hobbymäßig bin Ich mein eigener
System Administrator (Diese Seite habe ich z.B. selbst gehostet.).
<br>
<br>
{% endblocktranslate %}
<a class="icon-link icon-link-hover" href="{% url 'start:professional' %}">
{% translate "further information" %}
<svg class="bi" aria-hidden="true"><use xlink:href="#arrow-right"></use></svg>
</a>
</p>
</div> </div>
<div class="col"> <div class="col">
<h4>
{% translate "Wer bin ich?" %}
<small class="text-body-secondary">{% translate "Privat" %}</small>
</h4>
{% lorem 1 b %} {% lorem 1 b %}
</div> </div>
</div> </div>
</article>
</div> </div>
{% endblock main %} {% endblock main %}

View File

@ -0,0 +1,30 @@
from django.template import Library
from django.urls import resolve, reverse
from django.utils.translation import activate, get_language
register = Library()
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
"""
Get active page's url by a specified language
Usage: {% change_lang 'en' %}
shamelessly stolen from stackoverflow:
https://stackoverflow.com/a/41147772
"""
path = context['request'].path
url_parts = resolve(path)
url = path
cur_language = get_language()
try:
activate(lang)
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally:
activate(cur_language)
return "%s" % url

View File

@ -2,8 +2,11 @@ from django.urls import path
from . import views from . import views
app_name: str = "start"
urlpatterns = [ urlpatterns = [
path("", views.IndexView.as_view(), name="StartIndex"), path("", views.IndexView.as_view(), name="index"),
path("search/", views.MainSearchView.as_view(), name="StartMainSearch"), path("search/", views.MainSearchView.as_view(), name="search"),
path("legal/", views.LegalInfoView.as_view(), name="StartLegalInfo"), path("legal/", views.LegalInfoView.as_view(), name="legal_info"),
path("professional/", views.LegalInfoView.as_view(), name="professional"),
path('language/activate/<language_code>/', views.ActivateLanguageView.as_view(), name='activate_language'),
] ]

View File

@ -1,4 +1,7 @@
from http.client import HTTPResponse from http.client import HTTPResponse
from django.shortcuts import redirect
from django.utils import translation
from django.views.generic.base import View
from django.apps import AppConfig from django.apps import AppConfig
from django.http import Http404, HttpResponse, HttpResponseBadRequest, response from django.http import Http404, HttpResponse, HttpResponseBadRequest, response
from django.urls import Resolver404 from django.urls import Resolver404
@ -8,6 +11,7 @@ from django.template import Template, context, loader
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
from .forms import MainSearchForm from .forms import MainSearchForm
from .models import MainSearchEntry
class IndexView(TemplateView): class IndexView(TemplateView):
""" """
@ -24,11 +28,11 @@ class IndexView(TemplateView):
context["MainSearchForm"] = MainSearchForm() context["MainSearchForm"] = MainSearchForm()
return context return context
class LegalInfoView(TemplateView): class ProfessionalView(TemplateView):
""" """
Legal info that the german authorities want. Professional informations that might interest a professional employer
""" """
# TODO
template_name: str = "start/legalinfo.html" template_name: str = "start/legalinfo.html"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -36,20 +40,52 @@ class LegalInfoView(TemplateView):
context["MainSearchForm"] = MainSearchForm() context["MainSearchForm"] = MainSearchForm()
return context return context
class MainSearchView(TemplateView): class LegalInfoView(TemplateView):
"""
Legal info that the german authorities want.
"""
# TODO
template_name: str = "start/legalinfo.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["MainSearchForm"] = MainSearchForm()
return context
class ActivateLanguageView(View):
"""
Set the language to whatever
"""
language_code = ''
redirect_to = ''
def get(self, request, *args, **kwargs):
self.redirect_to = request.META.get('HTTP_REFERER')
self.language_code = kwargs.get('language_code')
translation.activate(self.language_code)
request.session[translation.LANGUAGE_SESSION_KEY] = self.language_code
return redirect(self.redirect_to)
class MainSearchView(ListView):
""" """
Search for anything. Search for anything.
""" """
model = MainSearchEntry
object_list = [] # this is only declaration, the view breaks without it.
template_name: str = "start/search.html" template_name: str = "start/search.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["MainSearchForm"] = MainSearchForm()
return context
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
form = MainSearchForm(request.GET) form = MainSearchForm(request.GET)
if not form.is_valid(): if not form.is_valid():
return render(request, "errors/bad_request.html") return render(request, "errors/bad_request.html")
context = { context = self.get_context_data(**kwargs)
"searchstr": form.cleaned_data['search'], context["searchstr"] = form.cleaned_data['search']
"MainSearchForm": MainSearchForm() #object_list = self.model.objects.filter("something")
}
return render(request=request, template_name=self.template_name, context=context) return render(request=request, template_name=self.template_name, context=context)