Übersetzungen mit React

#Diese Webseite#Projekte#JavaScript#React#TypeScript

Ü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-localization

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

Sprachen wechseln

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>; }

Kommentare

Noch Fragen?