]> git.localhorst.tv Git - alttp.git/commitdiff
more alternate/canonical links
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 15 Feb 2023 10:36:58 +0000 (11:36 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 15 Feb 2023 10:36:58 +0000 (11:36 +0100)
resources/js/components/common/CanonicalLinks.js [new file with mode: 0644]
resources/js/components/pages/Front.js
resources/js/components/pages/Map.js
resources/js/components/pages/Technique.js
resources/js/components/pages/Techniques.js
resources/js/components/pages/Tournament.js
resources/js/components/pages/User.js
resources/js/helpers/Technique.js

diff --git a/resources/js/components/common/CanonicalLinks.js b/resources/js/components/common/CanonicalLinks.js
new file mode 100644 (file)
index 0000000..26e8696
--- /dev/null
@@ -0,0 +1,40 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import { useTranslation } from 'react-i18next';
+
+const CanonicalLinks = ({ base, lang, langs }) => {
+       const { i18n } = useTranslation();
+
+       const activeLang = lang || i18n.language;
+       const availableLangs = langs || ['de', 'en'];
+
+       return <Helmet>
+               <link
+                       href={`https://alttp.localhorst.tv${base}?lng=${activeLang}`}
+                       hrefLang={activeLang}
+                       rel="canonical"
+               />
+               <link
+                       href={`https://alttp.localhorst.tv${base}`}
+                       hrefLang="x-default"
+                       rel="alternate"
+               />
+               {availableLangs.filter(l => l !== activeLang).map(l =>
+                       <link
+                               key={l}
+                               href={`https://alttp.localhorst.tv${base}?lng=${l}`}
+                               hrefLang={l}
+                               rel="alternate"
+                       />
+               )}
+       </Helmet>;
+};
+
+CanonicalLinks.propTypes = {
+       base: PropTypes.string.isRequired,
+       lang: PropTypes.string,
+       langs: PropTypes.arrayOf(PropTypes.string),
+};
+
+export default CanonicalLinks;
index 73b9b23d8fb6f5e6482b1f17627647d76575dc65..2ca43f24ae7dc5aacf107595494e686d8e63e468 100644 (file)
@@ -2,6 +2,8 @@ import React from 'react';
 import { Button, Col, Container, Image, Row } from 'react-bootstrap';
 import { useNavigate } from 'react-router-dom';
 
+import CanonicalLinks from '../common/CanonicalLinks';
+
 const Front = () => {
        const navigate = useNavigate();
 
@@ -14,6 +16,7 @@ const Front = () => {
        }, []);
 
        return <Container className="mt-5">
+               <CanonicalLinks base="/" />
                <Row>
                        <Col md={6}>
                                <Button
index b27560261194512b99000b6ac389c23c349983a1..09e381a3af8bcb3c9a2ea67b9c15571dc585495d 100644 (file)
@@ -3,6 +3,7 @@ import { Container } from 'react-bootstrap';
 import { Helmet } from 'react-helmet';
 import { useTranslation } from 'react-i18next';
 
+import CanonicalLinks from '../common/CanonicalLinks';
 import Buttons from '../map/Buttons';
 import List from '../map/List';
 import OpenSeadragon from '../map/OpenSeadragon';
@@ -20,6 +21,7 @@ const Map = () => {
                        <title>{t('map.heading')}</title>
                        <meta name="description" content={t('map.description')} />
                </Helmet>
+               <CanonicalLinks base="/map" />
                <OpenSeadragon ref={container}>
                        <div className="d-flex align-items-start justify-content-between">
                                <h1>{t('map.heading')}</h1>
index aabb8d0780db86a73be7e50133fe66ac2a66d7c8..c4be0666614eb932d5c22e5ae8ccbf0ffd3dc23b 100644 (file)
@@ -4,12 +4,13 @@ import { Helmet } from 'react-helmet';
 import { withTranslation } from 'react-i18next';
 import { useParams } from 'react-router-dom';
 
+import CanonicalLinks from '../common/CanonicalLinks';
 import ErrorBoundary from '../common/ErrorBoundary';
 import ErrorMessage from '../common/ErrorMessage';
 import Loading from '../common/Loading';
 import NotFound from '../pages/NotFound';
 import Detail from '../techniques/Detail';
-import { getLanguages, getTranslation } from '../../helpers/Technique';
+import { getLanguages, getMatchedLocale, getTranslation } from '../../helpers/Technique';
 import i18n from '../../i18n';
 
 const Technique = () => {
@@ -56,20 +57,12 @@ const Technique = () => {
                <Helmet>
                        <title>{getTranslation(technique, 'title', i18n.language)}</title>
                        <meta name="description" content={getTranslation(technique, 'short', i18n.language)} />
-                       <link
-                               href={`https://alttp.localhorst.tv/tech/${technique.name}`}
-                               hrefLang="x-default"
-                               rel="alternate"
-                       />
-                       {getLanguages(technique).map(l =>
-                               <link
-                                       key={l}
-                                       href={`https://alttp.localhorst.tv/tech/${technique.name}?lng=${l}`}
-                                       hrefLang={l}
-                                       rel="alternate"
-                               />
-                       )}
                </Helmet>
+               <CanonicalLinks
+                       base={`/tech/${technique.name}`}
+                       lang={getMatchedLocale(technique, i18n.language)}
+                       langs={getLanguages(technique)}
+               />
                <Detail technique={technique} />
        </ErrorBoundary>;
 };
index a89c3a252e01f560449110a2739217b2487e6d70..ebeb6e5613e8f9067995bbdbde2b639f93365967 100644 (file)
@@ -5,6 +5,7 @@ import { Helmet } from 'react-helmet';
 import { withTranslation } from 'react-i18next';
 
 import NotFound from './NotFound';
+import CanonicalLinks from '../common/CanonicalLinks';
 import ErrorBoundary from '../common/ErrorBoundary';
 import ErrorMessage from '../common/ErrorMessage';
 import Loading from '../common/Loading';
@@ -83,6 +84,7 @@ const Techniques = ({ namespace, type }) => {
                        <title>{i18n.t(`${namespace}.heading`)}</title>
                        <meta name="description" content={i18n.t(`${namespace}.description`)} />
                </Helmet>
+               <CanonicalLinks base="/tech" />
                <Overview
                        filter={filter}
                        namespace={namespace}
index 7abd5e437b25bf8454e49810d9a2e12cde88a30a..d148059fef2cda83250afa2a5e290dbdaaa0e07a 100644 (file)
@@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react';
 import { Helmet } from 'react-helmet';
 import { useParams } from 'react-router-dom';
 
+import CanonicalLinks from '../common/CanonicalLinks';
 import ErrorBoundary from '../common/ErrorBoundary';
 import ErrorMessage from '../common/ErrorMessage';
 import Loading from '../common/Loading';
@@ -131,6 +132,7 @@ const Tournament = () => {
                <Helmet>
                        <title>{tournament.title}</title>
                </Helmet>
+               <CanonicalLinks base={`/tournaments/${tournament.id}`} />
                <Detail addRound={addRound} tournament={tournament} />
        </ErrorBoundary>;
 };
index b481112456813a4613a572702bd9b460880969c1..144e4c01d86418c46bd16cc53f567556399420b8 100644 (file)
@@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react';
 import { Helmet } from 'react-helmet';
 import { useParams } from 'react-router-dom';
 
+import CanonicalLinks from '../common/CanonicalLinks';
 import ErrorBoundary from '../common/ErrorBoundary';
 import ErrorMessage from '../common/ErrorMessage';
 import Loading from '../common/Loading';
@@ -67,6 +68,7 @@ const User = () => {
                <Helmet>
                        <title>{user.nickname || user.username}</title>
                </Helmet>
+               <CanonicalLinks base={`/users/${user.id}`} />
                <Profile user={user} />
        </ErrorBoundary>;
 };
index c1375bb6c787810119c624aa7de5169aafd3e65d..b289341d34833bbb4b99262885522786260da515 100644 (file)
@@ -19,6 +19,18 @@ export const hasRelations = (tech, type) => getRelations(tech, type).length > 0;
 
 export const getLanguages = tech => ['en', ...tech.translations.map(t => t.locale)];
 
+export const getMatchedLocale = (tech, lang) => {
+       const direct = tech.translations.find(t => t.locale === lang);
+       if (direct) {
+               return direct.locale;
+       }
+       const sameLang = tech.translations.find(t => t.locale.substr(0, 2) === lang.substr(0, 2));
+       if (sameLang) {
+               return sameLang.locale;
+       }
+       return 'en';
+};
+
 export const getTranslation = (tech, prop, lang) => {
        const direct = tech.translations.find(t => t.locale === lang);
        if (direct) {