ProcessWire - Multilanguage Website: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
 
(43 dazwischenliegende Versionen von 7 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 
Mehrsprachige Websites mit ProcessWire / Andere Default Sprache
 
Mehrsprachige Websites mit ProcessWire / Andere Default Sprache
 +
 +
== Links ==
 +
* https://processwire.com/docs/multi-language-support/
 
* https://processwire.com/talk/topic/5518-multi-language-site/
 
* https://processwire.com/talk/topic/5518-multi-language-site/
 
* http://processwire.com/api/multi-language-support/multi-language-urls/
 
* http://processwire.com/api/multi-language-support/multi-language-urls/
* https://processwire.com/talk/topic/9322-change-default-language-for-homepage/ (Modul Solution)
+
* https://processwire.com/talk/topic/9322-change-default-language-for-homepage/ (Modul Solution, mehr zur Anschauung)
 +
 
 +
== Einleitung ==
 +
Es gibt mehrere Bereiche an die man denken muss. Einmal geht es um die Eingabe im Backend, die Ausgabe im Frontend, die Sprachnavigation auf der Website und die Templates:
 +
* Wie übersetze ich Text in meinen '''Templates''' ? Siehe unten i18n
 +
* Wie übersetze ich '''Inhalte''' im Backend ?  Dafür ist das Modul Language Support Fields zuständig
 +
* Wie sollen meine URLs aussehen ? Prinzipiell kann man jedem User unterschiedliche Sprachen auch ohne andere Domain liefern (über seine Session) aber i.d.R wollen wir die URL anzupassen.
 +
** ''domain.de/en/meineSeite'' oder ''domain.de/myPage''
 +
** Um '''Seitennamen''' zu übersetzen oder ein Domainkürzel in der URL voranzustellen benötige ich das Modul '''Language Support Page Names'''
 +
 
 +
== Welche Module benötige ich ==
 +
Da es einige Module in diesem Zusammenhang gibt hier eine Übersicht. Man findet Sie am besten unter
 +
Modules > Core > Language
  
== Deutsch als Default Sprache ==
+
* '''Languages Support''' - ProcessWire multi-language support. Basis Modul bracht man für alle Beispiele unten. Reicht aus, wenn man nur die Standard-Sprache ändern will. '''Hinweis:''' In der aktuellen PW3 Version schlägt einem ProcessWire nach Installation des Language Support Moduls gleich die Ergänzenden Module (s.u.) vor und man kann den Installationsprozess ziemlich fix erledigen.
* Enable languages support -> Core Module "Language Support" aktivieren. -> Languages stehen im Backend Setup zur Verfügung
+
* '''Languages Support - Fields''' Required to use multi-language fields. Basis für mehrsprachige Felder im Backend.
* Titel der Default Sprache anpassen (z.B. Deutsch (default) )
+
* '''Languages Support - Page Names''' (LanguageSupportPageNames) Required to use multi-language page names. Braucht man nur wenn '''alle Seiten in allen Sprachen unterschiedliche Namen''' bekommen sollen.
* Language Pack in der default Sprache installieren -> Dies ist ab jetzt die Default Sprache. Nicht vergessen auch den lang Tag im Header zu setzen, damit der Browser die Sprache richtig erkennt.
+
* '''Languages Support - Tabs''' Organizes multi-language fields into tabs for a cleaner easier to use interface.
 +
Für mehrsprachige Seiten benötigen wir im Frontend i.d.R. folgende Module:
 +
* '''Language Support Fields''' - Sind Felder, die im Backend für jede Sprache eine eigene Eingabe bieten.
 +
* '''Language Support Page Names''' benötigt man, damit man für die Sprachen eigene URLs angeben kann. Z.B. bei Home in Englisch /en/ usw.
 +
* '''FieldtypePageTitleLanguage''' benötigt man wenn man alle Seitenamen anpassen will (seite1_de seite1_fr ...) Für einen reinen Sprachpfad (/de/Seite) braucht man das nicht.
  
=== Weitere Sprachen ===
+
== Einsprachige Seite aber Deutsch als Default Sprache ==
* Für weitere Sprachen entsprechend hinzufügen.
+
Wenn nur die Standardsprache verändern möchte, aber keine Mehrsprachige Seite benötigt brauchen wir nur das Modul '''Language Support'''
+
* Enable languages support -> '''Core Module "Language Support" aktivieren'''. -> Sprachen stehen num im Backend Setup zur Verfügung
drop in the none english language pack (for admin backend) into the default language, (e.g. german langpack)
+
* '''Titel der Default Sprache''' anpassen (z.B. Deutsch (default) )
+
* Language Pack in der default Sprache installieren -> Dies ist ab jetzt die Default Sprache. Nicht vergessen auch den '''lang Tag im Header''' zu setzen, damit der Browser die Sprache richtig erkennt.
add a new language to it and drop in a language pack for any none english language or simply don't drop in a language pack to get the english version (but not as the default one!)
 
As a nice sideeffect every new user in your system gets the native language per default without have it to select from the list.
 
  
So, yes, this is no solution if you once have set it up and need to switch the default language afterwards, but just want to note it.
+
== Sprachpakete installieren ==
 +
https://processwire.com/modules/category/language-pack/
 +
* Sprache auswählen und dort komplettes zip hochladen.
 +
* Informell (DU) leider im Moment nicht vorhanden
  
=== Beispiel Default Sprache Deutsch ===
+
== Basis-Module für Mehrsprachigkeit im Backend ==
Todo Testen
+
Für mehrsprachige Seiten benötigen wir i.d.R. folgende Module:
* Modul Language Support
+
* '''Language Support Fields''' für die Backend Übersetzungen und '''Language Support Page Names''' für die URLs.
* Translation File unter Setup Sprachen hochladen
+
* '''FieldtypePageTitleLanguage''' benötigt man wenn man alle Seitenamen anpassen will (seite1_de seite1_fr ...) Für einen reinen Sprachpfad (/de/Seite) braucht man das nicht.
* Übersetzungen von Hand hinzufügen
+
* Für weitere Sprachen entsprechend hinzufügen.
 +
Vorgehen:
 +
* Language Packs installieren: drop in the none english language pack (for admin backend) into the default language, (e.g. german langpack)
 +
* As a nice sideeffect every new user in your system gets the native language per default without have it to select from the list.
  
 
== Templates für Multilanguage vorbereiten (i18n) ==
 
== Templates für Multilanguage vorbereiten (i18n) ==
 
  https://processwire.com/docs/multi-language-support/code-i18n/
 
  https://processwire.com/docs/multi-language-support/code-i18n/
 +
https://processwire.com/blog/posts/functional-fields/
 +
=== Functional fields ===
 +
In PW3 kamen die functional Fields hinzu. Mit diesen kann man statischen Text dynamisch im Page Editor ansprechen. D.h. das Functional Field findet Texte im Template und macht sie automatisch editierbar im Page Editor. Das Ganze funktioniert auch Mehrsprachig.
 +
[[ProcessWire - Functional Fields]]
 +
https://processwire.com/blog/posts/functional-fields/
 +
Beispiele für die Ausgabe von
 +
<pre>
 +
__text('your text');
 +
__textarea('your text');
 +
__richtext('<p>your text</p>');
 +
__text('Subscribe Now', 'subscribe') // define a identifier for this text snippet...
 +
__text('subscribe') // ..reuse it this way
 +
$pages->get('/')->mytext->subscribe // reuse from another template
 +
__text('Subscribe Now', 'subscribe', 'Submit button'); // Label for page editor
 +
__text('Subscribe Now', 'subscribe', 'label=Submit button, notes=Test'); // or use a pw selector
 +
__text('Subscribe Now', 'name=subscribe, label=Submit button, notes=Test'); // equivalent to upper
 +
 +
</pre>
 +
 +
=== Standard Multilanguage nach i18n ===
  
 
  $out = $this->_("Live long and prosper");  // syntax within a class
 
  $out = $this->_("Live long and prosper");  // syntax within a class
Zeile 48: Zeile 91:
 
echo _x('Comment', 'column name');
 
echo _x('Comment', 'column name');
 
</pre>
 
</pre>
 +
 
=== Kommentare für den Übersetzer und User ===
 
=== Kommentare für den Übersetzer und User ===
 
  $date = __('g:i:s a'); // Date string in PHP date() format
 
  $date = __('g:i:s a'); // Date string in PHP date() format
Zeile 54: Zeile 98:
 
* Eine Zeile ein Paar Anführungszeichen
 
* Eine Zeile ein Paar Anführungszeichen
 
* Nur eine Übersetzungsfunktion pro Zeile
 
* Nur eine Übersetzungsfunktion pro Zeile
 +
 +
== Language Switcher ==
 +
<syntaxhighlight lang="php">
 +
// remember what language is set to
 +
$savedLanguage = $user->language;
 +
 +
foreach($languages as $language) {
 +
 +
  // if user is already viewing the page in this language, skip it
 +
  if($language->id == $savedLanguage->id) continue;
 +
 +
  // if this page isn't viewable (active) for the language, skip it
 +
  if(!$page->viewable($language)) continue;
 +
 +
  // set the user's language, so that the $page->url and any other
 +
  // fields we access from it will be reflective of the $language
 +
  $user->language = $language;
 +
 +
  // output a link to this page in the other language
 +
  echo "<li><a href='$page->url'>$language->title: $page->title</a></li>";
 +
}
 +
// restore the original language setting
 +
$user->language = $savedLanguage;
 +
</syntaxhighlight>
 +
 +
== Seiten nur in einer Sprache verfügbar ==
 +
What If I want to create/publish a page only in DE language, and that page should not be available in the default language?
 +
Default language is required. But you could always add your own checkbox field to the page as a toggle to disable it. Your head.inc or _init.php or whatever your common initialization file is could check:
 +
 +
if($page->disable_default_language && $user->language->isDefault()) throw new Wire404Exception();
 +
You'd also have to consider it with navigation generation, perhaps skipping over pages that have the toggle set while in the default language, or adding it to your selectors when querying pages.
 +
 +
Edit: you could also just choose to not use the default language at all.
 +
 +
if($user->language->isDefault()) $user->language = $languages->get("en-us"); // or whatever you want your default to be
 +
 +
== Language Alternate Fields ==
 +
Eine Möglichkeit alle Felder (auch Bilder) in verschiedenen Sprachen zu nutzen.
 +
https://processwire.com/docs/multi-language-support/multi-language-fields/#language-alternate-fields
 +
 +
== Probleme lösen ==
 +
=== Feldtyp nicht als Multilanguagefeld vorhanden - Language Alternate Field ===
 +
Manche Felder (z.B. AssistedUrl) gibt es nur einsprachig. ProcessWire bietet aber mit den '''Language Alternate Fields''' eine Möglichkeit solche Felder mehrsprachig zu nutzen. Dazu braucht man kein Modul. Es ist eine Basis Funktionalität.
 +
 +
Dazu legt man für jede zusätzliche Sprache ein weiteres Feld mit dem selben Namen + der Namenserweiterung _sprachname an. Beispielsweise kann man für ein Feld Namens link ein weiteres Feld Namens '''link_en''' anlegen. Dann nutzt ProcessWire automatisch für die Sprache mit dem Namen '''en'''
 +
 +
== Beispiele ==
 +
 +
=== Multilanguage Page - Quickstart ===
 +
 +
==== 1. Module ====
 +
* s.o. alle benötigten installieren
 +
 +
==== 2. Backend ====
 +
* Default Sprache festlegen
 +
** Wenn nicht Englisch Sprachpaket installieren
 +
** Wenn der Titel der Sprache auch der Identifier für den html Tag sein soll muss er ''de, en, fi''... lauten
 +
* Weitere Sprachen hinzufügen. Für Englisch benötigt man kein Sprachpaket. Als Name am besten den offiziellen Code (de, en...) vergeben.
 +
* Die Homepage entscheidet über den Pfad. Wenn Englisch z.B. unter www.meineSeite.com/en/seitenname/ erreichbar sein soll, dann muss für Englisch unter '''Einstellung > Namen en''' eingetragen werden.
 +
* Alle Felder die Übersetzt werden sollen auf Multilanguage Felder umstellen
 +
 +
==== 3. Templates ====
 +
===== Lang Attribute =====
 +
 +
Das '''lang Attribut''' sollte zur Sprache passen.
 +
 +
'''Möglichkeit 1:'''
 +
 +
Mit der _x Funktion kann PW beliebige Strings in Templates übersetzten. PW findet diese automatisch.
 +
_main.php (oder header..)
 +
<html lang="<?php echo _x('en', 'HTML language code'); ?>">
 +
Im '''Backend''' muss man zunächst für Englisch den '''Sprachindex aufbauen''' ('''Spracheinstellungen Verwaltung > Sprachen > Englisch''')
 +
 +
Dann kann man nun in den '''Spracheinstellungen Verwaltung > Sprachen > meineSprache''' das Label ''HTML language code'' suchen und mit dem passenden lang tag ersetzen.
 +
 +
Das Funktioniert auch mit beliebigen anderen Werten die man im Template hartkodiert hat.
 +
 +
'''Möglichkeit 2 (bevorzugt weil schnell):'''
 +
 +
Man kann auch den Language Title verwenden wenn dieser entsprechend vergeben wurde (en, de,...) .
 +
 +
'''Nachteil:''' Dann kann man aber den Titel nicht mehr frei verändern wenn man ihn auch als Bezeichnung für den Language Switcher nutezn möchte. Der Titel für default heißt dann z.B. de und zwar auch in der englischen Übersetzung. '''Also nicht in der Übersetzung "german" schreiben sondern auch de oder einfach gar nichts.'''
 +
 +
<html lang="<?= $user->language->title ?>">
 +
 +
Wenn du trotzdem irgendwelche ausgeschriebenen Label benötigst kannst du dir von Hand Variablen definieren und Übersetzen (z.B. mit der Übersetzungsfunktion __('de') oder_x('de', 'Label für deutsch');
 +
 +
==== 4. Language Switcher ====
 +
'''Text Navigation''' z.B. so:
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
 +
?>
 +
<ul id="nav-lang" class="nav nav-h">
 +
<?php
 +
foreach($languages as $language){
 +
if(!$page->viewable($language)) continue; // is page viewable in this language?
 +
if($language->id == $user->language->id) {
 +
echo "<li class='current'>";
 +
} else {
 +
echo "<li>";
 +
}
 +
$url = $page->localUrl($language);
 +
$hreflang = $pages->get('/')->getLanguageValue($language, 'name');
 +
echo '<a hreflang="'.$hreflang.'" href="'.$url.'" style="text-transform:uppercase;">'.$language->title.'</a></li>';
 +
echo "</li>";
 +
}
 +
?>
 +
</ul>
 +
</syntaxhighlight>
 +
 +
=====Textnavigation mit first/last etc. Klassen=====
 +
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
 +
?>
 +
<ul id="nav-lang" class="nav nav-h">
 +
<?php
 +
$n = $languages->count();
 +
$i = 0;
 +
 +
$separator = '<span class="separator">|</span>';
 +
foreach($languages as $language){
 +
    $liClass = array();
 +
    if(!$page->viewable($language)) continue; // is page viewable in this language?
 +
    $i++;
 +
    if( $i == 1 ) $liClass[] = "first";
 +
    if( $i == $n ) $liClass[] = "last";
 +
    if($language->id == $user->language->id) $liClass[] = 'current';
 +
    echo '<li class="'.implode(' ',$liClass).'">';
 +
$url = $page->localUrl($language);
 +
$hreflang = $pages->get('/')->getLanguageValue($language, 'name');
 +
echo '<a hreflang="'.$hreflang.'" href="'.$url.'" style="text-transform:uppercase;">'.$language->title.'</a></li>';
 +
if( $i < $n ) echo $separator;
 +
    echo "</li>";
 +
}
 +
?>
 +
</ul>
 +
</syntaxhighlight>
 +
 +
=====Flaggennavi=====
 +
z.B. so :
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
 +
?>
 +
<ul id="nav-lang" class="">
 +
<?php
 +
foreach($languages as $language){
 +
if(!$page->viewable($language)) continue; // is page viewable in this language?
 +
if($language->id == $user->language->id) {
 +
 +
echo '<li class="current" style="opacity:0.5;">';
 +
} else {
 +
echo '<li>';
 +
}
 +
$flag = urls()->templates.'assets/flag-'.$language->name.'.png';
 +
$url = $page->localUrl($language);
 +
$hreflang = $pages->get('/')->getLanguageValue($language, 'name');
 +
echo '<a hreflang="'.$hreflang.'" href="'.$url.'"><img class="flag" src="'.$flag.'" style="width: 100px;"></a></li>';
 +
echo '</li>';
 +
}
 +
?>
 +
</ul>
 +
</syntaxhighlight>
 +
 +
===== Language Toggle Schiebeschalter =====
 +
'''PHP-Script für schnelles erstellen eines Schiebeschalters'''
 +
Bezieht sich auf das CSS für den fixed width Schalter
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
/**
 +
* langtoggle.inc
 +
* User is en, show de toggle. User en, show de toggle
 +
* Setze das title Feld der jeweiligen Sprache so wie du die Label haben möchtest
 +
*
 +
* Example SCSS:
 +
* https://wiki.stephanschlegel.de/index.php?title=ProcessWire_-_Multilanguage_Website#4._Language_Switcher
 +
*/
 +
 +
$langtoggle = '';
 +
$user->language->name == 'en' ? $targetlangName = 'default' : $targetlangName = 'en'; //setzt voraus, das die name-Felder der Sprachen en und default sind. default ist immer der name der Standarssprache
 +
 +
foreach($languages as $language){
 +
if(!$page->viewable($language)) continue;
 +
if($language->id == $user->language->id) {
 +
    // button für diese Sprache wird nicht benötigt
 +
    // du könntest hier auch eine gedimmte Version nehmen
 +
  }else{
 +
    // URL der aktuellen Seite für die Zielsprache
 +
    $url = $page->localUrl($language);
 +
    //bd($url, 'langtoggle: target url');
 +
 +
    $langtoggle .= '
 +
    <div class="language-switcher-fixed">
 +
      <a href="'.$url.'" class="toggle-switch '.$language->name.'" title="'.$language->title.'">
 +
        <div class="switch">
 +
          <div class="knob"></div>
 +
          <div class="label">'.$language->title.'</div>
 +
        </div>
 +
      </a>
 +
    </div>
 +
    ';
 +
  }
 +
}
 +
?>
 +
</syntaxhighlight>
 +
 +
'''CSS für fixed width Schiebeschalter mit Parametern'''
 +
<syntaxhighlight lang="scss">
 +
// Toggle Params
 +
$switch-background-color :#006B52;
 +
$switch-background-color-hover: #4a9a14;
 +
$switch-label-color: #fff;
 +
$switch-border-color: rgba(255, 255, 255, 0.642
 +
);
 +
$knob-color: #006B52;
 +
$knob-border-color: transparent;
 +
$knob-background-color: #fff;
 +
$switch-width: 60px; // change this
 +
$switch-border-thickness: 2px; // change this
 +
$knob-gap: 5px; // change this (distance to border)
 +
$switch-outer-width: $switch-width + 2 * $switch-border-thickness; // compensate border space
 +
$switch-height: floor(($switch-width + 2 * $switch-border-thickness) / 2);
 +
$switch-border-radius: ceil($switch-height / 2 + 2 * $switch-border-thickness);
 +
$switch-label-font-size: floor($switch-height / 2);
 +
$switch-label-width: floor($switch-width / 2);
 +
$switch-label-distance: floor($switch-border-radius / 3);
 +
$knob-height: (
 +
floor($switch-width / 2) - ((2 * $knob-gap) + 2px)
 +
);
 +
$knob-width: $knob-height;
 +
 +
/* fixed width */
 +
 +
 +
.language-switcher-fixed {
 +
// display: flex;
 +
// gap: 1rem;
 +
 +
 +
.toggle-switch {
 +
text-decoration: none;
 +
display: inline-block;
 +
 +
.switch {
 +
position: relative;
 +
width: $switch-outer-width;
 +
height: $switch-height;
 +
background-color: $switch-background-color;
 +
border-radius: $switch-border-radius;
 +
border: $switch-border-thickness solid $switch-border-color;
 +
transition: background-color 0.3s ease;
 +
}
 +
 +
.knob {
 +
position: absolute;
 +
top: $knob-gap;
 +
width: $knob-width;
 +
height: $knob-height;
 +
background-color: $knob-background-color;
 +
border-radius: 50%;
 +
border: $switch-border-thickness solid $knob-border-color;
 +
transition: all 0.3s ease;
 +
}
 +
 +
.label {
 +
position: absolute;
 +
top: 50%;
 +
transform: translateY(-50%);
 +
font-size: $switch-label-font-size;
 +
font-weight: bold;
 +
text-transform: uppercase;
 +
color: $switch-label-color;
 +
width: $switch-label-width;
 +
text-align: center;
 +
}
 +
}
 +
 +
/* Default Schalter: Knopf links, Beschriftung rechts */
 +
.toggle-switch.default {
 +
.knob {
 +
left: $knob-gap;
 +
}
 +
 +
.label {
 +
right: $switch-label-distance;
 +
}
 +
}
 +
 +
/* Englischer Schalter: Knopf rechts, Beschriftung links */
 +
.toggle-switch.en {
 +
.knob {
 +
right: $knob-gap;
 +
}
 +
 +
.label {
 +
left: $switch-label-distance;
 +
}
 +
}
 +
 +
/* Hover- und Active-Effekte */
 +
.toggle-switch:hover .switch {
 +
background-color: $switch-background-color-hover;
 +
}
 +
 +
.toggle-switch:active .knob {
 +
transform: scale(0.95);
 +
}
 +
 +
}
 +
</syntaxhighlight>
 +
 +
''' Allgemeiner code (Beispiel mit dynamischer Breite enthalten '''
 +
Siehe auch Codepen "Kholja"
 +
<syntaxhighlight lang="html5">
 +
<h2>Fixed width label</h2>
 +
 +
<div class="language-switcher-fixed">
 +
  <!-- Englisch: Knopf rechts, Beschriftung links -->
 +
  <a href="/en" class="toggle-switch en" title="Wechsel zu Englisch">
 +
    <div class="switch">
 +
      <div class="knob"></div>
 +
      <div class="label">en</div>
 +
    </div>
 +
  </a>
 +
 +
  <!-- Deutsch: Knopf links, Beschriftung rechts -->
 +
  <a href="/de" class="toggle-switch de" title="Wechsel zu Deutsch">
 +
    <div class="switch">
 +
      <div class="knob"></div>
 +
      <div class="label">de</div>
 +
    </div>
 +
  </a>
 +
</div>
 +
 +
<h2>Dynamic width label</h2>
 +
<div class="language-switcher-dynamic">
 +
  <!-- Deutscher Schalter: Knopf links, Label rechts -->
 +
  <a href="/de" class="toggle-switch de" title="Wechsel zu Deutsch">
 +
    <div class="switch">
 +
      <div class="knob"></div>
 +
      <span class="label">Deutsch</span>
 +
    </div>
 +
  </a>
 +
 +
  <!-- Englischer Schalter: Knopf rechts, Label links -->
 +
  <a href="/en" class="toggle-switch en" title="Wechsel zu Englisch">
 +
    <div class="switch">
 +
      <div class="knob"></div>
 +
      <span class="label">English</span>
 +
    </div>
 +
  </a>
 +
</div>
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="scss">
 +
// Toggle Params
 +
$switch-background-color :#006B52;
 +
$switch-background-color-hover: #4a9a14;
 +
$switch-label-color: #fff;
 +
$switch-border-color: rgba(255, 255, 255, 0.642
 +
);
 +
$knob-color: #006B52;
 +
$knob-border-color: transparent;
 +
$knob-background-color: #fff;
 +
$switch-width: 60px; // change this
 +
$switch-border-thickness: 2px; // change this
 +
$knob-gap: 5px; // change this (distance to border)
 +
$switch-outer-width: $switch-width + 2 * $switch-border-thickness; // compensate border space
 +
$switch-height: floor(($switch-width + 2 * $switch-border-thickness) / 2);
 +
$switch-border-radius: ceil($switch-height / 2 + 2 * $switch-border-thickness);
 +
$switch-label-font-size: floor($switch-height / 2);
 +
$switch-label-width: floor($switch-width / 2);
 +
$switch-label-distance: floor($switch-border-radius / 3);
 +
$knob-height: (
 +
floor($switch-width / 2) - ((2 * $knob-gap) + 2px)
 +
);
 +
$knob-width: $knob-height;
 +
 +
/* fixed width */
 +
 +
 +
.language-switcher-fixed {
 +
// display: flex;
 +
// gap: 1rem;
 +
 +
 +
.toggle-switch {
 +
text-decoration: none;
 +
display: inline-block;
 +
 +
.switch {
 +
position: relative;
 +
width: $switch-outer-width;
 +
height: $switch-height;
 +
background-color: $switch-background-color;
 +
border-radius: $switch-border-radius;
 +
border: $switch-border-thickness solid $switch-border-color;
 +
transition: background-color 0.3s ease;
 +
}
 +
 +
.knob {
 +
position: absolute;
 +
top: $knob-gap;
 +
width: $knob-width;
 +
height: $knob-height;
 +
background-color: $knob-background-color;
 +
border-radius: 50%;
 +
border: $switch-border-thickness solid $knob-border-color;
 +
transition: all 0.3s ease;
 +
}
 +
 +
.label {
 +
position: absolute;
 +
top: 50%;
 +
transform: translateY(-50%);
 +
font-size: $switch-label-font-size;
 +
font-weight: bold;
 +
text-transform: uppercase;
 +
color: $switch-label-color;
 +
width: $switch-label-width;
 +
text-align: center;
 +
}
 +
}
 +
 +
/* Default Schalter: Knopf links, Beschriftung rechts */
 +
.toggle-switch.default {
 +
.knob {
 +
left: $knob-gap;
 +
}
 +
 +
.label {
 +
right: $switch-label-distance;
 +
}
 +
}
 +
 +
/* Englischer Schalter: Knopf rechts, Beschriftung links */
 +
.toggle-switch.en {
 +
.knob {
 +
right: $knob-gap;
 +
}
 +
 +
.label {
 +
left: $switch-label-distance;
 +
}
 +
}
 +
 +
/* Hover- und Active-Effekte */
 +
.toggle-switch:hover .switch {
 +
background-color: $switch-background-color-hover;
 +
}
 +
 +
.toggle-switch:active .knob {
 +
transform: scale(0.95);
 +
}
 +
 +
}
 +
</syntaxhighlight>
 +
 +
=== Prantner ===
 +
Hauptnavigation mit Flaggen:
 +
 +
language-switcher.inc
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
$imgMarkup = "";
 +
$out = "";
 +
foreach($languages as $language) {
 +
if(!$page->viewable($language)) continue; // is page viewable in this language?
 +
$url = $page->localUrl($language);
 +
$hreflang = $homepage->getLanguageValue($language, 'name');
 +
$imgUrl = $config->urls->templates.'assets/flags/'.$language->name.'_sq.png';
 +
$imgMarkup = "<img src=\"$imgUrl\" title=\"$language->title\" alt=\"$language->title\" class=\"circle z-depth-1\">";
 +
if($language->id == $user->language->id) {
 +
$out .= "<span class=\"lang-button current\">";
 +
} else {
 +
$out .= "<span class=\"lang-button\">";
 +
}
 +
$out .= "<a hreflang=\"$hreflang\" href=\"$url\">$imgMarkup</a></span>";
 +
}
 +
$out = '<div id="nav-lang">'.$out.'</div>';
 +
echo $out;
 +
?>
 +
</syntaxhighlight>
 +
 +
language-switcher-mobile.inc
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
?>
 +
<ul id="nav-mobile" class="right hide-on-med-and-down">
 +
<?php
 +
foreach($languages as $language) {
 +
if(!$page->viewable($language)) continue; // is page viewable in this language?
 +
if($language->id == $user->language->id) {
 +
echo "<li class='current'>";
 +
} else {
 +
echo "<li>";
 +
}
 +
$url = $page->localUrl($language);
 +
$hreflang = $homepage->getLanguageValue($language, 'name');
 +
echo "<a hreflang='$hreflang' href='$url'>$language->title</a></li>";
 +
}
 +
?>
 +
</ul>
 +
</syntaxhighlight>
 +
 +
== Language Snippets ==
 +
=== URL der Sprache ===
 +
$language = $user->language;
 +
$page->getLanguageValue($language->id, 'url'); // getLanguageValue kann auf verschiedene Werte des language Objekts zugreifen hier auf die 'url' z.B. "/" bei Homepage oder "/en/"
 +
$page->localUrl($language->id); // Kurzform von oberem Beispiel
 +
$page->localHttpUrl($language->id); // Absolute URL z.B. 'https://100.dekra-online.de/en/'
 +
 +
=== Field Label in aktueller Sprache ===
 +
fields($f)->getLabel()
 +
Wobei $f ein Feldname sein kann aber auch ein Feldobjekt.

Aktuelle Version vom 22. März 2025, 17:00 Uhr

Mehrsprachige Websites mit ProcessWire / Andere Default Sprache

Links[Bearbeiten]

Einleitung[Bearbeiten]

Es gibt mehrere Bereiche an die man denken muss. Einmal geht es um die Eingabe im Backend, die Ausgabe im Frontend, die Sprachnavigation auf der Website und die Templates:

  • Wie übersetze ich Text in meinen Templates ? Siehe unten i18n
  • Wie übersetze ich Inhalte im Backend ? Dafür ist das Modul Language Support Fields zuständig
  • Wie sollen meine URLs aussehen ? Prinzipiell kann man jedem User unterschiedliche Sprachen auch ohne andere Domain liefern (über seine Session) aber i.d.R wollen wir die URL anzupassen.
    • domain.de/en/meineSeite oder domain.de/myPage
    • Um Seitennamen zu übersetzen oder ein Domainkürzel in der URL voranzustellen benötige ich das Modul Language Support Page Names

Welche Module benötige ich[Bearbeiten]

Da es einige Module in diesem Zusammenhang gibt hier eine Übersicht. Man findet Sie am besten unter

Modules > Core > Language
  • Languages Support - ProcessWire multi-language support. Basis Modul bracht man für alle Beispiele unten. Reicht aus, wenn man nur die Standard-Sprache ändern will. Hinweis: In der aktuellen PW3 Version schlägt einem ProcessWire nach Installation des Language Support Moduls gleich die Ergänzenden Module (s.u.) vor und man kann den Installationsprozess ziemlich fix erledigen.
  • Languages Support - Fields Required to use multi-language fields. Basis für mehrsprachige Felder im Backend.
  • Languages Support - Page Names (LanguageSupportPageNames) Required to use multi-language page names. Braucht man nur wenn alle Seiten in allen Sprachen unterschiedliche Namen bekommen sollen.
  • Languages Support - Tabs Organizes multi-language fields into tabs for a cleaner easier to use interface.

Für mehrsprachige Seiten benötigen wir im Frontend i.d.R. folgende Module:

  • Language Support Fields - Sind Felder, die im Backend für jede Sprache eine eigene Eingabe bieten.
  • Language Support Page Names benötigt man, damit man für die Sprachen eigene URLs angeben kann. Z.B. bei Home in Englisch /en/ usw.
  • FieldtypePageTitleLanguage benötigt man wenn man alle Seitenamen anpassen will (seite1_de seite1_fr ...) Für einen reinen Sprachpfad (/de/Seite) braucht man das nicht.

Einsprachige Seite aber Deutsch als Default Sprache[Bearbeiten]

Wenn nur die Standardsprache verändern möchte, aber keine Mehrsprachige Seite benötigt brauchen wir nur das Modul Language Support

  • Enable languages support -> Core Module "Language Support" aktivieren. -> Sprachen stehen num im Backend Setup zur Verfügung
  • Titel der Default Sprache anpassen (z.B. Deutsch (default) )
  • Language Pack in der default Sprache installieren -> Dies ist ab jetzt die Default Sprache. Nicht vergessen auch den lang Tag im Header zu setzen, damit der Browser die Sprache richtig erkennt.

Sprachpakete installieren[Bearbeiten]

https://processwire.com/modules/category/language-pack/
  • Sprache auswählen und dort komplettes zip hochladen.
  • Informell (DU) leider im Moment nicht vorhanden

Basis-Module für Mehrsprachigkeit im Backend[Bearbeiten]

Für mehrsprachige Seiten benötigen wir i.d.R. folgende Module:

  • Language Support Fields für die Backend Übersetzungen und Language Support Page Names für die URLs.
  • FieldtypePageTitleLanguage benötigt man wenn man alle Seitenamen anpassen will (seite1_de seite1_fr ...) Für einen reinen Sprachpfad (/de/Seite) braucht man das nicht.
  • Für weitere Sprachen entsprechend hinzufügen.

Vorgehen:

  • Language Packs installieren: drop in the none english language pack (for admin backend) into the default language, (e.g. german langpack)
  • As a nice sideeffect every new user in your system gets the native language per default without have it to select from the list.

Templates für Multilanguage vorbereiten (i18n)[Bearbeiten]

https://processwire.com/docs/multi-language-support/code-i18n/
https://processwire.com/blog/posts/functional-fields/

Functional fields[Bearbeiten]

In PW3 kamen die functional Fields hinzu. Mit diesen kann man statischen Text dynamisch im Page Editor ansprechen. D.h. das Functional Field findet Texte im Template und macht sie automatisch editierbar im Page Editor. Das Ganze funktioniert auch Mehrsprachig.

ProcessWire - Functional Fields
https://processwire.com/blog/posts/functional-fields/

Beispiele für die Ausgabe von

__text('your text');
__textarea('your text');
__richtext('<p>your text</p>'); 
__text('Subscribe Now', 'subscribe') // define a identifier for this text snippet...
__text('subscribe') // ..reuse it this way
$pages->get('/')->mytext->subscribe // reuse from another template
__text('Subscribe Now', 'subscribe', 'Submit button'); // Label for page editor
__text('Subscribe Now', 'subscribe', 'label=Submit button, notes=Test'); // or use a pw selector
__text('Subscribe Now', 'name=subscribe, label=Submit button, notes=Test'); // equivalent to upper

Standard Multilanguage nach i18n[Bearbeiten]

$out = $this->_("Live long and prosper");  // syntax within a class
$out = __("Live long and prosper!"); // syntax outside of a class

Dann im Backend unter der Sprache "Find files to translate" und die Template Datei auswählen.

Variablen in i18n[Bearbeiten]

$out = sprintf(__("Created %d pages."), $count); 
$out = sprintf(__('Your city is %1$s, and your zip code is %2$s.'), $city, $zipcode);

Plural in Multilanguage Files[Bearbeiten]

Hierzu gibt es die _n() Funktion

$out = sprintf(_n("Created %d page.", "Created %d pages.", $count), $count);

Unterschiedliche Übersetzungen bei gleichem Wortlaut[Bearbeiten]

Manchmal muss der Begriff in anderen Sprachen unterschiedlich übersetzt werden, obwohl er in der Default Sprache gleich lautet:

$label = _x('Comment', 'noun'); // or $this->_x('Comment', 'noun') in a class
...
// some other place in the code
echo _x('Comment', 'column name');

Kommentare für den Übersetzer und User[Bearbeiten]

$date = __('g:i:s a'); // Date string in PHP date() format
echo __("Welcome Guest"); // Headline for guest user // Keep it short (2-3 words)

Regeln[Bearbeiten]

  • Eine Zeile ein Paar Anführungszeichen
  • Nur eine Übersetzungsfunktion pro Zeile

Language Switcher[Bearbeiten]

// remember what language is set to
$savedLanguage = $user->language;

foreach($languages as $language) {

  // if user is already viewing the page in this language, skip it
  if($language->id == $savedLanguage->id) continue;

  // if this page isn't viewable (active) for the language, skip it
  if(!$page->viewable($language)) continue;

  // set the user's language, so that the $page->url and any other
  // fields we access from it will be reflective of the $language
  $user->language = $language;

  // output a link to this page in the other language
  echo "<li><a href='$page->url'>$language->title: $page->title</a></li>";
}
// restore the original language setting
$user->language = $savedLanguage;

Seiten nur in einer Sprache verfügbar[Bearbeiten]

What If I want to create/publish a page only in DE language, and that page should not be available in the default language? Default language is required. But you could always add your own checkbox field to the page as a toggle to disable it. Your head.inc or _init.php or whatever your common initialization file is could check:

if($page->disable_default_language && $user->language->isDefault()) throw new Wire404Exception(); 

You'd also have to consider it with navigation generation, perhaps skipping over pages that have the toggle set while in the default language, or adding it to your selectors when querying pages.

Edit: you could also just choose to not use the default language at all.

if($user->language->isDefault()) $user->language = $languages->get("en-us"); // or whatever you want your default to be

Language Alternate Fields[Bearbeiten]

Eine Möglichkeit alle Felder (auch Bilder) in verschiedenen Sprachen zu nutzen.

https://processwire.com/docs/multi-language-support/multi-language-fields/#language-alternate-fields

Probleme lösen[Bearbeiten]

Feldtyp nicht als Multilanguagefeld vorhanden - Language Alternate Field[Bearbeiten]

Manche Felder (z.B. AssistedUrl) gibt es nur einsprachig. ProcessWire bietet aber mit den Language Alternate Fields eine Möglichkeit solche Felder mehrsprachig zu nutzen. Dazu braucht man kein Modul. Es ist eine Basis Funktionalität.

Dazu legt man für jede zusätzliche Sprache ein weiteres Feld mit dem selben Namen + der Namenserweiterung _sprachname an. Beispielsweise kann man für ein Feld Namens link ein weiteres Feld Namens link_en anlegen. Dann nutzt ProcessWire automatisch für die Sprache mit dem Namen en

Beispiele[Bearbeiten]

Multilanguage Page - Quickstart[Bearbeiten]

1. Module[Bearbeiten]

  • s.o. alle benötigten installieren

2. Backend[Bearbeiten]

  • Default Sprache festlegen
    • Wenn nicht Englisch Sprachpaket installieren
    • Wenn der Titel der Sprache auch der Identifier für den html Tag sein soll muss er de, en, fi... lauten
  • Weitere Sprachen hinzufügen. Für Englisch benötigt man kein Sprachpaket. Als Name am besten den offiziellen Code (de, en...) vergeben.
  • Die Homepage entscheidet über den Pfad. Wenn Englisch z.B. unter www.meineSeite.com/en/seitenname/ erreichbar sein soll, dann muss für Englisch unter Einstellung > Namen en eingetragen werden.
  • Alle Felder die Übersetzt werden sollen auf Multilanguage Felder umstellen

3. Templates[Bearbeiten]

Lang Attribute[Bearbeiten]

Das lang Attribut sollte zur Sprache passen.

Möglichkeit 1:

Mit der _x Funktion kann PW beliebige Strings in Templates übersetzten. PW findet diese automatisch. _main.php (oder header..)

<html lang="<?php echo _x('en', 'HTML language code'); ?>">

Im Backend muss man zunächst für Englisch den Sprachindex aufbauen (Spracheinstellungen Verwaltung > Sprachen > Englisch)

Dann kann man nun in den Spracheinstellungen Verwaltung > Sprachen > meineSprache das Label HTML language code suchen und mit dem passenden lang tag ersetzen.

Das Funktioniert auch mit beliebigen anderen Werten die man im Template hartkodiert hat.

Möglichkeit 2 (bevorzugt weil schnell):

Man kann auch den Language Title verwenden wenn dieser entsprechend vergeben wurde (en, de,...) .

Nachteil: Dann kann man aber den Titel nicht mehr frei verändern wenn man ihn auch als Bezeichnung für den Language Switcher nutezn möchte. Der Titel für default heißt dann z.B. de und zwar auch in der englischen Übersetzung. Also nicht in der Übersetzung "german" schreiben sondern auch de oder einfach gar nichts.

<html lang="<?= $user->language->title ?>">

Wenn du trotzdem irgendwelche ausgeschriebenen Label benötigst kannst du dir von Hand Variablen definieren und Übersetzen (z.B. mit der Übersetzungsfunktion __('de') oder_x('de', 'Label für deutsch');

4. Language Switcher[Bearbeiten]

Text Navigation z.B. so:

<?php namespace ProcessWire;

?>
<ul id="nav-lang" class="nav nav-h">
<?php
foreach($languages as $language){
	if(!$page->viewable($language)) continue; // is page viewable in this language?
	if($language->id == $user->language->id) {
		echo "<li class='current'>";
	} else {
		echo "<li>";
	}
	$url = $page->localUrl($language);
	$hreflang = $pages->get('/')->getLanguageValue($language, 'name');
	echo '<a hreflang="'.$hreflang.'" href="'.$url.'" style="text-transform:uppercase;">'.$language->title.'</a></li>';
	echo "</li>";
}
?>
</ul>
Textnavigation mit first/last etc. Klassen[Bearbeiten]
<?php namespace ProcessWire;

?>
<ul id="nav-lang" class="nav nav-h">
<?php
$n = $languages->count();
$i = 0;

$separator = '<span class="separator">|</span>';
foreach($languages as $language){
    $liClass = array();
    if(!$page->viewable($language)) continue; // is page viewable in this language?
    $i++;
    if( $i == 1 ) $liClass[] = "first";
    if( $i == $n ) $liClass[] = "last";
    if($language->id == $user->language->id) $liClass[] = 'current';
    echo '<li class="'.implode(' ',$liClass).'">';
	$url = $page->localUrl($language);
	$hreflang = $pages->get('/')->getLanguageValue($language, 'name');
	echo '<a hreflang="'.$hreflang.'" href="'.$url.'" style="text-transform:uppercase;">'.$language->title.'</a></li>';
	if( $i < $n ) echo $separator;
    echo "</li>";
}
?>
</ul>
Flaggennavi[Bearbeiten]

z.B. so :

<?php namespace ProcessWire;

?>
<ul id="nav-lang" class="">
<?php
foreach($languages as $language){
	if(!$page->viewable($language)) continue; // is page viewable in this language?
	if($language->id == $user->language->id) {

		echo '<li class="current" style="opacity:0.5;">';
	} else {
		echo '<li>';
	}
	$flag = urls()->templates.'assets/flag-'.$language->name.'.png';
	$url = $page->localUrl($language);
	$hreflang = $pages->get('/')->getLanguageValue($language, 'name');
	echo '<a hreflang="'.$hreflang.'" href="'.$url.'"><img class="flag" src="'.$flag.'" style="width: 100px;"></a></li>';
	echo '</li>';
}
?>
</ul>
Language Toggle Schiebeschalter[Bearbeiten]

PHP-Script für schnelles erstellen eines Schiebeschalters Bezieht sich auf das CSS für den fixed width Schalter

<?php namespace ProcessWire;
/**
 * langtoggle.inc
 * User is en, show de toggle. User en, show de toggle
 * Setze das title Feld der jeweiligen Sprache so wie du die Label haben möchtest
 * 
 * Example SCSS:
 * https://wiki.stephanschlegel.de/index.php?title=ProcessWire_-_Multilanguage_Website#4._Language_Switcher
 */

$langtoggle = '';
$user->language->name == 'en' ? $targetlangName = 'default' : $targetlangName = 'en'; //setzt voraus, das die name-Felder der Sprachen en und default sind. default ist immer der name der Standarssprache

foreach($languages as $language){
	if(!$page->viewable($language)) continue; 
	if($language->id == $user->language->id) {
    // button für diese Sprache wird nicht benötigt
    // du könntest hier auch eine gedimmte Version nehmen
  }else{
    // URL der aktuellen Seite für die Zielsprache
    $url = $page->localUrl($language);
    //bd($url, 'langtoggle: target url');

    $langtoggle .= '
    <div class="language-switcher-fixed">
      <a href="'.$url.'" class="toggle-switch '.$language->name.'" title="'.$language->title.'">
        <div class="switch">
          <div class="knob"></div>
          <div class="label">'.$language->title.'</div>
        </div>
      </a>
    </div>
    ';
  }
}
?>

CSS für fixed width Schiebeschalter mit Parametern

// Toggle Params
$switch-background-color :#006B52;
$switch-background-color-hover: #4a9a14;
$switch-label-color: #fff;
$switch-border-color: rgba(255, 255, 255, 0.642
);
$knob-color: #006B52;
$knob-border-color: transparent;
$knob-background-color: #fff;
$switch-width: 60px; // change this
$switch-border-thickness: 2px; // change this
$knob-gap: 5px; // change this (distance to border)
$switch-outer-width: $switch-width + 2 * $switch-border-thickness; // compensate border space
$switch-height: floor(($switch-width + 2 * $switch-border-thickness) / 2);
$switch-border-radius: ceil($switch-height / 2 + 2 * $switch-border-thickness);
$switch-label-font-size: floor($switch-height / 2);
$switch-label-width: floor($switch-width / 2);
$switch-label-distance: floor($switch-border-radius / 3);
$knob-height: (
	floor($switch-width / 2) - ((2 * $knob-gap) + 2px)
);
$knob-width: $knob-height;

/* fixed width */


.language-switcher-fixed {
	// display: flex;
	// gap: 1rem;


	.toggle-switch {
		text-decoration: none;
		display: inline-block;

		.switch {
			position: relative;
			width: $switch-outer-width;
			height: $switch-height;
			background-color: $switch-background-color;
			border-radius: $switch-border-radius;
			border: $switch-border-thickness solid $switch-border-color;
			transition: background-color 0.3s ease;
		}

		.knob {
			position: absolute;
			top: $knob-gap;
			width: $knob-width;
			height: $knob-height;
			background-color: $knob-background-color;
			border-radius: 50%;
			border: $switch-border-thickness solid $knob-border-color;
			transition: all 0.3s ease;
		}

		.label {
			position: absolute;
			top: 50%;
			transform: translateY(-50%);
			font-size: $switch-label-font-size;
			font-weight: bold;
			text-transform: uppercase;
			color: $switch-label-color;
			width: $switch-label-width;
			text-align: center;
		}
	}

	/* Default Schalter: Knopf links, Beschriftung rechts */
	.toggle-switch.default {
		.knob {
			left: $knob-gap;
		}

		.label {
			right: $switch-label-distance;
		}
	}

	/* Englischer Schalter: Knopf rechts, Beschriftung links */
	.toggle-switch.en {
		.knob {
			right: $knob-gap;
		}

		.label {
			left: $switch-label-distance;
		}
	}

	/* Hover- und Active-Effekte */
	.toggle-switch:hover .switch {
		background-color: $switch-background-color-hover;
	}

	.toggle-switch:active .knob {
		transform: scale(0.95);
	}

}

Allgemeiner code (Beispiel mit dynamischer Breite enthalten Siehe auch Codepen "Kholja"

<h2>Fixed width label</h2>

<div class="language-switcher-fixed">
  <!-- Englisch: Knopf rechts, Beschriftung links -->
  <a href="/en" class="toggle-switch en" title="Wechsel zu Englisch">
    <div class="switch">
      <div class="knob"></div>
      <div class="label">en</div>
    </div>
  </a>

  <!-- Deutsch: Knopf links, Beschriftung rechts -->
  <a href="/de" class="toggle-switch de" title="Wechsel zu Deutsch">
    <div class="switch">
      <div class="knob"></div>
      <div class="label">de</div>
    </div>
  </a>
</div>

<h2>Dynamic width label</h2>
<div class="language-switcher-dynamic">
  <!-- Deutscher Schalter: Knopf links, Label rechts -->
  <a href="/de" class="toggle-switch de" title="Wechsel zu Deutsch">
    <div class="switch">
      <div class="knob"></div>
      <span class="label">Deutsch</span>
    </div>
  </a>

  <!-- Englischer Schalter: Knopf rechts, Label links -->
  <a href="/en" class="toggle-switch en" title="Wechsel zu Englisch">
    <div class="switch">
      <div class="knob"></div>
      <span class="label">English</span>
    </div>
  </a>
</div>
// Toggle Params
$switch-background-color :#006B52;
$switch-background-color-hover: #4a9a14;
$switch-label-color: #fff;
$switch-border-color: rgba(255, 255, 255, 0.642
);
$knob-color: #006B52;
$knob-border-color: transparent;
$knob-background-color: #fff;
$switch-width: 60px; // change this
$switch-border-thickness: 2px; // change this
$knob-gap: 5px; // change this (distance to border)
$switch-outer-width: $switch-width + 2 * $switch-border-thickness; // compensate border space
$switch-height: floor(($switch-width + 2 * $switch-border-thickness) / 2);
$switch-border-radius: ceil($switch-height / 2 + 2 * $switch-border-thickness);
$switch-label-font-size: floor($switch-height / 2);
$switch-label-width: floor($switch-width / 2);
$switch-label-distance: floor($switch-border-radius / 3);
$knob-height: (
	floor($switch-width / 2) - ((2 * $knob-gap) + 2px)
);
$knob-width: $knob-height;

/* fixed width */


.language-switcher-fixed {
	// display: flex;
	// gap: 1rem;


	.toggle-switch {
		text-decoration: none;
		display: inline-block;

		.switch {
			position: relative;
			width: $switch-outer-width;
			height: $switch-height;
			background-color: $switch-background-color;
			border-radius: $switch-border-radius;
			border: $switch-border-thickness solid $switch-border-color;
			transition: background-color 0.3s ease;
		}

		.knob {
			position: absolute;
			top: $knob-gap;
			width: $knob-width;
			height: $knob-height;
			background-color: $knob-background-color;
			border-radius: 50%;
			border: $switch-border-thickness solid $knob-border-color;
			transition: all 0.3s ease;
		}

		.label {
			position: absolute;
			top: 50%;
			transform: translateY(-50%);
			font-size: $switch-label-font-size;
			font-weight: bold;
			text-transform: uppercase;
			color: $switch-label-color;
			width: $switch-label-width;
			text-align: center;
		}
	}

	/* Default Schalter: Knopf links, Beschriftung rechts */
	.toggle-switch.default {
		.knob {
			left: $knob-gap;
		}

		.label {
			right: $switch-label-distance;
		}
	}

	/* Englischer Schalter: Knopf rechts, Beschriftung links */
	.toggle-switch.en {
		.knob {
			right: $knob-gap;
		}

		.label {
			left: $switch-label-distance;
		}
	}

	/* Hover- und Active-Effekte */
	.toggle-switch:hover .switch {
		background-color: $switch-background-color-hover;
	}

	.toggle-switch:active .knob {
		transform: scale(0.95);
	}

}

Prantner[Bearbeiten]

Hauptnavigation mit Flaggen:

language-switcher.inc

<?php namespace ProcessWire;
$imgMarkup = "";
$out = "";
foreach($languages as $language) {
	if(!$page->viewable($language)) continue; // is page viewable in this language?
	$url = $page->localUrl($language);
	$hreflang = $homepage->getLanguageValue($language, 'name');
	$imgUrl = $config->urls->templates.'assets/flags/'.$language->name.'_sq.png';
	$imgMarkup = "<img src=\"$imgUrl\" title=\"$language->title\" alt=\"$language->title\" class=\"circle z-depth-1\">";
	if($language->id == $user->language->id) {
		$out .= "<span class=\"lang-button current\">";
	} else {
		$out .= "<span class=\"lang-button\">";
	}
	$out .= "<a hreflang=\"$hreflang\" href=\"$url\">$imgMarkup</a></span>";
}
$out = '<div id="nav-lang">'.$out.'</div>';
echo $out; 
?>

language-switcher-mobile.inc

<?php namespace ProcessWire;
?>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<?php
	foreach($languages as $language) {
		if(!$page->viewable($language)) continue; // is page viewable in this language?
		if($language->id == $user->language->id) {
			echo "<li class='current'>";
		} else {
			echo "<li>";
		}
		$url = $page->localUrl($language);
		$hreflang = $homepage->getLanguageValue($language, 'name');
		echo "<a hreflang='$hreflang' href='$url'>$language->title</a></li>";
	}
?>
</ul>

Language Snippets[Bearbeiten]

URL der Sprache[Bearbeiten]

$language = $user->language;

$page->getLanguageValue($language->id, 'url'); // getLanguageValue kann auf verschiedene Werte des language Objekts zugreifen hier auf die 'url' z.B. "/" bei Homepage oder "/en/"
$page->localUrl($language->id); // Kurzform von oberem Beispiel
$page->localHttpUrl($language->id); // Absolute URL z.B. 'https://100.dekra-online.de/en/'

Field Label in aktueller Sprache[Bearbeiten]

fields($f)->getLabel()

Wobei $f ein Feldname sein kann aber auch ein Feldobjekt.