From 516c35dcb4b7d956316f4972cf9c98d07fbeae93 Mon Sep 17 00:00:00 2001
From: Mario Linz <mario@webmakers.de>
Date: Wed, 25 May 2022 12:10:29 +0200
Subject: [PATCH] =?UTF-8?q?Weitere=20Verbesserungen=20des=20Starter=20Proj?=
 =?UTF-8?q?ekts=20f=C3=BCr=20neue=20Projekte.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 api/collections/content.yml                   |  13 +-
 api/collections/general.yml                   | 435 +++++++++---------
 api/collections/navigation.yml                |   1 +
 src/api.ts                                    |   7 +-
 src/components/App.svelte                     |  34 +-
 src/components/routes/Content.svelte          |  15 +-
 src/components/routes/Home.svelte             |  39 +-
 .../widgets/GeneralMediaImage.svelte          |  20 +
 src/components/widgets/LanguageChooser.svelte |  30 ++
 src/components/widgets/Navigation.svelte      |   9 +-
 src/components/widgets/ScrollTo.svelte        |   8 +-
 src/css/theme-2022/components/general.less    |  43 --
 .../components/language-chooser.less          |  22 +
 src/css/theme-2022/main.less                  |   1 +
 src/css/theme-2022/reset.less                 |   1 +
 src/store.ts                                  |  19 +-
 types/global.d.ts                             |   2 +-
 17 files changed, 398 insertions(+), 301 deletions(-)
 create mode 100644 src/components/widgets/GeneralMediaImage.svelte
 create mode 100644 src/components/widgets/LanguageChooser.svelte
 create mode 100644 src/css/theme-2022/components/language-chooser.less

diff --git a/api/collections/content.yml b/api/collections/content.yml
index 93a9aa7..3c04ea8 100644
--- a/api/collections/content.yml
+++ b/api/collections/content.yml
@@ -24,14 +24,18 @@ meta:
           mediaQuery: "(max-width:599px)"
           primaryText: path
           columns:
-              - name
-              - path
+              - source: path
+                twig: "{{locale}}{{path}}"
+              - source: locale
+                type: flag
         # Desktop
         - type: table
           mediaQuery: "(min-width:600px)"
           columns:
-              - name
-              - path
+              - source: path
+                twig: "{{locale}}{{path}}"
+              - source: locale
+                type: flag
 
 imageFilter:
     xs:
@@ -102,6 +106,7 @@ hooks:
 
 # Feldliste der Kollektion
 fields:
+    - !include fields/_locale.yml
     - name: name
       type: string
       meta:
diff --git a/api/collections/general.yml b/api/collections/general.yml
index 47c8c9f..8373452 100644
--- a/api/collections/general.yml
+++ b/api/collections/general.yml
@@ -34,222 +34,225 @@ meta:
               - lastname
               - companyName
 
