fix: add inline language selector to platform template
- Remove dependency on shared language_selector macro - Add platformLanguageSelector() Alpine.js component - Include flag-icons CSS CDN for language flags - Fix 'languageSelector is not defined' error 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
{# app/templates/platform/base.html #}
|
{# app/templates/platform/base.html #}
|
||||||
{# Base template for platform public pages (homepage, about, faq, etc.) #}
|
{# Base template for platform public pages (homepage, about, faq, etc.) #}
|
||||||
{% from 'shared/macros/language_selector.html' import language_selector_compact %}
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ current_language|default('en') }}" x-data="platformLayoutData()" x-bind:class="{ 'dark': dark }">
|
<html lang="{{ current_language|default('en') }}" x-data="platformLayoutData()" x-bind:class="{ 'dark': dark }">
|
||||||
<head>
|
<head>
|
||||||
@@ -45,6 +44,9 @@
|
|||||||
{# Tailwind CSS v4 (built locally via standalone CLI) #}
|
{# Tailwind CSS v4 (built locally via standalone CLI) #}
|
||||||
<link rel="stylesheet" href="{{ url_for('static', path='platform/css/tailwind.output.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', path='platform/css/tailwind.output.css') }}">
|
||||||
|
|
||||||
|
{# Flag icons for language selector #}
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.0.0/css/flag-icons.min.css"/>
|
||||||
|
|
||||||
{% block extra_head %}{% endblock %}
|
{% block extra_head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -90,11 +92,40 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Language selector #}
|
{# Language selector - inline version for platform #}
|
||||||
{{ language_selector_compact(
|
<div x-data="platformLanguageSelector()" class="relative">
|
||||||
current_language=current_language|default('en'),
|
<button
|
||||||
enabled_languages=SUPPORTED_LANGUAGES|default(['en', 'fr', 'de', 'lb'])
|
@click="isOpen = !isOpen"
|
||||||
) }}
|
@click.outside="isOpen = false"
|
||||||
|
type="button"
|
||||||
|
class="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
|
||||||
|
:class="{ 'bg-gray-100 dark:bg-gray-700': isOpen }"
|
||||||
|
>
|
||||||
|
<span class="fi text-lg" :class="'fi-' + flags[currentLang]"></span>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
x-show="isOpen"
|
||||||
|
x-transition
|
||||||
|
class="absolute right-0 z-50 mt-1 w-44 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 py-1"
|
||||||
|
>
|
||||||
|
<template x-for="lang in languages" :key="lang">
|
||||||
|
<button
|
||||||
|
@click="setLanguage(lang)"
|
||||||
|
type="button"
|
||||||
|
class="flex items-center gap-3 w-full px-4 py-2 text-sm font-medium transition-colors"
|
||||||
|
:class="currentLang === lang
|
||||||
|
? 'bg-indigo-50 dark:bg-indigo-900/20 text-indigo-700 dark:text-indigo-300'
|
||||||
|
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'"
|
||||||
|
>
|
||||||
|
<span class="fi" :class="'fi-' + flags[lang]"></span>
|
||||||
|
<span x-text="names[lang]"></span>
|
||||||
|
<svg x-show="currentLang === lang" class="w-4 h-4 ml-auto text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{# Dark mode toggle #}
|
{# Dark mode toggle #}
|
||||||
<button
|
<button
|
||||||
@@ -267,6 +298,47 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Language selector for platform pages
|
||||||
|
function platformLanguageSelector() {
|
||||||
|
return {
|
||||||
|
isOpen: false,
|
||||||
|
currentLang: '{{ current_language|default("en") }}',
|
||||||
|
languages: {{ SUPPORTED_LANGUAGES|default(['en', 'fr', 'de', 'lb'])|tojson }},
|
||||||
|
names: {
|
||||||
|
'en': 'English',
|
||||||
|
'fr': 'Français',
|
||||||
|
'de': 'Deutsch',
|
||||||
|
'lb': 'Lëtzebuergesch'
|
||||||
|
},
|
||||||
|
flags: {
|
||||||
|
'en': 'gb',
|
||||||
|
'fr': 'fr',
|
||||||
|
'de': 'de',
|
||||||
|
'lb': 'lu'
|
||||||
|
},
|
||||||
|
async setLanguage(lang) {
|
||||||
|
if (lang === this.currentLang) {
|
||||||
|
this.isOpen = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/v1/language/set', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ language: lang })
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
this.currentLang = lang;
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set language:', error);
|
||||||
|
}
|
||||||
|
this.isOpen = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% block extra_scripts %}{% endblock %}
|
{% block extra_scripts %}{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user