diff --git a/Dockerfile b/Dockerfile index cd6fff0..9cf16da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,4 +7,4 @@ COPY config/ /var/www/html/user/config/ COPY pages/ /var/www/html/user/pages/ # Fix permissions -RUN chown -R www-data:www-data /var/www/html/user/ \ No newline at end of file +RUN chown -R www-data:www-data /var/www/html/user/ diff --git a/blueprints/station.yaml b/blueprints/station.yaml index 78af6e3..fee1556 100644 --- a/blueprints/station.yaml +++ b/blueprints/station.yaml @@ -1,7 +1,3 @@ -# Station Blueprint -# Defines a content module/station for the media guide -# /user/blueprints/station.yaml - title: Station '@extends': type: default @@ -14,7 +10,6 @@ form: active: 1 fields: - # Station Info Tab station_info: type: tab title: Station Info @@ -22,10 +17,8 @@ form: header.station_id: type: text label: Station ID - help: Unique identifier for this station (used in QR codes) validate: required: true - pattern: '^[a-z0-9-]+$' header.station_type: type: select @@ -37,11 +30,6 @@ form: navigation: Navigation default: exhibit - header.exhibition_ref: - type: text - label: Exhibition Reference - help: Reference to parent exhibition - header.active: type: toggle label: Active @@ -55,127 +43,3 @@ form: type: number label: Display Order default: 0 - - # Multilingual Content Tab - content_tab: - type: tab - title: Content - fields: - header.title: - type: multilang - label: Title - languages: true - - header.description: - type: multilang - label: Short Description - type: textarea - languages: true - - # Components Tab - components_tab: - type: tab - title: Components - fields: - header.components: - type: list - label: Content Components - style: vertical - btnLabel: Add Component - collapsed: true - - fields: - .type: - type: select - label: Component Type - options: - heading: Heading - text: Text Block - video: Video Player - audio: Audio Player - tabs: Tabbed Content - slideshow: Slideshow - - .id: - type: text - label: Component ID - help: Unique ID for this component - - # Heading specific - .level: - type: select - label: Heading Level - options: - h1: H1 - h2: H2 - h3: H3 - - # Text/Heading content (multilingual) - .content: - type: editor - label: Content - - # Video specific - .video_src: - type: filepicker - label: Video File - folder: 'user://media/videos' - accept: - - video/* - - .video_poster: - type: filepicker - label: Video Poster - folder: 'user://media/images' - accept: - - image/* - - # Audio specific - .audio_src: - type: filepicker - label: Audio File - folder: 'user://media/audio' - accept: - - audio/* - - .caption: - type: text - label: Caption - - # Tabs specific - .tabs: - type: list - label: Tabs - fields: - .title: - type: text - label: Tab Title - .content: - type: editor - label: Tab Content - - # Slideshow specific - .slides: - type: list - label: Slides - fields: - .image: - type: filepicker - label: Slide Image - folder: 'user://media/images' - accept: - - image/* - .caption: - type: text - label: Slide Caption - - # Media Tab - media_tab: - type: tab - title: Media Files - fields: - header.media_folder: - type: text - label: Media Folder - help: Folder containing media files for this station - placeholder: /media/station-id diff --git a/config/site.yaml b/config/site.yaml index 6b4f5e2..4bc9aea 100644 --- a/config/site.yaml +++ b/config/site.yaml @@ -1,6 +1,3 @@ -# Grav Site Configuration -# /user/config/site.yaml - title: EU Media Guide CMS default_lang: en @@ -10,18 +7,3 @@ author: metadata: description: Multilingual Media Guide Content Management System - -taxonomies: - - category - - tag - - exhibition - - station_type - -# Custom fields for the media guide -mediaguide: - exhibitions: [] - station_types: - - intro - - exhibit - - information - - navigation diff --git a/config/system.yaml b/config/system.yaml index c69a858..4121c9b 100644 --- a/config/system.yaml +++ b/config/system.yaml @@ -1,73 +1,45 @@ -# Grav System Configuration -# /user/config/system.yaml - languages: supported: - # EU Protocol Order (alphabetical by native name) - - bg # български (Bulgarian) - - es # español (Spanish) - - cs # čeština (Czech) - - da # dansk (Danish) - - de # Deutsch (German) - - et # eesti (Estonian) - - el # ελληνικά (Greek) - - en # English - - fr # français (French) - - ga # Gaeilge (Irish) - - hr # hrvatski (Croatian) - - it # italiano (Italian) - - lv # latviešu (Latvian) - - lt # lietuvių (Lithuanian) - - hu # magyar (Hungarian) - - mt # Malti (Maltese) - - nl # Nederlands (Dutch) - - pl # polski (Polish) - - pt # português (Portuguese) - - ro # română (Romanian) - - sk # slovenčina (Slovak) - - sl # slovenščina (Slovenian) - - fi # suomi (Finnish) - - sv # svenska (Swedish) + - bg + - cs + - da + - de + - el + - en + - es + - et + - fi + - fr + - ga + - hr + - hu + - it + - lt + - lv + - mt + - nl + - pl + - pt + - ro + - sk + - sl + - sv default_lang: en include_default_lang: true translations: true translations_fallback: true - session_store_active: false http_accept_language: true - override_locale: false pages: theme: quark markdown: extra: true - types: - - txt - - xml - - html - - htm - - json - - rss - - atom cache: - enabled: false # Disable during development - check: - method: file - driver: auto - prefix: 'g' - lifetime: 604800 - -debugger: enabled: false - shutdown: - close_connection: true + driver: auto twig: - cache: false # Disable during development + cache: false debug: true auto_reload: true - autoescape: false - -assets: - css_pipeline: false - js_pipeline: false diff --git a/docker-compose.yml b/docker-compose.yml index 025d2ec..63631f4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,4 +16,4 @@ services: volumes: grav_accounts: - grav_data: \ No newline at end of file + grav_data: diff --git a/pages/stations/european-concerns/station.md b/pages/stations/european-concerns/station.md new file mode 100644 index 0000000..b3f2b5d --- /dev/null +++ b/pages/stations/european-concerns/station.md @@ -0,0 +1,100 @@ +--- +title: European Concerns - Posters +station_id: 5a0c1432bcb943c304dae4b7 +station_type: exhibit +active: true +order: 2 + +title_translations: + en: Select a poster to read the message! + fr: Faire défiler et sélectionner une affiche + de: Blättern Sie und wählen Sie ein Poster + nl: Blader en kies een poster + it: Sfoglia e seleziona un manifesto + es: Hojee y seleccione un cartel + pt: Percorra a galeria e seleccione um cartaz + bg: Разгледайте и изберете плакат + cs: Vyberte si plakát z nabídky + da: Bladr og vælg en plakat + el: Ξεφυλλίστε και διαλέξτε μία αφίσα + et: Lehitse ja vali plakat + fi: Selaa ja valitse juliste + ga: Féach tríd na postaeir agus roghnaigh ceann + hr: Izaberite poster za čitanje poruke! + hu: Lapozzon és válasszon ki egy plakátot! + lt: Paslinkite kadrus ir pasirinkite plakatą + lv: Pāršķirstiet sarakstu un izvēlieties plakātu. + mt: Qalleb fil-posters u agħżel wieħed + pl: Przewiń listę i wybierz plakat + ro: Selectaţi o imagine + sk: Listujte a vyberte si plagát + sl: Pobrskajte in izberite poster + sv: Bläddra och välj en affisch + +description_translations: + en: European concerns + fr: Les préoccupations des européens + de: Europäische Themen + nl: Europese kwesties + it: Gli affari europei + es: Preocupaciones europeas + pt: Temas europeus + bg: Европейски въпроси + cs: Evropská problematika + da: Europæiske anliggender + el: Προβληματισμοί των Ευρωπαίων + et: Euroopa mured + fi: Eurooppalaisille tärkeitä asioita + ga: Cúiseanna imní don Eoraip + hr: Europska pitanja + hu: Európai gondok + lt: Europos uždaviniai + lv: Eiropiešiem svarīgi jautājumi + mt: Kwistjonijiet Ewropej + pl: Troski Europejczyków + ro: Aspecte importante pentru Europa + sk: Európske témy + sl: Evropska vprašanja + sv: Viktiga frågor för EU + +components: + - type: heading + id: concerns-heading + level: h1 + content: + en: European concerns + fr: Les préoccupations des européens + de: Europäische Themen + nl: Europese kwesties + it: Gli affari europei + es: Preocupaciones europeas + + - type: text + id: concerns-intro + content: + en:

