|
| 1 | +--- |
| 2 | +title: Wie man mit Polyglot mehrsprachige Unterstützung für einen Jekyll-Blog implementiert (1) - Anwendung des Polyglot-Plugins & Implementierung von hreflang alt-Tags, Sitemap und Sprachauswahl-Button |
| 3 | +description: >- |
| 4 | + Dieser Beitrag beschreibt den Prozess der Implementierung mehrsprachiger Unterstützung für einen Jekyll-Blog basierend auf dem 'jekyll-theme-chirpy' Theme unter Verwendung des Polyglot-Plugins. |
| 5 | + Als erster Teil der Serie behandelt dieser Post die Anwendung des Polyglot-Plugins und die Modifikation des HTML-Headers und der Sitemap. |
| 6 | +categories: |
| 7 | +- Blogging |
| 8 | +tags: |
| 9 | +- Jekyll |
| 10 | +- Polyglot |
| 11 | +--- |
| 12 | +## Überblick |
| 13 | +Vor etwa 4 Monaten, Anfang Juli 2024, habe ich meinem Jekyll-basierten Blog, der über Github Pages gehostet wird, mehrsprachige Unterstützung hinzugefügt, indem ich das [Polyglot](https://github.com/untra/polyglot)-Plugin implementiert habe. |
| 14 | +Diese Serie teilt die Erfahrungen mit Bugs, die während der Anwendung des Polyglot-Plugins auf das Chirpy-Theme auftraten, deren Lösungen, sowie Methoden zum Schreiben von HTML-Headern und sitemap.xml unter Berücksichtigung der SEO. |
| 15 | +Die Serie besteht aus zwei Beiträgen, und dieser Beitrag ist der erste Teil der Serie. |
| 16 | +- Teil 1: Anwendung des Polyglot-Plugins & Implementierung von hreflang alt-Tags, Sitemap und Sprachauswahl-Button (dieser Beitrag) |
| 17 | +- Teil 2: [Fehlerbehebung bei Build-Fehlern des Chirpy-Themes und Suchfunktionsproblemen](/posts/how-to-support-multi-language-on-jekyll-blog-with-polyglot-2) |
| 18 | + |
| 19 | +## Anforderungen |
| 20 | +- [x] Das gebaute Ergebnis (Webseite) sollte in sprachspezifischen Pfaden (z.B. `/posts/de/`{: .filepath}, `/posts/ja/`{: .filepath}) bereitgestellt werden können. |
| 21 | +- [x] Um den zusätzlichen Zeit- und Arbeitsaufwand für die mehrsprachige Unterstützung zu minimieren, sollte die Sprache beim Build automatisch anhand des lokalen Pfads der originalen Markdown-Datei (z.B. `/_posts/de/`{: .filepath}, `/_posts/ja/`{: .filepath}) erkannt werden, ohne dass 'lang' und 'permalink' Tags im YAML-Frontmatter der Markdown-Datei manuell spezifiziert werden müssen. |
| 22 | +- [x] Der Header-Teil jeder Seite der Website sollte angemessene Content-Language Meta-Tags und hreflang Alternativ-Tags enthalten, um die SEO-Richtlinien für die Google-Mehrsprachensuche zu erfüllen. |
| 23 | +- [x] Die `sitemap.xml` sollte alle Links zu den mehrsprachigen Seiten der Website ohne Auslassungen bereitstellen, und die `sitemap.xml` selbst sollte nur einmal im Root-Verzeichnis existieren, ohne Duplikate. |
| 24 | +- [x] Alle vom [Chirpy-Theme](https://github.com/cotes2020/jekyll-theme-chirpy) bereitgestellten Funktionen sollten auf jeder Sprachseite normal funktionieren, andernfalls müssen sie entsprechend angepasst werden. |
| 25 | + - [x] Normale Funktion von 'Recently Updated' und 'Trending Tags' |
| 26 | + - [x] Keine Fehler während des Build-Prozesses mit GitHub Actions |
| 27 | + - [x] Normale Funktion der Beitragssuche in der oberen rechten Ecke des Blogs |
| 28 | + |
| 29 | +## Anwendung des Polyglot-Plugins |
| 30 | +Da Jekyll standardmäßig keine mehrsprachigen Blogs unterstützt, ist die Verwendung eines externen Plugins erforderlich, um einen mehrsprachigen Blog zu implementieren, der die oben genannten Anforderungen erfüllt. Nach einiger Recherche stellte sich heraus, dass [Polyglot](https://github.com/untra/polyglot) häufig für die Implementierung mehrsprachiger Websites verwendet wird und die meisten der oben genannten Anforderungen erfüllen kann, weshalb ich mich für dieses Plugin entschieden habe. |
| 31 | + |
| 32 | +### Plugin-Installation |
| 33 | +Da ich Bundler verwende, habe ich Folgendes zur `Gemfile` hinzugefügt: |
| 34 | + |
| 35 | +```ruby |
| 36 | +group :jekyll_plugins do |
| 37 | + gem "jekyll-polyglot" |
| 38 | +end |
| 39 | +``` |
| 40 | +{: file='Gemfile'} |
| 41 | + |
| 42 | +Anschließend wird die Installation automatisch abgeschlossen, wenn man `bundle update` im Terminal ausführt. |
| 43 | + |
| 44 | +Wenn man Bundler nicht verwendet, kann man das Gem auch direkt mit dem Befehl `gem install jekyll-polyglot` im Terminal installieren und dann das Plugin wie folgt zu `_config.yml` hinzufügen: |
| 45 | + |
| 46 | +```yml |
| 47 | +plugins: |
| 48 | + - jekyll-polyglot |
| 49 | +``` |
| 50 | +{: file='_config.yml'} |
| 51 | +
|
| 52 | +### Konfiguration |
| 53 | +Als Nächstes öffnet man die Datei `_config.yml` und fügt Folgendes hinzu: |
| 54 | + |
| 55 | +```yml |
| 56 | +# Polyglot Settings |
| 57 | +languages: ["en", "ko", "es", "pt-BR", "ja", "fr", "de"] |
| 58 | +default_lang: "en" |
| 59 | +exclude_from_localization: ["javascript", "images", "css", "public", "assets", "sitemap"] |
| 60 | +parallel_localization: false |
| 61 | +lang_from_path: true |
| 62 | +``` |
| 63 | +{: file='_config.yml'} |
| 64 | + |
| 65 | +- languages: Liste der zu unterstützenden Sprachen |
| 66 | +- default_lang: Standard-Fallback-Sprache |
| 67 | +- exclude_from_localization: Reguläre Ausdrücke für Root-Datei-/Ordnerpfade, die von der Lokalisierung ausgeschlossen werden sollen |
| 68 | +- parallel_localization: Boolescher Wert, der angibt, ob die mehrsprachige Verarbeitung während des Build-Prozesses parallelisiert werden soll |
| 69 | +- lang_from_path: Boolescher Wert; wenn auf 'true' gesetzt, wird die Sprache automatisch aus dem Pfadstring der Markdown-Datei erkannt, wenn dieser einen Sprachcode enthält, ohne dass das 'lang'-Attribut im YAML-Frontmatter der Markdown-Datei explizit angegeben werden muss |
| 70 | + |
| 71 | +> Das [offizielle Dokument des Sitemap-Protokolls](https://www.sitemaps.org/protocol.html#location) besagt Folgendes: |
| 72 | +> |
| 73 | +>> "Der Standort einer Sitemap-Datei bestimmt die Menge der URLs, die in dieser Sitemap enthalten sein können. Eine Sitemap-Datei, die sich unter http://example.com/catalog/sitemap.xml befindet, kann alle URLs enthalten, die mit http://example.com/catalog/ beginnen, aber keine URLs, die mit http://example.com/images/ beginnen." |
| 74 | +> |
| 75 | +>> "Es wird dringend empfohlen, Ihre Sitemap im Stammverzeichnis Ihres Webservers zu platzieren." |
| 76 | +> |
| 77 | +> Um dies einzuhalten, sollte 'sitemap' zur Liste 'exclude_from_localization' hinzugefügt werden, damit nicht für jede Sprache eine separate `sitemap.xml`-Datei mit identischem Inhalt erstellt wird, sondern nur eine einzige im Stammverzeichnis existiert. So wird vermieden, dass es wie im folgenden falschen Beispiel aussieht. |
| 78 | +> |
| 79 | +> Falsches Beispiel (der Inhalt jeder Datei ist für alle Sprachen identisch): |
| 80 | +> - /sitemap.xml |
| 81 | +> - /ko/sitemap.xml |
| 82 | +> - /es/sitemap.xml |
| 83 | +> - /pt-BR/sitemap.xml |
| 84 | +> - /ja/sitemap.xml |
| 85 | +> - /fr/sitemap.xml |
| 86 | +> - /de/sitemap.xml |
| 87 | +{: .prompt-tip } |
| 88 | + |
| 89 | +> Wenn 'parallel_localization' auf 'true' gesetzt wird, kann die Build-Zeit erheblich verkürzt werden. Allerdings gab es zum Stand Juli 2024 für diesen Blog einen Bug, bei dem die Linktitel im 'Recently Updated' und 'Trending Tags' Bereich der rechten Seitenleiste nicht korrekt verarbeitet wurden und sich mit anderen Sprachen vermischten, wenn diese Funktion aktiviert war. Es scheint noch nicht vollständig stabilisiert zu sein, daher sollte man vor der Anwendung auf der eigenen Seite testen, ob es ordnungsgemäß funktioniert. Außerdem [wird diese Funktion unter Windows nicht unterstützt und sollte daher deaktiviert werden](https://github.com/untra/polyglot?tab=readme-ov-file#compatibility). |
| 90 | +{: .prompt-warning } |
| 91 | + |
| 92 | +Zusätzlich [muss in Jekyll 4.0 die Generierung von CSS-Sourcemaps wie folgt deaktiviert werden](https://github.com/untra/polyglot?tab=readme-ov-file#compatibility): |
| 93 | + |
| 94 | +```yml |
| 95 | +sass: |
| 96 | + sourcemap: never # In Jekyll 4.0 , SCSS source maps will generate improperly due to how Polyglot operates |
| 97 | +``` |
| 98 | +{: file='_config.yml'} |
| 99 | + |
| 100 | +### Zu beachtende Punkte beim Verfassen von Beiträgen |
| 101 | +Beim Verfassen mehrsprachiger Beiträge sollte man Folgendes beachten: |
| 102 | +- Korrekte Sprachcode-Zuweisung: Der entsprechende ISO-Sprachcode sollte entweder über den Dateipfad (z.B. `/_posts/de/example-post.md`{: .filepath}) oder über das 'lang'-Attribut im YAML-Frontmatter (z.B. `lang: de`) zugewiesen werden. Beispiele finden Sie in der [Chrome-Entwicklerdokumentation](https://developer.chrome.com/docs/extensions/reference/api/i18n#locales). |
| 103 | + |
| 104 | +> Beachten Sie jedoch, dass in der [Chrome-Entwicklerdokumentation](https://developer.chrome.com/docs/extensions/reference/api/i18n#locales) Regionscodes im Format 'pt_BR' angegeben werden, aber tatsächlich sollte '_' durch '-' ersetzt werden, also 'pt-BR', damit später die hreflang-Alternativ-Tags im HTML-Header korrekt funktionieren. |
| 105 | + |
| 106 | +- Dateipfade und -namen sollten konsistent sein. |
| 107 | + |
| 108 | +Weitere Details finden Sie in der [README des GitHub untra/polyglot Repositories](https://github.com/untra/polyglot?tab=readme-ov-file#how-to-use-it). |
| 109 | + |
| 110 | +## Modifikation des HTML-Headers und der Sitemap |
| 111 | +Nun müssen für SEO-Zwecke Content-Language Meta-Tags und hreflang Alternativ-Tags in den HTML-Header jeder Seite des Blogs eingefügt werden. |
| 112 | + |
| 113 | +### HTML-Header |
| 114 | +In der neuesten Version 1.8.1 (Stand November 2024) bietet Polyglot eine Funktion, die diese Aufgabe automatisch erledigt, wenn der Liquid-Tag {% raw %}`{% I18n_Headers %}`{% endraw %} im Header-Bereich der Seite aufgerufen wird. |
| 115 | +Dies setzt jedoch voraus, dass für die betreffende Seite ein 'permalink'-Attribut-Tag explizit angegeben wurde, andernfalls funktioniert es nicht ordnungsgemäß. |
| 116 | + |
| 117 | +Daher habe ich [head.html aus dem Chirpy-Theme](https://github.com/cotes2020/jekyll-theme-chirpy/blob/v7.1.1/_includes/head.html) übernommen und den Inhalt wie folgt direkt ergänzt. |
| 118 | +Ich habe mich an der [SEO Recipes Seite des offiziellen Polyglot-Blogs](https://polyglot.untra.io/seo/) orientiert, aber modifiziert, um `page.url` anstelle von `page.permalink` zu verwenden, wenn `page.permalink` nicht vorhanden ist. |
| 119 | +Außerdem habe ich unter Bezugnahme auf die [offizielle Google Search Central Dokumentation](https://developers.google.com/search/docs/specialty/international/localized-versions#xdefault) `x-default` anstelle von `site.default_lang` als hreflang-Attributwert für die Standardsprachseite der Website festgelegt, damit dieser Seitenlink als Fallback erkannt wird, wenn die bevorzugte Sprache des Besuchers nicht in der Liste der unterstützten Sprachen der Website enthalten ist oder wenn die bevorzugte Sprache des Besuchers nicht erkannt werden kann. |
| 120 | + |
| 121 | +{% raw %} |
| 122 | +```liquid |
| 123 | + <meta http-equiv="Content-Language" content="{{site.active_lang}}"> |
| 124 | +
|
| 125 | + {% if site.default_lang %}<link rel="alternate" hreflang="x-default" href="{{site.url}}{{page.url}}" />{% endif %} |
| 126 | + {% for lang in site.languages %}{% if lang == site.default_lang %}{% continue %}{% endif %} |
| 127 | + <link rel="alternate" hreflang="{{lang}}" href="{{site.url}}/{{lang}}{{page.url}}" /> |
| 128 | + {% endfor %} |
| 129 | +``` |
| 130 | +{: file='/_includes/head.html'} |
| 131 | +{% endraw %} |
| 132 | + |
| 133 | +### Sitemap |
| 134 | +Da die von Jekyll beim Build automatisch generierte Sitemap mehrsprachige Seiten nicht korrekt unterstützt, erstellen Sie eine `sitemap.xml`-Datei im Root-Verzeichnis und fügen Sie folgenden Inhalt ein: |
| 135 | + |
| 136 | +{% raw %} |
| 137 | +```liquid |
| 138 | +--- |
| 139 | +layout: content |
| 140 | +--- |
| 141 | +<?xml version="1.0" encoding="UTF-8"?> |
| 142 | +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> |
| 143 | +{% for lang in site.languages %} |
| 144 | +
|
| 145 | + {% for node in site.pages %} |
| 146 | + {% comment %}<!-- sehr einfache Überprüfung, ob die Seite in der Ausschlussliste enthalten ist - das bedeutet, dass ausgeschlossene Seiten überhaupt nicht in der Sitemap erscheinen, schreiben Sie bei Bedarf Ausnahmen -->{% endcomment %} |
| 147 | + {% unless site.exclude_from_localization contains node.path %} |
| 148 | + {% comment %}<!-- Annahme: Wenn kein Layout zugewiesen ist, dann die Seite nicht in die Sitemap aufnehmen, Sie möchten dies möglicherweise ändern -->{% endcomment %} |
| 149 | + {% if node.layout %} |
| 150 | + <url> |
| 151 | + <loc>{% if lang == site.default_lang %}{{ node.url | absolute_url }}{% else %}{{ node.url | prepend: lang | prepend: '/' | absolute_url }}{% endif %}</loc> |
| 152 | + {% if node.last_modified_at and node.last_modified_at != node.date %}<lastmod>{{ node.last_modified_at | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% elsif node.date %}<lastmod>{{ node.date | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% endif %} |
| 153 | + </url> |
| 154 | + {% endif %} |
| 155 | + {% endunless %} |
| 156 | + {% endfor %} |
| 157 | +
|
| 158 | + {% comment %}<!-- Dies durchläuft alle Site-Sammlungen einschließlich Beiträge -->{% endcomment %} |
| 159 | + {% for collection in site.collections %} |
| 160 | + {% for node in site[collection.label] %} |
| 161 | + <url> |
| 162 | + <loc>{% if lang == site.default_lang %}{{ node.url | absolute_url }}{% else %}{{ node.url | prepend: lang | prepend: '/' | absolute_url }}{% endif %}</loc> |
| 163 | + {% if node.last_modified_at and node.last_modified_at != node.date %}<lastmod>{{ node.last_modified_at | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% elsif node.date %}<lastmod>{{ node.date | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% endif %} |
| 164 | + </url> |
| 165 | + {% endfor %} |
| 166 | + {% endfor %} |
| 167 | +
|
| 168 | +{% endfor %} |
| 169 | +</urlset> |
| 170 | +``` |
| 171 | +{: file='sitemap.xml'} |
| 172 | +{% endraw %} |
| 173 | + |
| 174 | +## Hinzufügen eines Sprachauswahl-Buttons zur Seitenleiste |
| 175 | +Erstellen Sie eine Datei `_includes/lang-selector.html` und fügen Sie folgenden Inhalt ein: |
| 176 | + |
| 177 | +{% raw %} |
| 178 | +```liquid |
| 179 | +<p> |
| 180 | +{%- for lang in site.languages -%} |
| 181 | + {%- if lang == site.default_lang -%} |
| 182 | +<a ferh="{{ page.url }}" style="display:inline-block; white-space:nowrap;"> |
| 183 | + {%- if lang == site.active_lang -%} |
| 184 | + <b>{{ lang }}</b> |
| 185 | + {%- else -%} |
| 186 | + {{ lang }} |
| 187 | + {%- endif -%} |
| 188 | +</a> |
| 189 | + {%- else -%} |
| 190 | +<a href="/{{ lang }}{{ page.url }}" style="display:inline-block; white-space:nowrap;"> |
| 191 | + {%- if lang == site.active_lang -%} |
| 192 | + <b>{{ lang }}</b> |
| 193 | + {%- else -%} |
| 194 | + {{ lang }} |
| 195 | + {%- endif -%} |
| 196 | +</a> |
| 197 | + {%- endif -%} |
| 198 | +{%- endfor -%} |
| 199 | +</p> |
| 200 | +``` |
| 201 | +{: file='_includes/lang-selector.html'} |
| 202 | +{% endraw %} |
| 203 | + |
| 204 | +Fügen Sie dann die folgenden drei Zeilen zum "sidebar-bottom" Klassenbereich in [_includes/sidebar.html des Chirpy-Themes](https://github.com/cotes2020/jekyll-theme-chirpy/blob/v7.1.1/_includes/sidebar.html) hinzu, damit Jekyll den Inhalt von `_includes/lang-selector.html` beim Seitenbau lädt: |
| 205 | + |
| 206 | +{% raw %} |
| 207 | +```liquid |
| 208 | + <div class="lang-selector"> |
| 209 | + {%- include lang-selector.html -%} |
| 210 | + </div> |
| 211 | +``` |
| 212 | +{% endraw %} |
| 213 | + |
| 214 | +## Weiterführende Lektüre |
| 215 | +Fortsetzung in [Teil 2](/posts/how-to-support-multi-language-on-jekyll-blog-with-polyglot-2) |
0 commit comments