From 8bfd4d789bb724e385dbf6f3e27d67e08308ce46 Mon Sep 17 00:00:00 2001 From: Mandel Olaiya Date: Thu, 9 Apr 2026 00:42:40 +0200 Subject: [PATCH] production refresh --- mandelstudio/migrations/0001_initial.py | 60 +++++ .../0002_seed_localized_footer_content.py | 236 ++++++++++++++++++ .../migrations/0003_locale_audit_models.py | 51 ++++ mandelstudio/migrations/__init__.py | 0 mandelstudio/ocyan.json | 22 +- mandelstudio/settings/base.py | 44 ++++ mandelstudio/sitemaps.py | 81 ++++++ .../engine/pages/base_home_page.html | 4 +- .../engine/pages/base_standard_page.html | 4 +- .../templates/engine/pages/engine_page.html | 4 +- .../templates/engine/partials/header5.html | 1 + .../templates/oxyan/partials/footer.html | 36 +++ .../oxyan/partials/language_chooser.html | 2 +- mandelstudio/templatetags/__init__.py | 0 .../templatetags/localized_navigation.py | 120 +++++++++ .../templatetags/mandelstudio_footer.py | 26 ++ .../templatetags/mandelstudio_i18n.py | 23 ++ mandelstudio/urls.py | 23 +- setup.py | 2 +- templates/oxyan/partials/footer.html | 36 +++ 20 files changed, 758 insertions(+), 17 deletions(-) create mode 100644 mandelstudio/migrations/0001_initial.py create mode 100644 mandelstudio/migrations/0002_seed_localized_footer_content.py create mode 100644 mandelstudio/migrations/0003_locale_audit_models.py create mode 100644 mandelstudio/migrations/__init__.py create mode 100644 mandelstudio/sitemaps.py create mode 100644 mandelstudio/templates/engine/partials/header5.html create mode 100644 mandelstudio/templates/oxyan/partials/footer.html create mode 100644 mandelstudio/templatetags/__init__.py create mode 100644 mandelstudio/templatetags/localized_navigation.py create mode 100644 mandelstudio/templatetags/mandelstudio_footer.py create mode 100644 mandelstudio/templatetags/mandelstudio_i18n.py create mode 100644 templates/oxyan/partials/footer.html diff --git a/mandelstudio/migrations/0001_initial.py b/mandelstudio/migrations/0001_initial.py new file mode 100644 index 0000000..e21f8a7 --- /dev/null +++ b/mandelstudio/migrations/0001_initial.py @@ -0,0 +1,60 @@ +# Generated by Django 5.2.11 on 2026-03-25 16:37 + +import django.db.models.deletion +import uuid +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("wagtailcore", "0097_alter_page_locale_alter_page_translation_key"), + ] + + operations = [ + migrations.CreateModel( + name="LocalizedFooterContent", + fields=[ + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("title", models.CharField(default="Footer content", max_length=120)), + ("translation_key", models.UUIDField(default=uuid.uuid4, editable=False)), + ( + "footer", + wagtail.fields.StreamField( + [("about_us", 2), ("text", 2), ("page_list", 4), ("SubscriptionBlock", 7)], + block_lookup={ + 0: ("wagtail.blocks.CharBlock", (), {"help_text": "Heading of the content block.", "label": "Heading", "required": False}), + 1: ("wagtail.blocks.RichTextBlock", (), {}), + 2: ("wagtail.blocks.StructBlock", [[("heading", 0), ("content", 1)]], {}), + 3: ("wagtail.blocks.PageChooserBlock", (), {"help_text": "List pages below this page", "label": "Page"}), + 4: ("wagtail.blocks.StructBlock", [[("heading", 0), ("page", 3)]], {}), + 5: ("wagtail.blocks.CharBlock", (), {"label": "Title", "required": False}), + 6: ("wagtail.blocks.TextBlock", (), {"label": "Description", "required": False}), + 7: ("wagtail.blocks.StructBlock", [[("title", 5), ("description", 6)]], {}), + }, + default=list, + ), + ), + ( + "mini_footer", + wagtail.fields.StreamField( + [("text", 0)], + block_lookup={0: ("wagtail.blocks.RichTextBlock", (), {})}, + default=list, + ), + ), + ("locale", models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name="+", to="wagtailcore.locale")), + ("site", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name="localized_footer_contents", to="wagtailcore.site")), + ], + options={ + "verbose_name": "Localized footer content", + "verbose_name_plural": "Localized footer contents", + "abstract": False, + "constraints": [models.UniqueConstraint(fields=("site", "locale"), name="unique_localized_footer_per_site_locale")], + "unique_together": {("translation_key", "locale")}, + }, + ), + ] diff --git a/mandelstudio/migrations/0002_seed_localized_footer_content.py b/mandelstudio/migrations/0002_seed_localized_footer_content.py new file mode 100644 index 0000000..9d91bab --- /dev/null +++ b/mandelstudio/migrations/0002_seed_localized_footer_content.py @@ -0,0 +1,236 @@ +from __future__ import annotations + +import uuid + +from django.db import migrations + + +CONTENT = { + "nl": { + "about": "

