diff --git a/package-lock.json b/package-lock.json index dff7bb7..e6f8091 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,12 @@ "@iiif/parser": "^1.1.2", "@samvera/clover-iiif": "^2.3.1", "axios": "^1.6.5", + "i18next": "^23.7.16", "konsta": "3.1.1", "konva": "^9.3.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.0.0", "react-konva": "^18.2.10", "react-plock": "^3.0.2", "react-router-dom": "^6.21.1", @@ -2397,6 +2399,28 @@ "@iiif/vault": "0.9.x" } }, + "node_modules/@iiif/vault-helpers/node_modules/react-i18next": { + "version": "11.18.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", + "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.14.5", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 19.0.0", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -6269,7 +6293,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", - "optional": true, "dependencies": { "void-elements": "3.1.0" } @@ -6293,9 +6316,9 @@ } }, "node_modules/i18next": { - "version": "23.7.6", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.7.6.tgz", - "integrity": "sha512-O66BhXBw0fH4bEJMA0/klQKPEbcwAp5wjXEL803pdAynNbg2f4qhLIYlNHJyE7icrL6XmSZKPYaaXwy11kJ6YQ==", + "version": "23.7.16", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.7.16.tgz", + "integrity": "sha512-SrqFkMn9W6Wb43ZJ9qrO6U2U4S80RsFMA7VYFSqp7oc7RllQOYDCdRfsse6A7Cq/V8MnpxKvJCYgM8++27n4Fw==", "funding": [ { "type": "individual", @@ -6310,8 +6333,6 @@ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" } ], - "optional": true, - "peer": true, "dependencies": { "@babel/runtime": "^7.23.2" } @@ -8117,16 +8138,15 @@ } }, "node_modules/react-i18next": { - "version": "11.18.6", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", - "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", - "optional": true, + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.0.0.tgz", + "integrity": "sha512-OCrS8rHNAmnr8ggGRDxjakzihrMW7HCbsplduTm3EuuQ6fyvWGT41ksZpqbduYoqJurBmEsEVZ1pILSUWkHZng==", "dependencies": { - "@babel/runtime": "^7.14.5", + "@babel/runtime": "^7.22.5", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { - "i18next": ">= 19.0.0", + "i18next": ">= 23.2.3", "react": ">= 16.8.0" }, "peerDependenciesMeta": { @@ -9821,7 +9841,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", - "optional": true, "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index 578cd07..3314ba2 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,12 @@ "@iiif/parser": "^1.1.2", "@samvera/clover-iiif": "^2.3.1", "axios": "^1.6.5", + "i18next": "^23.7.16", "konsta": "3.1.1", "konva": "^9.3.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.0.0", "react-konva": "^18.2.10", "react-plock": "^3.0.2", "react-router-dom": "^6.21.1", diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 1ef4569..e143341 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,5 +1,6 @@ // @ts-expect-error konsta typing import { App, Icon, Page, Tabbar, TabbarLink } from "konsta/react"; +import { useTranslation } from "react-i18next"; import { MdFavoriteBorder, MdOutlineAssignmentInd, @@ -9,6 +10,7 @@ import { import { NavLink, Outlet, useMatch, useResolvedPath } from "react-router-dom"; function Layout() { + const { t } = useTranslation(); return ( @@ -35,7 +37,7 @@ function Layout() { }`} /> } - label={"Portal"} + label={t("portal")} touchRipple={false} /> @@ -57,7 +59,7 @@ function Layout() { }`} /> } - label={"Meine Auswahl"} + label={t("selection")} touchRipple={false} /> @@ -79,7 +81,7 @@ function Layout() { }`} /> } - label={"Meine Sammlung"} + label={t("collection")} touchRipple={false} /> @@ -101,7 +103,7 @@ function Layout() { }`} /> } - label={"Meine Leinwand"} + label={t("artwork")} touchRipple={false} /> diff --git a/src/components/Start.tsx b/src/components/Start.tsx index 6f85ac4..ed36f51 100644 --- a/src/components/Start.tsx +++ b/src/components/Start.tsx @@ -1,5 +1,7 @@ // @ts-expect-error konsta typing import { Block, Button } from "konsta/react"; +import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; import CollageIcon from "/collage.webp"; import LogoIcon from "/logo_animated.svg"; @@ -22,22 +24,16 @@ const Collage = () => { }; function Start() { + const { t } = useTranslation(); return ( -

- Herzlich willkommen in der schillernden Welt von GLAMorous Europe! -

-

- Entdecke hier die schönsten Sammlungsobjekte aus Museen, Galerien, - Bibliotheken und Archiven verschiedener Länder Europas. -

+

{t("startTitle")}

+

{t("startSubtitle")}

-

- Lass dich von der künstlerischen Vielfalt Europas inspirieren! -

+

{t("startText")}

); diff --git a/src/locales/de.json b/src/locales/de.json new file mode 100644 index 0000000..ebc24af --- /dev/null +++ b/src/locales/de.json @@ -0,0 +1,23 @@ +{ + "translation": { + "artwork": "Meine Leinwand", + "artworkTitle": "Gestalte mit einzelnen Bildelementen dein ganz eigenes europäisches Kunstwerk und teile es mit anderen.", + "chooseLanguage": "Sprache wählen:", + "collection": "Meine Sammlung", + "collectionAddText": "Meiner Leinwand hinzufügen", + "collectionClose": "Schließen", + "collectionLoading": "Lade...", + "collectionTitle": "Öffne die Tür zu neuen Gemälden, Skulpturen und Fotografien, die perfekt zu deinem Geschmack passen.", + "portal": "Portal", + "selection": "Meine Auswahl", + "selectionCreator": "Urheber:in:", + "selectionLocation": "Ort:", + "selectionTitle": "Wähle deine persönlichen Favoriten aus.", + "selectionUnknown": "Unbekannt", + "selectionYear": "Jahr:", + "startButtonText": "Los geht's!", + "startSubtitle": "Entdecke hier die schönsten Sammlungsobjekte aus Museen, Galerien, Bibliotheken und Archiven verschiedener Länder Europas.", + "startText": "Lass dich von der künstlerischen Vielfalt Europas inspirieren!", + "startTitle": "Herzlich willkommen in der schillernden Welt von GLAMorous Europe!" + } +} diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 0000000..badab32 --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,23 @@ +{ + "translation": { + "artwork": "My Artwork", + "artworkTitle": "Use individual picture elements to create your very own European work of art and share it with others.", + "chooseLanguage": "Choose Language:", + "collection": "My Collection", + "collectionAddText": "Add to my artwork", + "collectionClose": "Close", + "collectionLoading": "Loading...", + "collectionTitle": "Open the door to new paintings, sculptures and photographs that perfectly match your taste.", + "portal": "Portal", + "selection": "My Selection", + "selectionCreator": "Creator:", + "selectionLocation": "Location:", + "selectionTitle": "Choose your personal favourites.", + "selectionUnknown": "Unknown", + "selectionYear": "Year:", + "startButtonText": "Let's go!", + "startSubtitle": "Discover the most beautiful collection objects from museums, galleries, libraries and archives from various European countries.", + "startText": "Be inspired by the artistic diversity of Europe!", + "startTitle": "Welcome to the glittering world of GLAMorous Europe!" + } +} diff --git a/src/main.tsx b/src/main.tsx index 30d9c68..8692390 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,14 +1,30 @@ +import i18next from "i18next"; import React from "react"; import { createRoot } from "react-dom/client"; +import { I18nextProvider } from "react-i18next"; import { BrowserRouter } from "react-router-dom"; import App from "./components/App.tsx"; import "./index.css"; +import de from "./locales/de.json"; +import en from "./locales/en.json"; + +i18next.init({ + interpolation: { escapeValue: false }, + lng: "auto", + fallbackLng: "de", + resources: { + de: { ...de }, + en: { ...en }, + }, +}); createRoot(document.getElementById("root")!).render( - - - + + + + + , );