Select a poster to read the message and learn about the issues that matter to Europeans.

+ fr:

Sélectionnez une affiche pour lire le message et découvrir les sujets qui préoccupent les Européens.

+ de:

Wählen Sie ein Poster aus, um die Botschaft zu lesen und mehr über die Themen zu erfahren, die den Europäern wichtig sind.

+ nl:

Selecteer een poster om het bericht te lezen en meer te weten te komen over de kwesties die belangrijk zijn voor Europeanen.

+ + - type: slideshow + id: posters-slideshow + slides: + - image: /images/posters/poster1.jpg + caption: + en: European concerns poster 1 + fr: Affiche des préoccupations européennes 1 + de: Europäische Themen Poster 1 + - image: /images/posters/poster2.jpg + caption: + en: European concerns poster 2 + fr: Affiche des préoccupations européennes 2 + de: Europäische Themen Poster 2 + - image: /images/posters/poster3.jpg + caption: + en: European concerns poster 3 + fr: Affiche des préoccupations européennes 3 + de: Europäische Themen Poster 3 +--- + +Interactive poster exhibition about European concerns and issues. diff --git a/pages/stations/intro/station.md b/pages/stations/intro/station.md new file mode 100644 index 0000000..41a40e0 --- /dev/null +++ b/pages/stations/intro/station.md @@ -0,0 +1,100 @@ +--- +title: Welcome - Touch to Start +station_id: 5a0034ab86c7c57110ae0a43 +station_type: intro +active: true +order: 1 + +title_translations: + en: Please touch here to start + fr: Veuillez appuyer ici pour démarrer + de: Wiedergabe bitte hier drücken + nl: Druk hier om te beginnen + it: Premete qui per iniziare + es: Pulse aquí para comenzar + pt: Por favor toque aqui para começar + bg: Моля, докоснете тук, за да започнете + cs: Zde stiskněte a spusťte přehrávání + da: Tryk venligst her for at starte + el: Παρακαλούμε πιέστε εδώ για να ξεκινήσετε + et: Alustamiseks vajutage palun siia + fi: Aloita koskettamalla tästä + ga: Leag do mhéar anseo le tosú + hr: Dodirnite ovdje zu početak + hu: A kezdéshez nyomja meg ezt a gombot! + lt: Jei norite pradėti, palieskite čia + lv: Lūdzu, pieskarieties šeit, lai sāktu + mt: Jekk jogħġbok agħfas hawn biex tibda + pl: Dotknij, aby rozpocząć + ro: Pentru a începe vă rugăm să apăsaţi aici + sk: Dotykom na tomto mieste sa spustí prehrávanie + sl: Za začetek pritisnite tukaj + sv: Peka här för att starta + +description_translations: + en: Welcome video introduction to the European Parliament + fr: Vidéo d'introduction au Parlement européen + de: Einführungsvideo zum Europäischen Parlament + nl: Introductievideo Europees Parlement + it: Video introduttivo al Parlamento europeo + es: Vídeo de introducción al Parlamento Europeo + +components: + - type: heading + id: welcome-heading + level: h1 + content: + en: Please touch here to start + fr: Veuillez appuyer ici pour démarrer + de: Wiedergabe bitte hier drücken + nl: Druk hier om te beginnen + it: Premete qui per iniziare + es: Pulse aquí para comenzar + pt: Por favor toque aqui para começar + bg: Моля, докоснете тук, за да започнете + cs: Zde stiskněte a spusťte přehrávání + da: Tryk venligst her for at starte + el: Παρακαλούμε πιέστε εδώ για να ξεκινήσετε + et: Alustamiseks vajutage palun siia + fi: Aloita koskettamalla tästä + ga: Leag do mhéar anseo le tosú + hr: Dodirnite ovdje zu početak + hu: A kezdéshez nyomja meg ezt a gombot! + lt: Jei norite pradėti, palieskite čia + lv: Lūdzu, pieskarieties šeit, lai sāktu + mt: Jekk jogħġbok agħfas hawn biex tibda + pl: Dotknij, aby rozpocząć + ro: Pentru a începe vă rugăm să apăsaţi aici + sk: Dotykom na tomto mieste sa spustí prehrávanie + sl: Za začetek pritisnite tukaj + sv: Peka här för att starta + + - type: video + id: intro-video + src: + en: /videos/cms_7388676871120926234.mp4 + bg: /videos/cms_3046071971567520684.mp4 + cs: /videos/cms_2771914627657443657.mp4 + da: /videos/cms_1785836764716686675.mp4 + de: /videos/cms_6408694982373705979.mp4 + el: /videos/cms_6207215930569761535.mp4 + es: /videos/cms_1390123522791732069.mp4 + et: /videos/cms_7268116320585483033.mp4 + fi: /videos/cms_340857536848363735.mp4 + fr: /videos/cms_766311708362015941.mp4 + ga: /videos/cms_157201896609093943.mp4 + hu: /videos/cms_1664578063593428062.mp4 + it: /videos/cms_8746182921133737875.mp4 + pl: /videos/cms_3435441211807278988.mp4 + pt: /videos/cms_8781957532829411669.mp4 + poster: /images/video-poster.jpg + caption: + en: Welcome to the European Parliament + fr: Bienvenue au Parlement européen + de: Willkommen im Europäischen Parlament + nl: Welkom bij het Europees Parlement + it: Benvenuti al Parlamento europeo + es: Bienvenidos al Parlamento Europeo +--- + +Welcome video content - Introduction to the European Parliament visitor center. diff --git a/plugins/json-export/blueprints.yaml b/plugins/json-export/blueprints.yaml index ab44fdf..e2bc657 100644 --- a/plugins/json-export/blueprints.yaml +++ b/plugins/json-export/blueprints.yaml @@ -4,7 +4,4 @@ description: Exports Grav content to JSON format for the React media guide app icon: file-code author: name: Media Guide Team -homepage: https://github.com/your-org/mediaguide -keywords: json, export, api, multilingual -bugs: https://github.com/your-org/mediaguide/issues license: MIT diff --git a/plugins/json-export/json-export.php b/plugins/json-export/json-export.php index af73251..97a1630 100644 --- a/plugins/json-export/json-export.php +++ b/plugins/json-export/json-export.php @@ -2,15 +2,7 @@ namespace Grav\Plugin; use Grav\Common\Plugin; -use RocketTheme\Toolbox\Event\Event; -use Grav\Common\Page\Page; -use Grav\Common\Grav; -/** - * JSON Export Plugin - * - * Exports content from Grav CMS to JSON format for the React media guide app - */ class JsonExportPlugin extends Plugin { public static function getSubscribedEvents() @@ -22,14 +14,10 @@ class JsonExportPlugin extends Plugin public function onPluginsInitialized() { - // Check if we're in admin context if ($this->isAdmin()) { - $this->enable([ - 'onAdminTaskExecute' => ['onAdminTaskExecute', 0] - ]); + return; } - // Enable API endpoint $this->enable([ 'onPagesInitialized' => ['onPagesInitialized', 0] ]); @@ -38,31 +26,24 @@ class JsonExportPlugin extends Plugin public function onPagesInitialized() { $uri = $this->grav['uri']; - - // API endpoints - if (strpos($uri->path(), '/api/') === 0) { - $this->handleApiRequest($uri); - } - } - - private function handleApiRequest($uri) - { $path = $uri->path(); - $lang = $uri->param('lang') ?? 'en'; + + if (strpos($path, '/api/') !== 0) { + return; + } + + $lang = $_GET['lang'] ?? 'en'; header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); - // GET /api/stations - List all stations if ($path === '/api/stations') { echo json_encode($this->getStationsList($lang), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; } - // GET /api/station/{id} - Get single station - if (preg_match('#^/api/station/([a-z0-9-]+)$#', $path, $matches)) { - $stationId = $matches[1]; - $station = $this->getStation($stationId, $lang); + if (preg_match('#^/api/station/([a-zA-Z0-9-]+)$#', $path, $matches)) { + $station = $this->getStation($matches[1], $lang); if ($station) { echo json_encode($station, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } else { @@ -72,18 +53,10 @@ class JsonExportPlugin extends Plugin exit; } - // GET /api/translations - Get UI translations if ($path === '/api/translations') { echo json_encode($this->getTranslations($lang), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; } - - // GET /api/export - Export all content to JSON files - if ($path === '/api/export') { - $result = $this->exportAllToJson(); - echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); - exit; - } } private function getStationsList($lang) @@ -92,22 +65,21 @@ class JsonExportPlugin extends Plugin $stations = []; foreach ($pages->all() as $page) { - if ($page->template() === 'station' && $page->header()->active) { + if ($page->template() === 'station') { $header = $page->header(); + if (!($header->active ?? true)) continue; + $stations[] = [ 'id' => $header->station_id ?? $page->slug(), 'type' => $header->station_type ?? 'exhibit', - 'title' => $this->getTranslatedField($header->title_translations ?? [], $lang), - 'description' => $this->getTranslatedField($header->description_translations ?? [], $lang), - 'order' => $header->order ?? 0, - 'active' => $header->active ?? true + 'title' => $this->getTranslated($header->title_translations ?? [], $lang), + 'description' => $this->getTranslated($header->description_translations ?? [], $lang), + 'order' => $header->order ?? 0 ]; } } - // Sort by order usort($stations, fn($a, $b) => $a['order'] <=> $b['order']); - return $stations; } @@ -121,15 +93,14 @@ class JsonExportPlugin extends Plugin $id = $header->station_id ?? $page->slug(); if ($id === $stationId) { - return $this->formatStationForLang($page, $lang); + return $this->formatStation($page, $lang); } } } - return null; } - private function formatStationForLang($page, $lang) + private function formatStation($page, $lang) { $header = $page->header(); @@ -137,204 +108,155 @@ class JsonExportPlugin extends Plugin 'id' => $header->station_id ?? $page->slug(), 'type' => $header->station_type ?? 'exhibit', 'language' => $lang, - 'title' => $this->getTranslatedField($header->title_translations ?? [], $lang), - 'description' => $this->getTranslatedField($header->description_translations ?? [], $lang), + 'title' => $this->getTranslated($header->title_translations ?? [], $lang), + 'description' => $this->getTranslated($header->description_translations ?? [], $lang), 'components' => [] ]; - // Process components if (isset($header->components) && is_array($header->components)) { - foreach ($header->components as $component) { - $station['components'][] = $this->formatComponent($component, $lang); + foreach ($header->components as $comp) { + $station['components'][] = $this->formatComponent($comp, $lang); } } return $station; } - private function formatComponent($component, $lang) + private function formatComponent($comp, $lang) { - $formatted = [ - 'id' => $component['id'] ?? uniqid(), - 'type' => $component['type'] ?? 'text' + $out = [ + 'id' => $comp['id'] ?? uniqid(), + 'type' => $comp['type'] ?? 'text' ]; - switch ($component['type']) { + switch ($comp['type']) { case 'heading': - $formatted['level'] = $component['level'] ?? 'h2'; - $formatted['content'] = $this->getTranslatedField($component['content'] ?? [], $lang); + $out['level'] = $comp['level'] ?? 'h2'; + $out['content'] = $this->getTranslated($comp['content'] ?? [], $lang); break; - case 'text': - $formatted['content'] = $this->getTranslatedField($component['content'] ?? [], $lang); + $out['content'] = $this->getTranslated($comp['content'] ?? [], $lang); break; - case 'video': - $formatted['src'] = $this->getTranslatedField($component['src'] ?? [], $lang); - $formatted['poster'] = $component['poster'] ?? null; - $formatted['caption'] = $this->getTranslatedField($component['caption'] ?? [], $lang); + $out['src'] = $this->getTranslated($comp['src'] ?? [], $lang); + $out['poster'] = $comp['poster'] ?? null; + $out['caption'] = $this->getTranslated($comp['caption'] ?? [], $lang); break; - case 'audio': - $formatted['src'] = $this->getTranslatedField($component['src'] ?? [], $lang); - $formatted['caption'] = $this->getTranslatedField($component['caption'] ?? [], $lang); + $out['src'] = $this->getTranslated($comp['src'] ?? [], $lang); + $out['caption'] = $this->getTranslated($comp['caption'] ?? [], $lang); break; - case 'tabs': - $formatted['tabs'] = []; - if (isset($component['tabs']) && is_array($component['tabs'])) { - foreach ($component['tabs'] as $tab) { - $formatted['tabs'][] = [ - 'title' => $this->getTranslatedField($tab['title'] ?? [], $lang), - 'content' => $this->getTranslatedField($tab['content'] ?? [], $lang) - ]; - } + $out['tabs'] = []; + foreach ($comp['tabs'] ?? [] as $tab) { + $out['tabs'][] = [ + 'title' => $this->getTranslated($tab['title'] ?? [], $lang), + 'content' => $this->getTranslated($tab['content'] ?? [], $lang) + ]; } break; - case 'slideshow': - $formatted['slides'] = []; - if (isset($component['slides']) && is_array($component['slides'])) { - foreach ($component['slides'] as $slide) { - $formatted['slides'][] = [ - 'image' => $slide['image'] ?? '', - 'caption' => $this->getTranslatedField($slide['caption'] ?? [], $lang) - ]; - } + $out['slides'] = []; + foreach ($comp['slides'] ?? [] as $slide) { + $out['slides'][] = [ + 'image' => $slide['image'] ?? '', + 'caption' => $this->getTranslated($slide['caption'] ?? [], $lang) + ]; } break; } - return $formatted; + return $out; } - private function getTranslatedField($field, $lang, $fallback = 'en') + private function getTranslated($field, $lang) { - if (is_string($field)) { - return $field; - } - - if (is_array($field)) { - return $field[$lang] ?? $field[$fallback] ?? reset($field) ?: ''; - } - - return ''; + if (is_string($field)) return $field; + return $field[$lang] ?? $field['en'] ?? reset($field) ?: ''; } private function getTranslations($lang) { - // UI translations - these should be stored in config or separate files - $translations = [ + $t = [ 'en' => [ 'appTitle' => 'EU Media Guide', - 'scanQR' => 'Scan QR', + 'scanQR' => 'Scan QR Code', 'selectLanguage' => 'Select Language', 'contentLibrary' => 'Content Library', - 'noContent' => 'Scan a QR code or select content from the menu', - 'errorLoading' => 'Failed to load content. Please try again.', - 'playAudio' => 'Play Audio', - 'pauseAudio' => 'Pause Audio', + 'loading' => 'Loading...', + 'play' => 'Play', + 'pause' => 'Pause', 'next' => 'Next', 'previous' => 'Previous', - 'closeMenu' => 'Close Menu', - 'openMenu' => 'Open Menu', - 'loading' => 'Loading...' + 'menu' => 'Menu', + 'close' => 'Close' ], 'fr' => [ 'appTitle' => 'Guide Média UE', - 'scanQR' => 'Scanner QR', + 'scanQR' => 'Scanner le code QR', 'selectLanguage' => 'Choisir la langue', - 'contentLibrary' => 'Bibliothèque de contenu', - 'noContent' => 'Scannez un code QR ou sélectionnez du contenu dans le menu', - 'errorLoading' => 'Échec du chargement. Veuillez réessayer.', - 'playAudio' => 'Lire l\'audio', - 'pauseAudio' => 'Pause audio', + 'contentLibrary' => 'Bibliothèque', + 'loading' => 'Chargement...', + 'play' => 'Lecture', + 'pause' => 'Pause', 'next' => 'Suivant', 'previous' => 'Précédent', - 'closeMenu' => 'Fermer le menu', - 'openMenu' => 'Ouvrir le menu', - 'loading' => 'Chargement...' + 'menu' => 'Menu', + 'close' => 'Fermer' ], 'de' => [ - 'appTitle' => 'EU Media Guide', - 'scanQR' => 'QR scannen', + 'appTitle' => 'EU Medienführer', + 'scanQR' => 'QR-Code scannen', 'selectLanguage' => 'Sprache wählen', 'contentLibrary' => 'Inhaltsbibliothek', - 'noContent' => 'Scannen Sie einen QR-Code oder wählen Sie Inhalte aus dem Menü', - 'errorLoading' => 'Laden fehlgeschlagen. Bitte versuchen Sie es erneut.', - 'playAudio' => 'Audio abspielen', - 'pauseAudio' => 'Audio pausieren', + 'loading' => 'Laden...', + 'play' => 'Abspielen', + 'pause' => 'Pause', 'next' => 'Weiter', 'previous' => 'Zurück', - 'closeMenu' => 'Menü schließen', - 'openMenu' => 'Menü öffnen', - 'loading' => 'Laden...' + 'menu' => 'Menü', + 'close' => 'Schließen' ], 'nl' => [ - 'appTitle' => 'EU Media Gids', - 'scanQR' => 'QR scannen', + 'appTitle' => 'EU Mediagids', + 'scanQR' => 'QR-code scannen', 'selectLanguage' => 'Taal selecteren', 'contentLibrary' => 'Inhoudsbibliotheek', - 'noContent' => 'Scan een QR-code of selecteer inhoud uit het menu', - 'errorLoading' => 'Laden mislukt. Probeer het opnieuw.', - 'playAudio' => 'Audio afspelen', - 'pauseAudio' => 'Audio pauzeren', + 'loading' => 'Laden...', + 'play' => 'Afspelen', + 'pause' => 'Pauze', 'next' => 'Volgende', 'previous' => 'Vorige', - 'closeMenu' => 'Menu sluiten', - 'openMenu' => 'Menu openen', - 'loading' => 'Laden...' + 'menu' => 'Menu', + 'close' => 'Sluiten' + ], + 'it' => [ + 'appTitle' => 'Guida Media UE', + 'scanQR' => 'Scansiona codice QR', + 'selectLanguage' => 'Seleziona lingua', + 'contentLibrary' => 'Libreria contenuti', + 'loading' => 'Caricamento...', + 'play' => 'Riproduci', + 'pause' => 'Pausa', + 'next' => 'Successivo', + 'previous' => 'Precedente', + 'menu' => 'Menu', + 'close' => 'Chiudi' + ], + 'es' => [ + 'appTitle' => 'Guía de Medios UE', + 'scanQR' => 'Escanear código QR', + 'selectLanguage' => 'Seleccionar idioma', + 'contentLibrary' => 'Biblioteca de contenido', + 'loading' => 'Cargando...', + 'play' => 'Reproducir', + 'pause' => 'Pausa', + 'next' => 'Siguiente', + 'previous' => 'Anterior', + 'menu' => 'Menú', + 'close' => 'Cerrar' ] - // Add more languages as needed - ]; - - return $translations[$lang] ?? $translations['en']; - } - - private function exportAllToJson() - { - $exportPath = $this->grav['locator']->findResource('user://') . '/export/'; - - if (!is_dir($exportPath)) { - mkdir($exportPath, 0755, true); - } - - $languages = $this->grav['config']->get('system.languages.supported', ['en']); - $exported = []; - - foreach ($languages as $lang) { - // Export stations - $stations = $this->getStationsList($lang); - file_put_contents( - $exportPath . "stations.{$lang}.json", - json_encode($stations, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) - ); - - // Export each station content - foreach ($stations as $station) { - $content = $this->getStation($station['id'], $lang); - if ($content) { - file_put_contents( - $exportPath . "{$station['id']}.{$lang}.json", - json_encode($content, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) - ); - } - } - - // Export translations - $translations = $this->getTranslations($lang); - file_put_contents( - $exportPath . "translations.{$lang}.json", - json_encode($translations, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) - ); - - $exported[] = $lang; - } - - return [ - 'success' => true, - 'exported_languages' => $exported, - 'path' => $exportPath ]; + return $t[$lang] ?? $t['en']; } } diff --git a/plugins/json-export/json-export.yaml b/plugins/json-export/json-export.yaml index 67256e1..35ebd30 100644 --- a/plugins/json-export/json-export.yaml +++ b/plugins/json-export/json-export.yaml @@ -4,9 +4,6 @@ description: Exports Grav content to JSON format for the React media guide app icon: file-code author: name: Media Guide Team -homepage: https://github.com/your-org/mediaguide -keywords: json, export, api, multilingual -bugs: https://github.com/your-org/mediaguide/issues license: MIT form: