Internationalization preparation
Creating own repo for locales
This commit is contained in:
parent
d2792b8aa3
commit
307ea4e9ee
13 changed files with 97 additions and 10 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "locale"]
|
||||||
|
path = locale
|
||||||
|
url = git@kumig.it:kumisystems/journeyjoker-locale.git
|
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
apt install libpq-dev build-essential libpython3-dev postgis python3-pip python3-venv libgdal-dev wkhtmltopdf -y
|
apt install libpq-dev build-essential libpython3-dev postgis python3-pip python3-venv libgdal-dev wkhtmltopdf gettext -y
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
pip install -Ur requirements.txt
|
pip install -Ur requirements.txt
|
||||||
|
./manage.py
|
||||||
|
./manage.py compilemessages -i venv
|
23
frontend/fields.py
Normal file
23
frontend/fields.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from .validators import LanguageValidator
|
||||||
|
|
||||||
|
class LanguageField(models.CharField):
|
||||||
|
default_validators = [LanguageValidator()]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs.setdefault("max_length", 16)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def pre_save(self, model_instance, add):
|
||||||
|
value = getattr(model_instance, self.attname, None)
|
||||||
|
if value:
|
||||||
|
value = value.lower()
|
||||||
|
if "_" in value:
|
||||||
|
lang, country = value.split("_")
|
||||||
|
value = "_".join([lang, country.upper()])
|
||||||
|
setattr(model_instance, self.attname, value)
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
return super().pre_save(model_instance, add)
|
|
@ -5,6 +5,8 @@ from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from localauth.models import ImageMixin
|
from localauth.models import ImageMixin
|
||||||
|
|
||||||
|
from .fields import LanguageField
|
||||||
|
|
||||||
from django_countries.fields import CountryField
|
from django_countries.fields import CountryField
|
||||||
|
|
||||||
class ClassProperty(property):
|
class ClassProperty(property):
|
||||||
|
@ -19,7 +21,7 @@ class Testimonial(models.Model):
|
||||||
MaxValueValidator(5),
|
MaxValueValidator(5),
|
||||||
MinValueValidator(1)
|
MinValueValidator(1)
|
||||||
])
|
])
|
||||||
language = models.CharField(max_length=12, choices=settings.LANGUAGES)
|
language = LanguageField()
|
||||||
public = models.BooleanField(default=False)
|
public = models.BooleanField(default=False)
|
||||||
|
|
||||||
class InspirationRegion(models.Model):
|
class InspirationRegion(models.Model):
|
||||||
|
|
7
frontend/templatetags/startswith.py
Normal file
7
frontend/templatetags/startswith.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def startswith(text, string):
|
||||||
|
return text.startswith(string)
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
|
||||||
from .views import HomeView, DemoTemplateView, ImpressumView, PrivacyNoticeView, TOSView, InspirationsView
|
from .views import HomeView, DemoTemplateView, ImpressumView, PrivacyNoticeView, TOSView, InspirationsView, LanguageChoiceView
|
||||||
|
|
||||||
app_name = "frontend"
|
app_name = "frontend"
|
||||||
|
|
||||||
|
@ -12,4 +12,5 @@ urlpatterns = [
|
||||||
path('privacy/', PrivacyNoticeView.as_view(), name="privacy"),
|
path('privacy/', PrivacyNoticeView.as_view(), name="privacy"),
|
||||||
path('tos/', TOSView.as_view(), name="tos"),
|
path('tos/', TOSView.as_view(), name="tos"),
|
||||||
path('inspirations/', InspirationsView.as_view(), name="inspirations"),
|
path('inspirations/', InspirationsView.as_view(), name="inspirations"),
|
||||||
|
path('api/setlang/<slug:code>/', LanguageChoiceView.as_view(), name="languagechoice"),
|
||||||
]
|
]
|
10
frontend/validators.py
Normal file
10
frontend/validators.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
class LanguageValidator:
|
||||||
|
def __call__(self, value):
|
||||||
|
for language, _ in settings.LANGUAGES:
|
||||||
|
if language.startswith(value):
|
||||||
|
return
|
||||||
|
raise ValidationError(_("This is not a valid language code supported by this project."), code='invalid', params={'value': value})
|
|
@ -1,4 +1,7 @@
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView, View
|
||||||
|
from django.conf import settings
|
||||||
|
from django.http.response import HttpResponse
|
||||||
|
from django.contrib import messages
|
||||||
|
|
||||||
class HomeView(TemplateView):
|
class HomeView(TemplateView):
|
||||||
template_name = "frontend/index.html"
|
template_name = "frontend/index.html"
|
||||||
|
@ -20,3 +23,14 @@ class TOSView(TemplateView):
|
||||||
|
|
||||||
class InspirationsView(TemplateView):
|
class InspirationsView(TemplateView):
|
||||||
template_name = "frontend/inspirations.html"
|
template_name = "frontend/inspirations.html"
|
||||||
|
|
||||||
|
class LanguageChoiceView(View):
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
response = HttpResponse()
|
||||||
|
for language, _ in settings.LANGUAGES:
|
||||||
|
if language.startswith(kwargs["code"]):
|
||||||
|
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
request.user.language = language
|
||||||
|
request.user.save()
|
||||||
|
return response
|
|
@ -10,6 +10,8 @@ from polymorphic.models import PolymorphicModel
|
||||||
|
|
||||||
from .helpers import profile_to_coords, upload_path
|
from .helpers import profile_to_coords, upload_path
|
||||||
|
|
||||||
|
from frontend.fields import LanguageField
|
||||||
|
|
||||||
class UserManager(BaseUserManager):
|
class UserManager(BaseUserManager):
|
||||||
use_in_migrations = True
|
use_in_migrations = True
|
||||||
|
|
||||||
|
@ -42,6 +44,7 @@ class User(AbstractBaseUser):
|
||||||
date_joined = models.DateTimeField(default=timezone.now)
|
date_joined = models.DateTimeField(default=timezone.now)
|
||||||
last_login = models.DateTimeField(null=True)
|
last_login = models.DateTimeField(null=True)
|
||||||
is_superuser = models.BooleanField(default=False)
|
is_superuser = models.BooleanField(default=False)
|
||||||
|
language = LanguageField(max_length=16, default="de")
|
||||||
|
|
||||||
objects = UserManager()
|
objects = UserManager()
|
||||||
|
|
||||||
|
|
1
locale
Submodule
1
locale
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 9ec43f57ecfd9f4064873527f5df6e371ee429f3
|
|
@ -1 +1,9 @@
|
||||||
var language="DE";
|
(function($) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
$("#language").change(function() {
|
||||||
|
$.get("/api/setlang/" + $(this).val() + "/").done(function() { document.location.reload(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
|
@ -1,6 +1,7 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load dbsetting %}
|
{% load dbsetting %}
|
||||||
|
{% load startswith %}
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -116,9 +117,10 @@
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<div class="form-group language">
|
<div class="form-group language">
|
||||||
<span><i class="fa fa-angle-down"></i></span>
|
<span><i class="fa fa-angle-down"></i></span>
|
||||||
<select class="form-control">
|
<select name="language" id="language" class="form-control">
|
||||||
<option>{% if request.LANGUAGE_CODE == "de" %}DE{% else %}EN{% endif %}</option>
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
<option>{% if request.LANGUAGE_CODE == "de" %}EN{% else %}DE{% endif %}</option>
|
<option value="de" {% if LANGUAGE_CODE|lower|startswith:"de" %}selected{% endif %}>DE</option>
|
||||||
|
<option value="en" {% if LANGUAGE_CODE|lower|startswith:"en" %}selected{% endif %}>EN</option>
|
||||||
</select>
|
</select>
|
||||||
</div><!-- end form-group -->
|
</div><!-- end form-group -->
|
||||||
</li>
|
</li>
|
||||||
|
@ -358,6 +360,7 @@
|
||||||
<script src="{% static "frontend/js/custom-owl.js" %}"></script>
|
<script src="{% static "frontend/js/custom-owl.js" %}"></script>
|
||||||
<script src="{% static "frontend/js/custom-date-picker.js" %}"></script>
|
<script src="{% static "frontend/js/custom-date-picker.js" %}"></script>
|
||||||
<script src="{% static "frontend/js/custom-video.js" %}"></script>
|
<script src="{% static "frontend/js/custom-video.js" %}"></script>
|
||||||
|
<script src="{% static "frontend/js/language.js" %}"></script>
|
||||||
|
|
||||||
{% block "scripts" %}
|
{% block "scripts" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -34,6 +34,7 @@ INSTALLED_APPS = [
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
@ -111,6 +112,15 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
LOCALE_PATHS = [
|
||||||
|
BASE_DIR / "locale",
|
||||||
|
]
|
||||||
|
|
||||||
|
LANGUAGES = [
|
||||||
|
('de', 'German'),
|
||||||
|
('en', 'English')
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||||
|
|
Loading…
Reference in a new issue