Wij bouwen snelle websites en webshops die je team zelf kan beheren. Van eerste lancering tot doorontwikkeling: helder, schaalbaar en zonder ruis.

", + "links_heading": "Snelle links", + "support_heading": "Help & support", + "link_labels": { + "about": "Over ons", + "services": "Diensten", + "projects": "Projecten", + "contact": "Contact", + "capabilities": "Mogelijkheden", + "ai_search": "AI Search", + "book_call": "Plan een gesprek", + }, + "mini": "

Contact - Diensten - Projecten - Copyright 2026 - MandelBlog Studio

", + }, + "en": { + "about": "

We build fast websites and webshops your team can manage without friction. From launch to growth, the setup stays clear, scalable, and easy to extend.

", + "links_heading": "Quick links", + "support_heading": "Help & support", + "link_labels": { + "about": "About us", + "services": "Services", + "projects": "Projects", + "contact": "Contact", + "capabilities": "Capabilities", + "ai_search": "AI Search", + "book_call": "Book a call", + }, + "mini": "

Contact - Services - Projects - Copyright 2026 - MandelBlog Studio

", + }, + "de": { + "about": "

Wir entwickeln schnelle Websites und Webshops, die Ihr Team selbst pflegen kann. Von der ersten Veröffentlichung bis zur Weiterentwicklung bleibt alles klar, skalierbar und wartbar.

", + "links_heading": "Schnellzugriff", + "support_heading": "Hilfe & Support", + "link_labels": { + "about": "Über uns", + "services": "Dienstleistungen", + "projects": "Projekte", + "contact": "Kontakt", + "capabilities": "Möglichkeiten", + "ai_search": "KI-Suche", + "book_call": "Gespräch planen", + }, + "mini": "

Kontakt - Dienstleistungen - Projekte - Copyright 2026 - MandelBlog Studio

", + }, + "fr": { + "about": "

Nous créons des sites web et des boutiques en ligne rapides que votre équipe peut gérer facilement. Du lancement à la croissance, tout reste clair, évolutif et simple à maintenir.

", + "links_heading": "Accès rapide", + "support_heading": "Aide & support", + "link_labels": { + "about": "À propos", + "services": "Services", + "projects": "Projets", + "contact": "Contact", + "capabilities": "Possibilités", + "ai_search": "Recherche IA", + "book_call": "Planifier un échange", + }, + "mini": "

Contact - Services - Projets - Copyright 2026 - MandelBlog Studio

", + }, + "es": { + "about": "

Construimos sitios web y tiendas online rápidas que tu equipo puede gestionar sin complicaciones. Desde el lanzamiento hasta el crecimiento, todo se mantiene claro, escalable y fácil de ampliar.

", + "links_heading": "Accesos rápidos", + "support_heading": "Ayuda y soporte", + "link_labels": { + "about": "Sobre nosotros", + "services": "Servicios", + "projects": "Proyectos", + "contact": "Contacto", + "capabilities": "Posibilidades", + "ai_search": "Búsqueda con IA", + "book_call": "Planificar una llamada", + }, + "mini": "

Contacto - Servicios - Proyectos - Copyright 2026 - MandelBlog Studio

", + }, + "it": { + "about": "

