Übersetzungen mit React
Für diese Website wollte ich ihren Inhalt nicht nur auf Deutsch, sondern auch auf Englisch anbieten. Da ich auch Blogposts wie diesen hier veröffentliche und weiterhin veröffentlichen werde, sollte es nicht kompliziert sein, Übersetzungen hinzuzufügen oder zu ändern, und ich müsste sie auf der ganzen Website verwenden, nicht nur in den Blogposts.
react-localizationist eine Bibliothek, die genau das tut. Hier ist ein schnelles Beispiel, wie es funktioniert:
//import the module
import LocalizedStrings from 'react-localization';
//define translated texts
let myTranslations = new LocalizedStrings({
en:{
title: "Localization in React", //add translations like this
//jsx elements that you want to display can be added using lambda expressions:
content: () => <>
<p>Interesting text</p>
</>
},
de: {
title: "Übersetzungen mit React",
content: () => <>
<p>Interessanter text</p>
</>
}
});
function Post(){ //react component using function syntax
//use translated texts like this:
return <>
<h1>{myTranslations.title}</h1>
<p>{myTranslations.content()}</p>
</>
}
Standardmäßig verwendet es die Browsersprache. Um den Besuchern meiner Website das Wechseln der Sprachen zu ermöglichen, habe ich dieses System erweitert, damit die aktuelle Sprache in einem Abfrageparameter angegeben werden kann. Besucher können die aktuelle Sprache ändern, indem sie ein Dropdown-Menü verwenden, das diesen Abfrageparameter ändert. Daher muss jedes LocalizedStrings
-Objekt die Sprache verwenden, die durch den Abfrageparameter angegeben ist.
Das Ändern der Sprache mit react-localization
erfolgt für jedes LocalizedStrings
-Objekt individuell. Daher habe ich die Klasse LocalizedStrings
erweitert:
import LocalizedStrings from 'react-localization';
export class MyLocalizedStrings extends LocalizedStrings {
constructor(x) {
return MyLocalizedStrings.create(x);
}
static create(x){
var ret = new LocalizedStrings(x);
//set language in query param
ret.setLanguage(getCurrentLanguage());
return ret;
}
}
export function getCurrentLanguage(){
var quer = window.location.href.match(/[?&]lang=([^&]*)/);
var navLanguage = getNavigatorLanguage();
return quer ? quer[1] : navLanguage;
}
export function getNavigatorLanguage() {
var navLanguage = navigator.language;
if (navLanguage.includes("-")) {
navLanguage = navLanguage.split("-")[0];
}
return navLanguage;
}
Das hat gut funktioniert. Aber beim Klicken auf Links, die zu anderen Seiten auf meiner Website führen, verschwand der lang
-Parameter. Queryparameter werden nicht beibehalten. Daher habe ich ein React-Komponente erstellt, die als Link verwendet werden kann und den Besucher zur nächsten Seite weiterleitet, während der lang
-Parameter beibehalten wird:
import React from 'react';
import { useSearchParams } from 'react-router-dom';
export function NavLinkLang(props) {
const [searchParams, setSearchParams] = useSearchParams(props.to);
const language = searchParams.get('lang');
const appendSymbol = (props.to.includes && (/(?)(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/).test(props.to)) ? "&" : "?";
const appendix = language ? appendSymbol + "lang=" + language : "";
const href = window.origin + "/#" + props.to + appendix;
//instead of using "Link" or "<a>", we use a div and implement link functionality ourselves so we don't have nested links (not html compliant)
return <>
<div {...props}
style={{ cursor: 'pointer' }}
className='navlinklang'
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
//TODO extract to router.tsx:
window.location = href;
}} />
<a href={href} style={{ display: "none" }}>Link</a>
</>;
}
Das ist der Component um die Sprache zu wechseln:
import React, { useEffect, useRef, useState } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'react-bootstrap';
import { NavLink } from 'react-router-dom';
import { MyLocalizedStrings, getNavigatorLanguage } from './MyLocalizedStrings';
//import { strings } from '..';
export const strings = new MyLocalizedStrings({
en: {
language: "Language",
flag: "🇬🇧",
},
de: {
language: "Sprache",
flag: "🇩🇪",
},
})
export function LanguageToggle() {
const [searchParams, setSearchParams] = useSearchParams();
const myParam = searchParams.get('lang');
useEffect(() => {
if (myParam && myParam!=strings.getLanguage()) {
window.location.reload();
}
}, [myParam]);
function setLanguage(newLang) {
searchParams.set("lang", newLang)
//if language is the same as the navigator language, remove the language parameter
if(newLang==getNavigatorLanguage()){
searchParams.delete("lang");
setSearchParams(searchParams);
window.location.reload();
}
setSearchParams(searchParams);
}
return <Dropdown>
<DropdownToggle>{strings.flag} {strings.language}</DropdownToggle>
<DropdownMenu>
<DropdownItem onClick={() => { setLanguage("en"); }}>English</DropdownItem>
<DropdownItem onClick={() => { setLanguage("de"); }}>Deutsch</DropdownItem>
</DropdownMenu>
</Dropdown>;
}
Noch Fragen?