-    entryViewFields:
-        tabsSection:
-            meta:
-                expand: meta
-            tabs:
-                - name: general
-                  meta:
-                      label: { de: "Allgemein", en: "General" }
-                  fields:
-                      - name: public
-                        type: boolean
-                        meta:
-                            defaultValue: true
-                            label:
-                                de: Veröffentlicht
-                                en: Public
-                            helperText:
-                                de: "Alle allgemeinen Informationen werden auf der Seite angezeigt."
-                                en: "All general information are displayed on the page."
-                - name: meta
-                  meta:
-                      label: { de: "Meta", en: "Meta" }
-                  fields:
-                      - name: meta
-                        type: object
-                        subFields:
-                            - name: metaTitle
-                              type: string
-                              meta:
-                                  label: { de: "Titel der Webseite", en: "Page Title" }
-                            - name: metaDescription
-                              type: string
-                              meta:
-                                  label: { de: "Beschreibung der Webseite", en: "Page Description" }
-                            - name: metaTagRobots
-                              type: string[]
-                              meta:
-                                  widget: chipArray
-                                  label:
-                                      de: Robots
-                                      en: Robots
-                                  defaultValue: []
-                                  autocomplete: true
-                                  choices:
-                                      - { id: "noindex", name: "noindex" }
-                                      - { id: "index", name: "index" }
-                                      - { id: "follow", name: "follow" }
-                                      - { id: "nofollow", name: "nofollow" }
-                                      - { id: "noimageindex", name: "noimageindex" }
-                                      - { id: "none", name: "none" }
-                                      - { id: "noarchive", name: "noarchive" }
-                                      - { id: "nocache", name: "nocache" }
-                                      - { id: "nosnippet", name: "nosnippet" }
-                                      - { id: "nnavailable_after", name: "nnavailable_after" }
-                                  helperText:
-                                      de: "<strong>Noindex</strong>: Weist eine Suchmaschine an, eine Seite nicht zu indizieren.<br/><strong>index</strong>: Weist eine Suchmaschine an, eine Seite zu indizieren. Beachten Sie, dass Sie dieses Meta-Tag nicht hinzufügen müssen; es ist die Voreinstellung.<br/><strong>follow</strong>: Auch wenn die Seite nicht indexiert ist, sollte der Crawler allen Links auf einer Seite folgen und Eigenkapital an die verlinkten Seiten weitergeben.<br/><strong>nofollow</strong>: Weist einen Crawler an, keinen Links auf einer Seite zu folgen oder Link-Equity weiterzugeben.<br/><strong>noimageindex</strong>: Weist einen Crawler an, keine Bilder auf einer Seite zu indizieren.<br/><strong>none</strong>: Entspricht der gleichzeitigen Verwendung der noindex- und nofollow-Tags.<br/><strong>noarchive</strong>: Suchmaschinen sollten keinen zwischengespeicherten Link zu dieser Seite auf einem SERP anzeigen.<br/><strong>nocache</strong>: Wie noarchive, aber nur von Internet Explorer und Firefox verwendet.<br/><strong>nosnippet</strong>: Weist eine Suchmaschine an, kein Snippet dieser Seite (d. h. Meta-Beschreibung) dieser Seite auf einem SERP anzuzeigen.<br/><strong>nnavailable_after</strong>: Suchmaschinen sollen diese Seite nach einem bestimmten Datum nicht mehr indexieren.<br/>"
-                                      en: "<strong>Noindex</strong>: Tells a search engine not to index a page.<br/><strong>index</strong>: Tells a search engine to index a page. Note that you don’t need to add this meta tag; it’s the default.<br/><strong>follow</strong>: Even if the page isn’t indexed, the crawler should follow all the links on a page and pass equity to the linked pages.<br/><strong>nofollow</strong>: Tells a crawler not to follow any links on a page or pass along any link equity.<br/><strong>noimageindex</strong>: Tells a crawler not to index any images on a page.<br/><strong>none</strong>: Equivalent to using both the noindex and nofollow tags simultaneously.<br/><strong>noarchive</strong>: Search engines should not show a cached link to this page on a SERP.<br/><strong>nocache</strong>: Same as noarchive, but only used by Internet Explorer and Firefox.<br/><strong>nosnippet</strong>: Tells a search engine not to show a snippet of this page (i.e. meta description) of this page on a SERP.<br/><strong>nnavailable_after</strong>: Search engines should no longer index this page after a particular date.<br/>"
-                            - name: metaKeywords
-                              type: string
-                              meta:
-                                  label: { de: "SEO / Schlüsselwörter", en: "SEO / Keywords" }
-                                  helperText:
-                                      de: "Beispiel: Stichwort1, Stichwort2, Stichwort3"
-                                      en: "Example: keyword1, keyword2, keyword3"
-                - name: person
-                  meta:
-                      label: { de: "Person", en: "Person" }
-                  fields:
-                      - name: person
-                        type: object
-                        subFields:
-                            - name: salutation
-                              type: string
-                              meta:
-                                  label: { de: "Anrede", en: "Salutation" }
-                            - name: firstname
-                              type: string
-                              meta:
-                                  label: { de: "Vorname", en: "Firstname" }
-                            - name: lastname
-                              type: string
-                              meta:
-                                  label: { de: "Nachname", en: "Lastname" }
-                            - name: additional
-                              type: string
-                              meta:
-                                  label: { de: "Zusatz", en: "Additional" }
-                            - name: street
-                              type: string
-                              meta:
-                                  label: { de: "Straße", en: "Street" }
-                            - name: postcode
-                              type: string
-                              meta:
-                                  label: { de: "Postleitzahl", en: "Postcode" }
-                            - name: city
-                              type: string
-                              meta:
-                                  label: { de: "Ort", en: "City" }
-                            - name: tel
-                              type: string
-                              meta:
-                                  label: { de: "Telefonnummer", en: "Phone number" }
-                            - name: fax
-                              type: string
-                              meta:
-                                  label: { de: "Faxnummer", en: "Fax number" }
-                            - name: mobile
-                              type: string
-                              meta:
-                                  label: { de: "Handynummer", en: "Mobile number" }
-                            - name: email
-                              type: string
-                              meta:
-                                  label: { de: "E-Mail", en: "E-Mail" }
-                - name: company
-                  meta:
-                      label: { de: "Unternehmen", en: "Company" }
-                  fields:
-                      - name: person
-                        type: object
-                        subFields:
-                            - name: companyName
-                              type: string
-                              meta:
-                                  label: { de: "Name des Unternehmens", en: "Company Name" }
-                            - name: companyWebUrl
-                              type: string
-                              meta:
-                                  label: { de: "URL zur Webseite", en: "Website URL" }
-                            - name: companyAddresses
-                              type: object[]
-                              meta:
-                                  label:
-                                      de: Adresse
-                                      en: Adresse
-                                  css:
-                              subFields:
-                                  - name: street
-                                    type: string
-                                    meta:
-                                        label: { de: "Straße", en: "Street" }
-                                  - name: houseNr
-                                    type: string
-                                    meta:
-                                        label: { de: "Hausnummer", en: "House number" }
-                                  - name: postcode
-                                    type: string
-                                    meta:
-                                        label: { de: "PLZ", en: "ZIP" }
-                                  - name: city
-                                    type: string
-                                    meta:
-                                        label: { de: "Ort", en: "City" }
-                                  - name: tel
-                                    type: string
-                                    meta:
-                                        label: { de: "Telefon", en: "Phone number" }
-                                  - name: fax
-                                    type: string
-                                    meta:
-                                        label: { de: "Fax", en: "Fax" }
-                                  - name: email
-                                    type: string
-                                    meta:
-                                        label: { de: "E-Mail", en: "E-Mail" }
-                - name: media
-                  meta:
-                      label: { de: "Medien", en: "Media" }
-                  fields:
-                      - name: media
-                        type: object
-                        subFields:
-                            - name: favicon
-                              type: file
-                              meta:
-                                  label: { de: "Favicon", en: "Favicon" }
-                                  helperText:
-                                      de: "Ein Favicon ist ein kleines Icon, Symbol oder Logo, das von Webbrowsern verwendet wird, um eine Website auf wiedererkennbare Weise zu kennzeichnen."
-                                      en: "A favicon is a small icon, symbol, or logo used by web browsers to identify a website in a recognizable way."
-                            - name: brand
-                              type: file
-                              meta:
-                                  label: { de: "Logo / Brand", en: "Logo / Brand" }
-                                  helperText:
-                                      de: "Logo der Seite"
-                                      en: "Page Logo"
-                            - name: mediaFiles
-                              type: object[]
-                              meta:
-                                  label: { de: "Dateien", en: "Files" }
-                              subFields:
-                                  - name: title
-                                    type: string
-                                    meta:
-                                        label: { de: "Datei-Titel", en: "File Title" }
-                                  - name: alternateText
-                                    type: string
-                                    meta:
-                                        label: { de: "Alternativer Text", en: "Alternate Text" }
-                                  - name: id
-                                    type: string
-                                    meta:
-                                        label: { de: "Technischer Name / ID", en: "Technical name / ID" }
-                                  - name: file
-                                    type: file
-                                    meta:
-                                        label: { de: "", en: "" }
-                - name: copyright
-                  meta:
-                      label: { de: "Copyright", en: "Copyright" }
-                  fields:
-                      - name: copyrightText
-                        type: string
-                        meta:
-                            label: { de: "Copyright Text", en: "Copyright Text" }
+    tabsSection:
+        meta:
+            expand: media
+        tabs:
+            - name: general
+              meta:
+                  label: { de: "Allgemein", en: "General" }
+              fields:
+                  - name: public
+                    type: boolean
+                    meta:
+                        defaultValue: true
+                        label:
+                            de: Veröffentlicht
+                            en: Public
+                        helperText:
+                            de: "Alle allgemeinen Informationen werden auf der Seite angezeigt."
+                            en: "All general information are displayed on the page."
+            - name: meta
+              meta:
+                  label: { de: "Meta", en: "Meta" }
+              fields:
+                  - name: meta
+                    type: object
+                    subFields:
+                        - name: metaTitle
+                          type: string
+                          meta:
+                              label: { de: "Titel der Webseite", en: "Page Title" }
+                        - name: metaDescription
+                          type: string
+                          meta:
+                              label: { de: "Beschreibung der Webseite", en: "Page Description" }
+                        - name: metaTagRobots
+                          type: string[]
+                          meta:
+                              widget: chipArray
+                              label:
+                                  de: Robots
+                                  en: Robots
+                              defaultValue: []
+                              autocomplete: true
+                              choices:
+                                  - { id: "noindex", name: "noindex" }
+                                  - { id: "index", name: "index" }
+                                  - { id: "follow", name: "follow" }
+                                  - { id: "nofollow", name: "nofollow" }
+                                  - { id: "noimageindex", name: "noimageindex" }
+                                  - { id: "none", name: "none" }
+                                  - { id: "noarchive", name: "noarchive" }
+                                  - { id: "nocache", name: "nocache" }
+                                  - { id: "nosnippet", name: "nosnippet" }
+                                  - { id: "nnavailable_after", name: "nnavailable_after" }
+                              helperText:
+                                  de: "<strong>Noindex</strong>: Weist eine Suchmaschine an, eine Seite nicht zu indizieren.<br/><strong>index</strong>: Weist eine Suchmaschine an, eine Seite zu indizieren. Beachten Sie, dass Sie dieses Meta-Tag nicht hinzufügen müssen; es ist die Voreinstellung.<br/><strong>follow</strong>: Auch wenn die Seite nicht indexiert ist, sollte der Crawler allen Links auf einer Seite folgen und Eigenkapital an die verlinkten Seiten weitergeben.<br/><strong>nofollow</strong>: Weist einen Crawler an, keinen Links auf einer Seite zu folgen oder Link-Equity weiterzugeben.<br/><strong>noimageindex</strong>: Weist einen Crawler an, keine Bilder auf einer Seite zu indizieren.<br/><strong>none</strong>: Entspricht der gleichzeitigen Verwendung der noindex- und nofollow-Tags.<br/><strong>noarchive</strong>: Suchmaschinen sollten keinen zwischengespeicherten Link zu dieser Seite auf einem SERP anzeigen.<br/><strong>nocache</strong>: Wie noarchive, aber nur von Internet Explorer und Firefox verwendet.<br/><strong>nosnippet</strong>: Weist eine Suchmaschine an, kein Snippet dieser Seite (d. h. Meta-Beschreibung) dieser Seite auf einem SERP anzuzeigen.<br/><strong>nnavailable_after</strong>: Suchmaschinen sollen diese Seite nach einem bestimmten Datum nicht mehr indexieren.<br/>"
+                                  en: "<strong>Noindex</strong>: Tells a search engine not to index a page.<br/><strong>index</strong>: Tells a search engine to index a page. Note that you don’t need to add this meta tag; it’s the default.<br/><strong>follow</strong>: Even if the page isn’t indexed, the crawler should follow all the links on a page and pass equity to the linked pages.<br/><strong>nofollow</strong>: Tells a crawler not to follow any links on a page or pass along any link equity.<br/><strong>noimageindex</strong>: Tells a crawler not to index any images on a page.<br/><strong>none</strong>: Equivalent to using both the noindex and nofollow tags simultaneously.<br/><strong>noarchive</strong>: Search engines should not show a cached link to this page on a SERP.<br/><strong>nocache</strong>: Same as noarchive, but only used by Internet Explorer and Firefox.<br/><strong>nosnippet</strong>: Tells a search engine not to show a snippet of this page (i.e. meta description) of this page on a SERP.<br/><strong>nnavailable_after</strong>: Search engines should no longer index this page after a particular date.<br/>"
+                        - name: metaKeywords
+                          type: string
+                          meta:
+                              label: { de: "SEO / Schlüsselwörter", en: "SEO / Keywords" }
+                              helperText:
+                                  de: "Beispiel: Stichwort1, Stichwort2, Stichwort3"
+                                  en: "Example: keyword1, keyword2, keyword3"
+            - name: person
+              meta:
+                  label: { de: "Person", en: "Person" }
+              fields:
+                  - name: person
+                    type: object
+                    subFields:
+                        - name: salutation
+                          type: string
+                          meta:
+                              label: { de: "Anrede", en: "Salutation" }
+                        - name: firstname
+                          type: string
+                          meta:
+                              label: { de: "Vorname", en: "Firstname" }
+                        - name: lastname
+                          type: string
+                          meta:
+                              label: { de: "Nachname", en: "Lastname" }
+                        - name: additional
+                          type: string
+                          meta:
+                              label: { de: "Zusatz", en: "Additional" }
+                        - name: street
+                          type: string
+                          meta:
+                              label: { de: "Straße", en: "Street" }
+                        - name: postcode
+                          type: string
+                          meta:
+                              label: { de: "Postleitzahl", en: "Postcode" }
+                        - name: city
+                          type: string
+                          meta:
+                              label: { de: "Ort", en: "City" }
+                        - name: tel
+                          type: string
+                          meta:
+                              label: { de: "Telefonnummer", en: "Phone number" }
+                        - name: fax
+                          type: string
+                          meta:
+                              label: { de: "Faxnummer", en: "Fax number" }
+                        - name: mobile
+                          type: string
+                          meta:
+                              label: { de: "Handynummer", en: "Mobile number" }
+                        - name: email
+                          type: string
+                          meta:
+                              label: { de: "E-Mail", en: "E-Mail" }
+            - name: company
+              meta:
+                  label: { de: "Unternehmen", en: "Company" }
+              fields:
+                  - name: person
+                    type: object
+                    subFields:
+                        - name: companyName
+                          type: string
+                          meta:
+                              label: { de: "Name des Unternehmens", en: "Company Name" }
+                        - name: companyWebUrl
+                          type: string
+                          meta:
+                              label: { de: "URL zur Webseite", en: "Website URL" }
+                        - name: companyAddresses
+                          type: object[]
+                          meta:
+                              label:
+                                  de: Adresse
+                                  en: Adresse
+                              css:
+                          subFields:
+                              - name: street
+                                type: string
+                                meta:
+                                    label: { de: "Straße", en: "Street" }
+                              - name: houseNr
+                                type: string
+                                meta:
+                                    label: { de: "Hausnummer", en: "House number" }
+                              - name: postcode
+                                type: string
+                                meta:
+                                    label: { de: "PLZ", en: "ZIP" }
+                              - name: city
+                                type: string
+                                meta:
+                                    label: { de: "Ort", en: "City" }
+                              - name: tel
+                                type: string
+                                meta:
+                                    label: { de: "Telefon", en: "Phone number" }
+                              - name: fax
+                                type: string
+                                meta:
+                                    label: { de: "Fax", en: "Fax" }
+                              - name: email
+                                type: string
+                                meta:
+                                    label: { de: "E-Mail", en: "E-Mail" }
+            - name: media
+              meta:
+                  label: { de: "Medien", en: "Media" }
+              fields:
+                  - name: media
+                    type: object
+                    subFields:
+                        - name: favicon
+                          type: file
+                          meta:
+                              label: { de: "Favicon", en: "Favicon" }
+                              helperText:
+                                  de: "Ein Favicon ist ein kleines Icon, Symbol oder Logo, das von Webbrowsern verwendet wird, um eine Website auf wiedererkennbare Weise zu kennzeichnen."
+                                  en: "A favicon is a small icon, symbol, or logo used by web browsers to identify a website in a recognizable way."
+                        - name: brand
+                          type: file
+                          meta:
+                              label: { de: "Logo / Brand", en: "Logo / Brand" }
+                              helperText:
+                                  de: "Logo der Seite"
+                                  en: "Page Logo"
+                        - name: mediaFiles
+                          type: object[]
+                          meta:
+                              label: { de: "Dateien", en: "Files" }
+                          subFields:
+                              - name: title
+                                type: string
+                                meta:
+                                    label: { de: "Datei-Titel", en: "File Title" }
+                              - name: alternateText
+                                type: string
+                                meta:
+                                    label: { de: "Alternativer Text", en: "Alternate Text" }
+                              - name: id
+                                type: string
+                                meta:
+                                    editableWhileCreating: true
+                                    label: { de: "Technischer Name / ID", en: "Technical name / ID" }
+                                    helperText:
+                                        de: "Achtung: Eine technische ID ist meist fest im Code der Seite verknüpft und darf, wenn sie einmal gesetzt wurde, nicht verändert werden!"
+                                        en: "Attention: A technical ID is usually permanently linked in the code of the page and, once it has been set, must not be changed!"
+                              - name: file
+                                type: file
+                                meta:
+                                    label: { de: "Datei", en: "File" }
+            - name: copyright
+              meta:
+                  label: { de: "Copyright", en: "Copyright" }
+              fields:
+                  - name: copyrightText
+                    type: string
+                    meta:
+                        label: { de: "Copyright Text", en: "Copyright Text" }
 
 imageFilter:
     xs:
