ProcessWire - Multilanguage Website

Aus Wikizone
Wechseln zu: Navigation, Suche

Mehrsprachige Websites mit ProcessWire / Andere Default Sprache

Links

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
  • 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

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.

Mehrere Sprachen

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)

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

__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 ===

 $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 ===
 $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===
Hierzu gibt es die _n() Funktion
 $out = sprintf(_n("Created %d page.", "Created %d pages.", $count), $count);
=== Unterschiedliche Übersetzungen bei gleichem Wortlaut ===
Manchmal muss der Begriff in anderen Sprachen unterschiedlich übersetzt werden, obwohl er in der Default Sprache gleich lautet:
<pre>
$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

$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

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

Language Switcher

// 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

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

Probleme lösen

Feldtyp nicht als Multilanguagefeld vorhanden

Manche Felder (z.B. AssistedUrl) gibt es nur einsprachig. ProcessWire bietet aber mit Language Alternate Fields eine Möglichkeit solche Felder mehrsprachig zu nutzen. 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 allgemeines Vorgehen

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

Das lang Attribut sollte zur Sprache passen. 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.

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.

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

Dies hat bei mir nicht funktioniert:

<? $lang = $pages->get(1)->getLanguageValue($user->language, 'name'); ?>
<html lang="<?php echo $lang ?>">

Hier wird einfach der Name der Sprache die der Benutzer im Moment hat (Session) ausgegeben. Der Name der Sprache sollte im Backend entsprechend der Norm gewählt sein. (de, it, fi...). Problem war das man den Namen der default Sprache nicht vergeben kann.

4. Language Switcher

Für Text Navigation 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'>";
	} 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>

Flaggennavi 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>

Prantner

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>