Realizziamo siti web e negozi online veloci che il tuo team può gestire in autonomia. Dal lancio alla crescita, tutto rimane chiaro, scalabile e semplice da estendere.

", + "links_heading": "Link rapidi", + "support_heading": "Aiuto e supporto", + "link_labels": { + "about": "Chi siamo", + "services": "Servizi", + "projects": "Progetti", + "contact": "Contatto", + "capabilities": "Possibilità", + "ai_search": "Ricerca AI", + "book_call": "Prenota una call", + }, + "mini": "

Contatto - Servizi - Progetti - Copyright 2026 - MandelBlog Studio

", + }, + "pt": { + "about": "

Criamos sites e lojas online rápidos que a sua equipa consegue gerir com autonomia. Do lançamento ao crescimento, tudo permanece claro, escalável e simples de evoluir.

", + "links_heading": "Acesso rápido", + "support_heading": "Ajuda e suporte", + "link_labels": { + "about": "Sobre nós", + "services": "Serviços", + "projects": "Projetos", + "contact": "Contacto", + "capabilities": "Possibilidades", + "ai_search": "Pesquisa IA", + "book_call": "Marcar conversa", + }, + "mini": "

Contacto - Serviços - Projetos - Copyright 2026 - MandelBlog Studio

", + }, + "ru": { + "about": "

Мы создаём быстрые сайты и интернет-магазины, которыми ваша команда может управлять самостоятельно. От запуска до развития всё остаётся понятным, масштабируемым и удобным для роста.

", + "links_heading": "Быстрые ссылки", + "support_heading": "Помощь и поддержка", + "link_labels": { + "about": "О нас", + "services": "Услуги", + "projects": "Проекты", + "contact": "Контакт", + "capabilities": "Возможности", + "ai_search": "AI Search", + "book_call": "Запланировать звонок", + }, + "mini": "

Контакт - Услуги - Проекты - Copyright 2026 - MandelBlog Studio

", + }, +} + +SOURCE_SLUGS = { + "about": "over-ons", + "services": "diensten", + "projects": "projecten", + "contact": "contact", + "capabilities": "mogelijkheden", + "ai_search": "ai-search", +} + + +def build_urls(Page, code): + source_pages = { + key: Page.objects.filter(locale__language_code="nl", slug=slug).first() + for key, slug in SOURCE_SLUGS.items() + } + urls = {} + for key, page in source_pages.items(): + if not page: + urls[key] = "/" + continue + translated = Page.objects.filter( + translation_key=page.translation_key, locale__language_code=code + ).first() + chosen = translated or page + urls[key] = getattr(chosen, "url", None) or "/" + return urls + + +def make_footer_raw(code, urls): + content = CONTENT[code] + labels = content["link_labels"] + links_html = ( + f'

{labels["about"]}
' + f'{labels["services"]}
' + f'{labels["projects"]}
' + f'{labels["contact"]}

' + ) + support_html = ( + f'

{labels["capabilities"]}
' + f'{labels["ai_search"]}
' + f'{labels["book_call"]}
' + f'info@mandelblog.com