diff --git a/api/collections/navigation.yml b/api/collections/navigation.yml
index bc69477..5b71f5b 100644
--- a/api/collections/navigation.yml
+++ b/api/collections/navigation.yml
@@ -204,3 +204,4 @@ indexes:
       key:
           - ident
           - locale
+          - path
diff --git a/src/api.ts b/src/api.ts
index 977ef7f..be4263a 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -186,8 +186,11 @@ export const sendEmail = async (type: string = "contactForm", data: any, noToken
     })
 }
 
-export const getContent = async (path: string): Promise<Content> => {
-    const c = await api<Content[]>("content", { limit: 1, filter: { path } })
+export const getContent = async (path: string, lang: string): Promise<Content> => {
+    const c = await api<Content[]>("content", {
+        limit: 1,
+        filter: { path: path.replace("/" + lang, ""), locale: lang },
+    })
     if (c?.data?.length) {
         return c.data[0]
     }
diff --git a/src/components/App.svelte b/src/components/App.svelte
index e21e0fb..aa22c84 100644
--- a/src/components/App.svelte
+++ b/src/components/App.svelte
@@ -1,7 +1,7 @@
 <script lang="ts">
     import { Router, Route } from "svelte-routing"
     import { scrollToTop } from "svelte-scrollto"
-    import { location } from "../store"
+    import { generalInfo, location } from "../store"
 
     import Home from "./routes/Home.svelte"
     import Content from "./routes/Content.svelte"
@@ -10,6 +10,7 @@
     import Footer from "./widgets/Footer.svelte"
 
     export let url = ""
+
     if (url) {
         // ssr
         let l = url.split("?")
@@ -22,13 +23,40 @@
     }
 
     // scroll to top on new site
-    location.subscribe((l) => {
-        if (l.push) scrollToTop()
+    location.subscribe((location) => {
+        if (location.push) scrollToTop()
     })
 
     if (typeof window !== "undefined") console.log("App initialized")
 </script>
 
+<svelte:head>
+    {#if $generalInfo?.meta?.metaTitle}
+        <title>{$generalInfo?.meta?.metaTitle}</title>
+    {/if}
+    {#if $generalInfo?.meta?.metaDescription}
+        <meta name="description" content="{$generalInfo?.meta?.metaDescription}" />
+    {/if}
+    {#if $generalInfo?.meta?.metaKeywords}
+        <meta name="keywords" content="{$generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}" />
+    {/if}
+    {#if $generalInfo?.person?.firstname || $generalInfo?.person?.lastname}
+        <meta
+            name="author"
+            content="{$generalInfo?.person?.firstname ? $generalInfo?.person?.firstname : ''} {$generalInfo?.person
+                ?.lastname
+                ? $generalInfo?.person?.lastname
+                : ''}"
+        />
+    {/if}
+    {#if $generalInfo?.meta?.metaTagRobots}
+        <meta name="robots" content="{$generalInfo?.meta?.metaTagRobots}" />
+    {/if}
+    {#if $generalInfo?.media?.favicon}
+        <link rel="shortcut icon" type="image/x-icon" href="{$generalInfo?.media?.favicon.src}" />
+    {/if}
+</svelte:head>
+
 <Header />
 
 <div>
diff --git a/src/components/routes/Content.svelte b/src/components/routes/Content.svelte
index e0645d9..62e2b0d 100644
--- a/src/components/routes/Content.svelte
+++ b/src/components/routes/Content.svelte
@@ -1,7 +1,6 @@
 <script lang="ts">
     import { getContent } from "../../api"
-    // import { apiBaseURL } from "../../config"
-    import { generalInfo } from "../../store"
+    import { generalInfo, currentLang } from "../../store"
 
     export let path: string
 
@@ -10,7 +9,7 @@
 
     function load() {
         loading = true
-        getContent(path)
+        getContent(path, $currentLang)
             .then((c) => {
                 content = c
             })
@@ -24,10 +23,6 @@
 
 <svelte:head>
     <title>{content?.name ? content?.name + " - " : ""}{$generalInfo?.meta?.metaTitle}</title>
-    <meta name="description" content="{$generalInfo?.meta?.metaDescription}" />
-    <meta name="keywords" content="{$generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}" />
-    <meta name="author" content="{$generalInfo?.person?.firstname} {$generalInfo?.person?.lastname}" />
-    <meta name="robots" content="{$generalInfo?.meta?.metaTagRobots}" />
 </svelte:head>
 
 <div class="container">
@@ -37,12 +32,8 @@
                 <!-- Loader -->
             {:else if content}
                 {#each content.blocks || [] as b}
-                    <h2>{b.title}</h2>
-                    <div>{@html b.text}</div>
+                    {JSON.stringify(b)}
                 {/each}
-            {:else}
-                <h1>Seite nicht gefunden</h1>
-                <div>Pfad: {path}</div>
             {/if}
         </div>
     </div>
diff --git a/src/components/routes/Home.svelte b/src/components/routes/Home.svelte
index 162fda0..3cea647 100644
--- a/src/components/routes/Home.svelte
+++ b/src/components/routes/Home.svelte
@@ -6,20 +6,45 @@
     import GoogleMaps from "../widgets/GoogleMaps.svelte"
     import ScrollTo from "../widgets/ScrollTo.svelte"
     import ContactForm from "../widgets/ContactForm.svelte"
+    import GeneralMediaImage from "../widgets/GeneralMediaImage.svelte"
 
     let expandedForm: string = "recipe"
 </script>
 
-<svelte:head>
-    <title>{$generalInfo?.meta?.metaTitle}</title>
-    <meta name="description" content="{$generalInfo?.meta?.metaDescription}" />
-    <meta name="keywords" content="{$generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}" />
-    <meta name="author" content="{$generalInfo?.person?.firstname} {$generalInfo?.person?.lastname}" />
-    <meta name="robots" content="{$generalInfo?.meta?.metaTagRobots}" />
-</svelte:head>
+<!-- <svelte:head>
+    {#if $generalInfo?.meta?.metaTitle}
+        <title>{$generalInfo?.meta?.metaTitle}</title>
+    {/if}
+    {#if $generalInfo?.meta?.metaDescription}
+        <meta name="description" content="{$generalInfo?.meta?.metaDescription}" />
+    {/if}
+    {#if $generalInfo?.meta?.metaKeywords}
+        <meta name="keywords" content="{$generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}" />
+    {/if}
+    {#if $generalInfo?.person?.firstname || $generalInfo?.person?.lastname}
+        <meta
+            name="author"
+            content="{$generalInfo?.person?.firstname ? $generalInfo?.person?.firstname : ''} {$generalInfo?.person
+                ?.lastname
+                ? $generalInfo?.person?.lastname
+                : ''}"
+        />
+    {/if}
+    {#if $generalInfo?.meta?.metaTagRobots}
+        <meta name="robots" content="{$generalInfo?.meta?.metaTagRobots}" />
+    {/if}
+    {#if $generalInfo?.media?.favicon}
+        <link rel="shortcut icon" type="image/x-icon" href="{$generalInfo?.media?.favicon.src}" />
+    {/if}
+</svelte:head> -->
 
 <section class="contact">
     <div class="container">
+        <div class="row">
+            <div class="col-md-12">
+                <GeneralMediaImage id="test1" />
+            </div>
+        </div>
         <div class="row nospace">
             <div class="col-md-6">
                 <ContactForm type="recipe" collapsed="{expandedForm !== 'recipe'}" />
diff --git a/src/components/widgets/GeneralMediaImage.svelte b/src/components/widgets/GeneralMediaImage.svelte
new file mode 100644
index 0000000..1516caa
--- /dev/null
+++ b/src/components/widgets/GeneralMediaImage.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+    import { generalInfo } from "../../store"
+
+    export let id: string = null
+    export let cssClass: string = ""
+</script>
+
+{#if id}
+    {#each $generalInfo?.media?.mediaFiles || [] as mediaFile}
+        {#if mediaFile.id === id && mediaFile.file}
+            {#if mediaFile.file.src.includes(";base64,")}
+                <img
+                    src="{mediaFile.file.src}"
+                    alt="{mediaFile.alternateText ? mediaFile.alternateText + ' - ' : ''}"
+                    class="{cssClass}"
+                />
+            {/if}
+        {/if}
+    {/each}
+{/if}
diff --git a/src/components/widgets/LanguageChooser.svelte b/src/components/widgets/LanguageChooser.svelte
new file mode 100644
index 0000000..33abfc4
--- /dev/null
+++ b/src/components/widgets/LanguageChooser.svelte
@@ -0,0 +1,30 @@
+<script lang="ts">
+    import { navigations, location, currentLang } from "../../store"
+
+    $: languages = []
+
+    $: if ($navigations?.length) {
+        $navigations.forEach((nav) => {
+            if (!languages.includes(nav.locale)) {
+                languages.push(nav.locale)
+            }
+        })
+        languages = languages
+    }
+
+    $: console.log($location)
+</script>
+
+<div class="language-chooser">
+    {#each languages as language}
+        <div
+            class="lang"
+            class:active="{$currentLang === language}"
+            on:click="{() => {
+                $currentLang = language
+            }}"
+        >
+            {language}
+        </div>
+    {/each}
+</div>
diff --git a/src/components/widgets/Navigation.svelte b/src/components/widgets/Navigation.svelte
index 12d9366..dcc7e29 100644
--- a/src/components/widgets/Navigation.svelte
+++ b/src/components/widgets/Navigation.svelte
@@ -2,11 +2,12 @@
     import * as animateScroll from "svelte-scrollto"
     import Icon from "mdi-svelte"
     import { mdiMenu } from "@mdi/js"
-    // import { generalInfo } from "../../store"
 
     import { links } from "svelte-routing"
     import { navigations } from "../../store"
 
+    import LanguageChooser from "./LanguageChooser.svelte"
+
     export let ident = "main"
 
     let navigation: Navigation
@@ -21,6 +22,8 @@
     }
 </script>
 
+<LanguageChooser />
+
 {#if navigation}
     <nav class="{ident}" use:links>
         {#each navigation?.items || [] as item}
@@ -36,7 +39,7 @@
                     {item.settings.title}
                 </a>
             {:else}
-                <a href="{item.settings.page}">
+                <a href="/{navigation.locale}{item.settings.page}">
                     {item.settings.title}
                 </a>
             {/if}
@@ -67,7 +70,7 @@
                     </div>
                 {:else}
                     <div class="nav-item">
-                        <a href="{item.settings.page}" on:click="{() => (showMobileNav = false)}">
+                        <a href="/{navigation.locale}{item.settings.page}" on:click="{() => (showMobileNav = false)}">
                             {item.settings.title}
                         </a>
                     </div>
diff --git a/src/components/widgets/ScrollTo.svelte b/src/components/widgets/ScrollTo.svelte
index a73fd01..68b3068 100644
--- a/src/components/widgets/ScrollTo.svelte
+++ b/src/components/widgets/ScrollTo.svelte
@@ -1,6 +1,8 @@
 <script lang="ts">
     import { createEventDispatcher } from "svelte"
 
+    import GeneralMediaImage from "./GeneralMediaImage.svelte"
+
     const dispatch = createEventDispatcher()
 </script>
 
@@ -14,7 +16,7 @@
                 })
             }}"
         >
-            <!-- <img src="img/icon/contact.svg" alt="" /> -->
+            <GeneralMediaImage id="contact" />
         </a>
     </div>
     <div class="circle-contact">
@@ -26,12 +28,12 @@
                 })
             }}"
         >
-            <!-- <img src="img/icon/recipe.svg" alt="" /> -->
+            <GeneralMediaImage id="recipe" />
         </a>
     </div>
     <div class="circle-top">
         <a href="/#">
-            <!-- <img src="img/icon/chevron-up.svg" alt="" /> -->
+            <GeneralMediaImage id="up" />
         </a>
     </div>
 </div>
diff --git a/src/css/theme-2022/components/general.less b/src/css/theme-2022/components/general.less
index c336783..0dd46c3 100755
--- a/src/css/theme-2022/components/general.less
+++ b/src/css/theme-2022/components/general.less
@@ -19,39 +19,6 @@ body {
     }
 }
 
-// Body Images
-
-.body-image-left {
-    position: absolute;
-    left: 0;
-    top: 80rem;
-
-    @media (max-width: 900px) {
-        top: 90rem;
-    }
-}
-
-// Lists
-
-ul {
-    list-style-type: none;
-    padding-left: 15px;
-
-    li {
-        line-height: 30px;
-        padding-left: 0;
-        font-weight: 700;
-
-        &:before {
-            content: "\203A";
-            font-weight: 700;
-            position: absolute;
-            top: -1px;
-            left: -12px;
-        }
-    }
-}
-
 // Scroll To Top
 
 .scroll-to-top {
@@ -96,13 +63,3 @@ ul {
         right: -53px;
     }
 }
-
-// Promotion
-
-.promotion-image-wave-top {
-    height: 70px;
-}
-
-.promotion-image-wave-bottom {
-    height: 137px;
-}
diff --git a/src/css/theme-2022/components/language-chooser.less b/src/css/theme-2022/components/language-chooser.less
new file mode 100644
index 0000000..cfe3887
--- /dev/null
+++ b/src/css/theme-2022/components/language-chooser.less
@@ -0,0 +1,22 @@
+.language-chooser {
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    border: 1px solid #ccc;
+
+    .lang {
+        border: 1px solid #ccc;
+        cursor: pointer;
+
+        &:hover {
+            background: #ccc;
+            color: black;
+        }
+
+        &.active {
+            background: #ccc;
+            color: black;
+            font-weight: 700;
+        }
+    }
+}
diff --git a/src/css/theme-2022/main.less b/src/css/theme-2022/main.less
index e16e29b..8a809ca 100644
--- a/src/css/theme-2022/main.less
+++ b/src/css/theme-2022/main.less
@@ -53,5 +53,6 @@
 @import "components/history";
 @import "components/top-section";
 @import "components/forms";
+@import "components/language-chooser";
 
 @import "components/cc-bar";
diff --git a/src/css/theme-2022/reset.less b/src/css/theme-2022/reset.less
index 23a118c..04458d0 100644
--- a/src/css/theme-2022/reset.less
+++ b/src/css/theme-2022/reset.less
@@ -49,6 +49,7 @@ a:not([class]) {
 /* Make images easier to work with */
 img,
 picture {
+    width: 100%;
     max-width: 100%;
     display: block;
 }
diff --git a/src/store.ts b/src/store.ts
index 19880f5..75e3148 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -1,20 +1,25 @@
 import { writable, get } from "svelte/store"
 import { getGeneralInformation, getArticles, getNavigations } from "./api"
 
-const initLoc = {
+// Localtion
+
+const initialLocation = {
     path: (typeof window !== "undefined" && window.location?.pathname) || "/",
     search: (typeof window !== "undefined" && window.location?.search) || "",
     push: false,
     pop: false,
 }
+export const location = writable(initialLocation)
 
-export const location = writable(initLoc)
+// Current Language
 
-const locale = {
-    key: "de",
-    title: "Deutsch",
+function langFromUrl(): string {
+    if (new RegExp(`\/[a-zA-Z]*[-[a-zA-Z]*]{0,1}\/[a-zA-Z0-9-]*$`).test(get(location).path)) {
+        return get(location)?.path.split("/")[1]
+    }
+    return "de"
 }
-export const currentLocale = writable(locale)
+export const currentLang = writable<string>(langFromUrl())
 
 // General Information
 
@@ -43,7 +48,7 @@ const getAllNavigations = async (locale: Locale) => {
     const list = await getNavigations(locale)
     navigations.set(list)
 }
-getAllNavigations(locale)
+getAllNavigations({ key: get(currentLang) })
 
 // Cookies - Webmakers Cookie Bar
 
diff --git a/types/global.d.ts b/types/global.d.ts
index e65939e..727d208 100644
--- a/types/global.d.ts
+++ b/types/global.d.ts
@@ -117,7 +117,7 @@ interface NavigationItem {
 
 interface Locale {
     key: string
-    title: string
+    title?: string
 }
 
 interface GeneralImage {