language switcher works
This commit is contained in:
parent
c3ff2408a6
commit
f4ca9a8835
|
@ -31,6 +31,10 @@ DEBUG = True
|
|||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
# Allow inclusion of stuff from these origins
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
"https://static.cscherr.de",
|
||||
]
|
||||
|
||||
# Application definition
|
||||
|
||||
|
@ -54,6 +58,7 @@ MIDDLEWARE = [
|
|||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'start.middleware.LangBasedOnUrlMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'gawa.urls'
|
||||
|
@ -115,7 +120,14 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
# Internationalization
|
||||
# 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
|
||||
prefix_default_language = False
|
||||
|
||||
|
|
|
@ -14,14 +14,14 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.conf.urls import url
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path("", include("start.urls")),
|
||||
path("blog/", include("blog.urls")),
|
||||
path('admin/', admin.site.urls),
|
||||
url(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
]
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
path("", include("start.urls")),
|
||||
path("blog/", include("blog.urls")),
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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()),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -1,3 +1,16 @@
|
|||
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()
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
{% load i18n %}
|
||||
{% load helper_tags %}
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{% block languagecode %}{% endblock languagecode %}">
|
||||
<head>
|
||||
<title>{% block title %}{% endblock title %}</title>
|
||||
<meta charset="utf-8">
|
||||
<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-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<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">
|
||||
{% translate "cscherr.de" noop %}
|
||||
</a>
|
||||
|
@ -21,36 +22,55 @@
|
|||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<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 class="nav-item">
|
||||
<a class="nav-link" href="{% url 'BlogIndex' %}">{% translate "Blog" %}</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Dropdown
|
||||
Debug
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#">Action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Another action</a></li>
|
||||
<li><a class="dropdown-item" href="http://localhost:8082" target="_blank">DB</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><a class="dropdown-item" href="#">Something else here</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
{% 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 }}
|
||||
<button class="btn btn-outline-success" type="submit">Search</button>
|
||||
<button class="btn btn-outline-dark bg-success" type="submit">Search</button>
|
||||
</form>
|
||||
{% endblock MainSearchFormSpace %}
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
{% block main %}{% endblock 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="row gy-5">
|
||||
<div class="col-6">
|
||||
|
@ -61,7 +81,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class="bg-secondary-subtle">
|
||||
<section class="">
|
||||
<div class="container overflow-hidden text-center">
|
||||
<div class="row gy-5">
|
||||
<div class="col-6">
|
||||
|
@ -121,12 +141,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</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
|
||||
<br>
|
||||
<a class="text-reset fw-bold" href="https://www.cscherr.de/">cscherr.de</a>
|
||||
</div>
|
||||
</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>
|
||||
</html>
|
||||
|
|
|
@ -4,18 +4,48 @@
|
|||
{% block languagecode %}{{ LANGUAGE_CODE }}{% endblock languagecode %}
|
||||
{% block title %}{% translate "cscherr.de" %} - {% translate "startpage" %}{% endblock title %}
|
||||
{% block main %}
|
||||
<div class="container-xxl px-4">
|
||||
<div class="container-xl">
|
||||
<div class="jumbotron text-center">
|
||||
<h1>My First Bootstrap Page</h1>
|
||||
<p>Resize this responsive page to see the effect!</p>
|
||||
<h1>{% translate "cscherr.de" %}</h1>
|
||||
<p>Untertitel</p>
|
||||
</div>
|
||||
<article>
|
||||
<div class="row text-center gy-5">
|
||||
<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 class="col">
|
||||
<h4>
|
||||
{% translate "Wer bin ich?" %}
|
||||
<small class="text-body-secondary">{% translate "Privat" %}</small>
|
||||
</h4>
|
||||
{% lorem 1 b %}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
{% endblock main %}
|
||||
|
|
|
@ -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
|
||||
|
|
@ -2,8 +2,11 @@ from django.urls import path
|
|||
|
||||
from . import views
|
||||
|
||||
app_name: str = "start"
|
||||
urlpatterns = [
|
||||
path("", views.IndexView.as_view(), name="StartIndex"),
|
||||
path("search/", views.MainSearchView.as_view(), name="StartMainSearch"),
|
||||
path("legal/", views.LegalInfoView.as_view(), name="StartLegalInfo"),
|
||||
path("", views.IndexView.as_view(), name="index"),
|
||||
path("search/", views.MainSearchView.as_view(), name="search"),
|
||||
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'),
|
||||
]
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
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.http import Http404, HttpResponse, HttpResponseBadRequest, response
|
||||
from django.urls import Resolver404
|
||||
|
@ -8,6 +11,7 @@ from django.template import Template, context, loader
|
|||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
from .forms import MainSearchForm
|
||||
from .models import MainSearchEntry
|
||||
|
||||
class IndexView(TemplateView):
|
||||
"""
|
||||
|
@ -24,11 +28,11 @@ class IndexView(TemplateView):
|
|||
context["MainSearchForm"] = MainSearchForm()
|
||||
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"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
@ -36,20 +40,52 @@ class LegalInfoView(TemplateView):
|
|||
context["MainSearchForm"] = MainSearchForm()
|
||||
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.
|
||||
"""
|
||||
|
||||
model = MainSearchEntry
|
||||
object_list = [] # this is only declaration, the view breaks without it.
|
||||
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):
|
||||
form = MainSearchForm(request.GET)
|
||||
if not form.is_valid():
|
||||
return render(request, "errors/bad_request.html")
|
||||
|
||||
context = {
|
||||
"searchstr": form.cleaned_data['search'],
|
||||
"MainSearchForm": MainSearchForm()
|
||||
}
|
||||
context = self.get_context_data(**kwargs)
|
||||
context["searchstr"] = form.cleaned_data['search']
|
||||
#object_list = self.model.objects.filter("something")
|
||||
return render(request=request, template_name=self.template_name, context=context)
|
||||
|
|
Loading…
Reference in New Issue