' + ) + return [ + { + "type": "about_us", + "id": str(uuid.uuid4()), + "value": {"heading": "MandelBlog Studio", "content": content["about"]}, + }, + { + "type": "text", + "id": str(uuid.uuid4()), + "value": {"heading": content["links_heading"], "content": links_html}, + }, + { + "type": "text", + "id": str(uuid.uuid4()), + "value": {"heading": content["support_heading"], "content": support_html}, + }, + ] + + +def make_mini_raw(code, urls): + return [ + { + "type": "text", + "id": str(uuid.uuid4()), + "value": CONTENT[code]["mini"].format(**urls), + } + ] + + +def seed_footer_content(apps, schema_editor): + LocalizedFooterContent = apps.get_model("mandelstudio", "LocalizedFooterContent") + Site = apps.get_model("wagtailcore", "Site") + Locale = apps.get_model("wagtailcore", "Locale") + site = Site.objects.order_by("id").first() + if site is None: + return + + from wagtail.models import Page + + translation_key = uuid.uuid4() + for code in CONTENT.keys(): + locale, _ = Locale.objects.get_or_create(language_code=code) + urls = build_urls(Page, code) + LocalizedFooterContent.objects.update_or_create( + site=site, + locale=locale, + defaults={ + "title": f"Footer content ({code})", + "translation_key": translation_key, + "footer": make_footer_raw(code, urls), + "mini_footer": make_mini_raw(code, urls), + }, + ) + + +def reverse_seed(apps, schema_editor): + LocalizedFooterContent = apps.get_model("mandelstudio", "LocalizedFooterContent") + LocalizedFooterContent.objects.all().delete() + + +class Migration(migrations.Migration): + dependencies = [("mandelstudio", "0001_initial")] + operations = [migrations.RunPython(seed_footer_content, reverse_seed)] diff --git a/mandelstudio/migrations/0003_locale_audit_models.py b/mandelstudio/migrations/0003_locale_audit_models.py new file mode 100644 index 0000000..fdde4bc --- /dev/null +++ b/mandelstudio/migrations/0003_locale_audit_models.py @@ -0,0 +1,51 @@ +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [("mandelstudio", "0002_seed_localized_footer_content")] + + operations = [ + migrations.CreateModel( + name="LocaleAuditRun", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("started_at", models.DateTimeField(auto_now_add=True)), + ("finished_at", models.DateTimeField(blank=True, null=True)), + ("locale_codes", models.JSONField(blank=True, default=list)), + ("fix_enabled", models.BooleanField(default=False)), + ("total_urls_checked", models.PositiveIntegerField(default=0)), + ("issues_found", models.PositiveIntegerField(default=0)), + ("pages_with_issues", models.PositiveIntegerField(default=0)), + ("summary", models.JSONField(blank=True, default=dict)), + ], + options={"ordering": ["-started_at"]}, + ), + migrations.CreateModel( + name="LocaleAuditIssue", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("locale_code", models.CharField(max_length=12)), + ("object_id", models.PositiveIntegerField(blank=True, null=True)), + ("object_type", models.CharField(blank=True, max_length=128)), + ("url", models.TextField(blank=True)), + ("title", models.CharField(blank=True, max_length=255)), + ("severity", models.CharField(max_length=16)), + ("issue_type", models.CharField(max_length=64)), + ("field_path", models.CharField(blank=True, max_length=512)), + ("bad_value", models.TextField(blank=True)), + ("replacement", models.TextField(blank=True)), + ("fixed", models.BooleanField(default=False)), + ("extra", models.JSONField(blank=True, default=dict)), + ( + "run", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="issues", + to="mandelstudio.localeauditrun", + ), + ), + ], + options={"ordering": ["locale_code", "url", "field_path"]}, + ), + ] diff --git a/mandelstudio/migrations/__init__.py b/mandelstudio/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mandelstudio/ocyan.json b/mandelstudio/ocyan.json index e078fac..758efde 100644 --- a/mandelstudio/ocyan.json +++ b/mandelstudio/ocyan.json @@ -2,7 +2,6 @@ "ocyan_plugins": [ "ocyan.plugin.contact_form", "ocyan.plugin.cookie_jar", - "ocyan.plugin.demo_data", "ocyan.plugin.django", "ocyan.plugin.newsletter", "ocyan.plugin.oscar", @@ -15,7 +14,7 @@ "ocyan.plugin.oscar_partner", "ocyan.plugin.oscar_shipping", "ocyan.plugin.oscar_sequential_order_numbers", - "ocyan.plugin.payment_dummy", + "ocyan.plugin.payment_mollie", "ocyan.plugin.roadrunner_bs5", "ocyan.plugin.template_engine", "ocyan.plugin.roadrunner_productchooser", @@ -64,8 +63,23 @@ "en" ] }, - "ocyan_dummy_payment_plugin": { - "help_text": "Hit pay, to simulate payment." + "payment_mollie": { + "api_key": "CHANGE_ME", + "ideal": true, + "creditcard": true, + "paypal": true, + "bancontact": true, + "sofort": true, + "banktransfer": false, + "belfius": false, + "bitcoin": false, + "directdebit": false, + "eps": false, + "giftcard": false, + "giropay": false, + "inghomepay": false, + "kbc": false, + "mistercash": false }, "oscar": { "allow_anon_checkout": true, diff --git a/mandelstudio/settings/base.py b/mandelstudio/settings/base.py index 534c268..a5548f6 100644 --- a/mandelstudio/settings/base.py +++ b/mandelstudio/settings/base.py @@ -8,6 +8,7 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ +import importlib.util import sys from pathlib import Path @@ -26,6 +27,49 @@ INSTALLED_APPS = [ "mandelstudio", ] + INSTALLED_APPS +# Route through the project URL layer so MandelStudio can override +# sitemap/robots behavior while still delegating the main Ocyan routes. +ROOT_URLCONF = "mandelstudio.urls" + + +def _ensure_required_app(*candidates): + """Ensure required plugin apps remain enabled when /etc/ocyan config omits them.""" + if any(app in INSTALLED_APPS for app in candidates): + return + for app in candidates: + if importlib.util.find_spec(app): + INSTALLED_APPS.append(app) + return + + +_ensure_required_app( + "ocyan.plugin.carbasa.carbasa", + "ocyan.plugin.carbasa", +) +_ensure_required_app( + "ocyan.plugin.coyote.coyote", + "ocyan.plugin.coyote", +) + +# Keep Carbasa/Coyote defaults stable even when plugin settings are not +# injected early enough during startup on this deployment. +OXYAN_HEADER_OPTIONS = globals().get( + "OXYAN_HEADER_OPTIONS", + [ + ("basic", "Basic Header"), + ("big", "Big Header"), + ("mega", "Mega Header"), + ], +) +COMPRESS_CACHE_KEY_FUNCTION = globals().get( + "COMPRESS_CACHE_KEY_FUNCTION", + "ocyan.plugin.coyote.utils.get_compressor_cache_key", +) +OXYAN_LAZY_THEME_DEFINITIONS = globals().get( + "OXYAN_LAZY_THEME_DEFINITIONS", + "ocyan.plugin.coyote.definitions.get_coyote_definitions", +) + # Enable request language negotiation. if "django.middleware.locale.LocaleMiddleware" not in MIDDLEWARE: if "django.contrib.sessions.middleware.SessionMiddleware" in MIDDLEWARE: diff --git a/mandelstudio/sitemaps.py b/mandelstudio/sitemaps.py new file mode 100644 index 0000000..794380e --- /dev/null +++ b/mandelstudio/sitemaps.py @@ -0,0 +1,81 @@ +from django.contrib.sitemaps.views import index as sitemap_index_view +from django.contrib.sitemaps.views import sitemap as sitemap_section_view +from django.http import HttpResponse +from wagtail.models import Locale, Page + +from ocyan.plugin.wagtail_oscar_integration.constants import CACHE_DURATION +from ocyan.plugin.wagtail_oscar_integration.sitemap import CategorySitemap +from ocyan.plugin.wagtail_oscar_integration.sitemap import ProductSitemap +from ocyan.plugin.wagtail_oscar_integration.sitemap import ShopSitemap +from ocyan.plugin.wagtail_oscar_integration.sitemap import WagtailSitemap as BaseWagtailSitemap + + +class WagtailSitemap(BaseWagtailSitemap): + def items(self): + page_ids = [] + + for locale in Locale.objects.all(): + translated_root_page = self.get_wagtail_site().root_page.get_translation_or_none( + locale + ) + if translated_root_page is None: + continue + + locale_page_ids = ( + translated_root_page.get_descendants(inclusive=True) + .live() + .public() + .order_by() + .values_list("pk", flat=True) + ) + page_ids.extend(locale_page_ids) + + if not page_ids: + return [] + + return ( + Page.objects.filter(pk__in=page_ids) + .live() + .public() + .defer_streamfields() + .order_by("path") + .specific() + ) + + +def gather_sitemaps(): + return { + "pages": WagtailSitemap, + "shop": ShopSitemap, + "products": ProductSitemap, + "categories": CategorySitemap, + } + + +def sitemap_index(request): + return sitemap_index_view( + request, + sitemaps=gather_sitemaps(), + sitemap_url_name="sitemaps", + ) + + +def sitemap_section(request, section=None): + return sitemap_section_view( + request, + sitemaps=gather_sitemaps(), + section=section, + ) + + +def robots_txt(request): + sitemap_url = request.build_absolute_uri("/sitemap.xml") + content = "\n".join( + [ + "User-agent: *", + "Allow: /", + f"Sitemap: {sitemap_url}", + "", + ] + ) + return HttpResponse(content, content_type="text/plain; charset=utf-8") diff --git a/mandelstudio/templates/engine/pages/base_home_page.html b/mandelstudio/templates/engine/pages/base_home_page.html index e016157..67d9ab1 100644 --- a/mandelstudio/templates/engine/pages/base_home_page.html +++ b/mandelstudio/templates/engine/pages/base_home_page.html @@ -1,5 +1,5 @@ {% extends "layout.html" %} -{% load wagtailcore_tags oxyan static string_filters %} +{% load wagtailcore_tags oxyan static string_filters mandelstudio_i18n %} {% block extrahead %} {{ block.super }} @@ -19,7 +19,7 @@ {% block layout %} - Ga naar inhoud + {% skip_to_content_text %} {% include_header header_template|default:"engine/partials/header.html" %}
diff --git a/mandelstudio/templates/engine/pages/base_standard_page.html b/mandelstudio/templates/engine/pages/base_standard_page.html index 4cf66eb..39d64d8 100644 --- a/mandelstudio/templates/engine/pages/base_standard_page.html +++ b/mandelstudio/templates/engine/pages/base_standard_page.html @@ -1,5 +1,5 @@ {% extends "layout.html" %} -{% load wagtailcore_tags oxyan static string_filters %} +{% load wagtailcore_tags oxyan static string_filters mandelstudio_i18n %} {% block extrahead %} {{ block.super }} @@ -19,7 +19,7 @@ {% block layout %} - Ga naar inhoud + {% skip_to_content_text %} {% include_header header_template|default:"engine/partials/header.html" %}
diff --git a/mandelstudio/templates/engine/pages/engine_page.html b/mandelstudio/templates/engine/pages/engine_page.html index e016157..67d9ab1 100644 --- a/mandelstudio/templates/engine/pages/engine_page.html +++ b/mandelstudio/templates/engine/pages/engine_page.html @@ -1,5 +1,5 @@ {% extends "layout.html" %} -{% load wagtailcore_tags oxyan static string_filters %} +{% load wagtailcore_tags oxyan static string_filters mandelstudio_i18n %} {% block extrahead %} {{ block.super }} @@ -19,7 +19,7 @@ {% block layout %} - Ga naar inhoud + {% skip_to_content_text %} {% include_header header_template|default:"engine/partials/header.html" %}
diff --git a/mandelstudio/templates/engine/partials/header5.html b/mandelstudio/templates/engine/partials/header5.html new file mode 100644 index 0000000..3bd86eb --- /dev/null +++ b/mandelstudio/templates/engine/partials/header5.html @@ -0,0 +1 @@ +{% include "carbasa/headers/header.html" %} diff --git a/mandelstudio/templates/oxyan/partials/footer.html b/mandelstudio/templates/oxyan/partials/footer.html new file mode 100644 index 0000000..a834a66 --- /dev/null +++ b/mandelstudio/templates/oxyan/partials/footer.html @@ -0,0 +1,36 @@ +{% load staticfiles %} +{% load wagtailcore_tags wagtailimages_tags wagtailsettings_tags cache mandelstudio_footer %} +{% get_settings %} +{% localized_footer_content as localized_footer %} + +{% cache 300 footer_menu LANGUAGE_CODE request.site %} +
+
+
+ {% with footer=localized_footer.footer|default:settings.ocyan_plugin_wagtail.OcyanSettings.footer %} + {% for block in footer %} + + {% endfor %} + {% endwith %} +
+
+
+ + +{% endcache %} diff --git a/mandelstudio/templates/oxyan/partials/language_chooser.html b/mandelstudio/templates/oxyan/partials/language_chooser.html index dba673e..79f1a10 100644 --- a/mandelstudio/templates/oxyan/partials/language_chooser.html +++ b/mandelstudio/templates/oxyan/partials/language_chooser.html @@ -8,7 +8,7 @@