From aec4a9406e6816f93de7074cb7874fc0fc7d8afd Mon Sep 17 00:00:00 2001 From: LBlend Date: Wed, 13 Mar 2024 02:36:31 +0100 Subject: [PATCH] initial translation support I should've divided this into multiple commits but oh well. This is just initial as there are still parts that needs to be done. Particularly user generated content needs to be translated somehow. See issue #45 for more info --- gatsby-config.js | 27 + package.json | 8 + src/components/items/back.js | 27 +- src/components/items/languageSelector.js | 42 + .../items/languageSelector.module.css | 24 + src/components/items/memberButton.js | 26 +- src/components/sections/about.js | 24 +- src/components/sections/boardMembers.js | 9 +- src/components/sections/contact.js | 138 +- src/components/sections/events.js | 25 +- src/components/sections/footer.js | 13 +- src/components/sections/header.js | 8 +- src/components/sections/office.js | 37 +- src/locales/en/404.json | 5 + src/locales/en/altText.json | 6 + src/locales/en/common.json | 5 + src/locales/en/index.json | 19 + src/locales/no/404.json | 5 + src/locales/no/altText.json | 6 + src/locales/no/common.json | 5 + src/locales/no/index.json | 19 + src/pages/404.js | 57 +- src/pages/eventPost.js | 21 +- src/pages/index.js | 44 +- yarn.lock | 1191 ++++++++++------- 25 files changed, 1141 insertions(+), 650 deletions(-) create mode 100644 src/components/items/languageSelector.js create mode 100644 src/components/items/languageSelector.module.css create mode 100644 src/locales/en/404.json create mode 100644 src/locales/en/altText.json create mode 100644 src/locales/en/common.json create mode 100644 src/locales/en/index.json create mode 100644 src/locales/no/404.json create mode 100644 src/locales/no/altText.json create mode 100644 src/locales/no/common.json create mode 100644 src/locales/no/index.json diff --git a/gatsby-config.js b/gatsby-config.js index 4c6a40a..19e4c68 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -21,6 +21,33 @@ module.exports = { path: `${__dirname}/src/images`, }, }, + { + resolve: `gatsby-source-filesystem`, + options: { + path: `${__dirname}/src/locales`, + name: `locale`, + }, + }, + { + resolve: `gatsby-plugin-react-i18next`, + options: { + localeJsonSourceName: `locale`, // name given to `gatsby-source-filesystem` plugin. + languages: [`en`, `no`], + defaultLanguage: `no`, + siteUrl: `https://uiogaming.no`, + // if you are using trailingSlash gatsby config include it here, as well (the default is 'always') + trailingSlash: "always", + // you can pass any i18next options + i18nextOptions: { + interpolation: { + escapeValue: false, // not needed for react as it escapes by default + }, + keySeparator: false, + nsSeparator: false, + }, + pages: [], + }, + }, `gatsby-transformer-sharp`, `gatsby-plugin-sharp`, { diff --git a/package.json b/package.json index d9f80d6..374ce2f 100644 --- a/package.json +++ b/package.json @@ -6,19 +6,27 @@ "author": "LBlend ( - -) +import { FaArrowLeft } from "react-icons/fa" +import { useTranslation } from "gatsby-plugin-react-i18next" + +const Back = () => { + const { t } = useTranslation() + + return ( + + ) +} export default Back diff --git a/src/components/items/languageSelector.js b/src/components/items/languageSelector.js new file mode 100644 index 0000000..556b4c1 --- /dev/null +++ b/src/components/items/languageSelector.js @@ -0,0 +1,42 @@ +import * as React from "react" +import * as styles from "./languageSelector.module.css" + +import { NO, GB } from "country-flag-icons/react/3x2" +import { useTranslation, useI18next } from "gatsby-plugin-react-i18next" + +const LanguageSelector = () => { + const { languages, changeLanguage } = useI18next() + const { t, i18n } = useTranslation() + + if (i18n.language === "no") { + return ( + { + e.preventDefault() + changeLanguage("en") + }} + > + + English + + ) + } else { + return ( + { + e.preventDefault() + changeLanguage("no") + }} + > + + Norsk + + ) + } +} + +export default LanguageSelector diff --git a/src/components/items/languageSelector.module.css b/src/components/items/languageSelector.module.css new file mode 100644 index 0000000..d919919 --- /dev/null +++ b/src/components/items/languageSelector.module.css @@ -0,0 +1,24 @@ +.button { + display: flex; + gap: 0.25rem; + + position: fixed; + top: 0.5rem; + right: 0.5rem; + z-index: 0; + + background: pink; + color: black; + border: 1px solid black; + font-size: 1.1rem; + border-radius: 0.5rem; + padding-inline: 0.5em; +} +.button:hover { + background: #ff7b7b; + color: white; +} + +.flag { + width: 1.2rem; +} diff --git a/src/components/items/memberButton.js b/src/components/items/memberButton.js index ffd503f..296f60f 100644 --- a/src/components/items/memberButton.js +++ b/src/components/items/memberButton.js @@ -1,14 +1,20 @@ import * as React from "react" import * as styles from "./memberButton.module.css" -const MemberButton = () => ( - - Bli medlem! - -) +import { useTranslation } from "gatsby-plugin-react-i18next" + +const MemberButton = () => { + const { t } = useTranslation() + + return ( + + {t("join")} + + ) +} export default MemberButton diff --git a/src/components/sections/about.js b/src/components/sections/about.js index b5e242d..6bd2db4 100644 --- a/src/components/sections/about.js +++ b/src/components/sections/about.js @@ -3,6 +3,7 @@ import * as styles from "./about.module.css" import { graphql, useStaticQuery } from "gatsby" import { GatsbyImage } from "gatsby-plugin-image" +import { useTranslation } from "gatsby-plugin-react-i18next" import DiscordButton from "../items/discordButton" import MemberButton from "../items/memberButton" @@ -22,31 +23,26 @@ const About = () => { } `) + const { t } = useTranslation() + return (
-

Foto: 장태민, Studentenes Fotoklubb

+

+ {t("photo")}: 장태민, Studentenes Fotoklubb +

-

Hvem er vi?

+

{t("about.title")}

-

- UiO Gaming er en forening med hovedfokus på å danne et - inkluderende fellesskap rundt videospill og e-sport. Hos oss er - det enkelt å skaffe seg venner, ettersom alle har felles - interesser. Vi arrangerer ukentlige spillkvelder og fysiske - sosiale arrangementer, som for eksempel brettspillkvelder og - sosiale sammenkomster. Vår hovedkanal er en aktiv Discord-server - hvor man kan møte nye folk med felles interesser og game med andre - studenter. -

+

{t("about.text")}

-

Interessert?

+

{t("about.interested")}

diff --git a/src/components/sections/boardMembers.js b/src/components/sections/boardMembers.js index 99383a3..1b6215f 100644 --- a/src/components/sections/boardMembers.js +++ b/src/components/sections/boardMembers.js @@ -3,6 +3,7 @@ import * as styles from "./boardMembers.module.css" import { graphql, useStaticQuery } from "gatsby" import { GatsbyImage } from "gatsby-plugin-image" +import { useTranslation } from "gatsby-plugin-react-i18next" const BoardMembers = () => { const data = useStaticQuery(graphql` @@ -30,9 +31,11 @@ const BoardMembers = () => { } `) + const { t } = useTranslation() + return (
-

Styret

+

{t("boardMembers.title")}

{data.allSanityAuthor.edges.map(({ node: member }) => (
@@ -43,7 +46,7 @@ const BoardMembers = () => {
@@ -57,7 +60,7 @@ const BoardMembers = () => { {member.contactInfo ? ( member.contactInfo ) : ( - Ingen kontaktinfo + {t("boardMembers.noContact")} )}

diff --git a/src/components/sections/contact.js b/src/components/sections/contact.js index ab25067..857a06d 100644 --- a/src/components/sections/contact.js +++ b/src/components/sections/contact.js @@ -1,6 +1,8 @@ import * as React from "react" import * as styles from "./contact.module.css" +import { useTranslation } from "gatsby-plugin-react-i18next" + import { FaYoutube, FaTwitch, @@ -11,66 +13,82 @@ import { FaInstagram, } from "react-icons/fa" -const Contact = () => ( -
-

Finn oss

-
-
- - - E-post - +const Contact = () => { + const { t } = useTranslation() + + return ( +
+

{t("contact.title")}

+ - - - - - - -
-
-) +
+ ) +} export default Contact diff --git a/src/components/sections/events.js b/src/components/sections/events.js index 9785c94..e441a1d 100644 --- a/src/components/sections/events.js +++ b/src/components/sections/events.js @@ -1,8 +1,9 @@ import * as React from "react" import * as styles from "./events.module.css" -import { Link, graphql, useStaticQuery } from "gatsby" +import { graphql, useStaticQuery } from "gatsby" import { GatsbyImage } from "gatsby-plugin-image" +import { Link, useTranslation } from "gatsby-plugin-react-i18next" import moment from "moment-timezone" import "moment/locale/nb" @@ -37,7 +38,9 @@ const Events = () => { } `) - moment.locale("nb_NO") + const { t, i18n } = useTranslation() + + moment.locale(i18n.language) const currentDate = moment().utc() const filteredEvents = data.allSanityEvent.edges @@ -49,7 +52,7 @@ const Events = () => { const mapEvents = events => { if (events.length !== 0) { return events.map(({ node: event }) => ( - +

{event.title}

@@ -62,7 +65,7 @@ const Events = () => {

{moment(event.date) .tz("Europe/Oslo") - .format("dddd Do MMMM, [kl.] H:mm")} + .format("dddd Do MMMM, H:mm")}

@@ -72,7 +75,9 @@ const Events = () => { ) : ( <> {event.description.substring(0, 120)}...{" "} - Les mer + + {t("events.readMore")} + )}

@@ -82,7 +87,7 @@ const Events = () => { } else { return (

- Ingen kommende arrangementer + {t("events.noEvents")}

(っ˘̩╭╮˘̩)っ @@ -94,15 +99,17 @@ const Events = () => { return (
-

Hva skjer?

+

{t("events.title")}

{mapEvents(filteredEvents)}
-

Foto: 장태민, Studentenes Fotoklubb

+

+ {t("photo")}: 장태민, Studentenes Fotoklubb +

diff --git a/src/components/sections/footer.js b/src/components/sections/footer.js index fb5a41e..47dbfe0 100644 --- a/src/components/sections/footer.js +++ b/src/components/sections/footer.js @@ -3,6 +3,7 @@ import * as styles from "./footer.module.css" import { graphql, useStaticQuery } from "gatsby" import { GatsbyImage } from "gatsby-plugin-image" +import { useTranslation } from "gatsby-plugin-react-i18next" const Footer = () => { const data = useStaticQuery(graphql` @@ -19,6 +20,8 @@ const Footer = () => { } `) + const { t } = useTranslation() + return (

diff --git a/src/components/sections/header.js b/src/components/sections/header.js index cf489fb..a24914b 100644 --- a/src/components/sections/header.js +++ b/src/components/sections/header.js @@ -3,6 +3,7 @@ import * as styles from "./header.module.css" import { graphql, useStaticQuery } from "gatsby" import { GatsbyImage } from "gatsby-plugin-image" +import { useTranslation } from "gatsby-plugin-react-i18next" const Header = () => { const data = useStaticQuery(graphql` @@ -19,6 +20,8 @@ const Header = () => { } `) + const { t } = useTranslation() + return (
{ />

UiO Gaming

-

- En hobbyforening som ønsker å skape et sosialt miljø rundt gaming og - e-sport på UiO -

+

{t("header.text")}

) } diff --git a/src/components/sections/office.js b/src/components/sections/office.js index 5da1ede..71c64b5 100644 --- a/src/components/sections/office.js +++ b/src/components/sections/office.js @@ -2,29 +2,30 @@ import * as React from "react" import * as styles from "./office.module.css" import ReactPannellum from "react-pannellum" +import { useTranslation } from "gatsby-plugin-react-i18next" const config = { autoLoad: true, } -const Office = () => ( -
-

Kontoret

-
-

- Vi har et foreningskontor på Chateau Neuf der man kan bruke utstyret - vårt og henge med andre medlemmer! -

+const Office = () => { + const { t } = useTranslation() - -
-
-) + return ( +
+

{t("office.title")}

+
+

{t("office.text")}

+ +
+
+ ) +} export default Office diff --git a/src/locales/en/404.json b/src/locales/en/404.json new file mode 100644 index 0000000..a18e02a --- /dev/null +++ b/src/locales/en/404.json @@ -0,0 +1,5 @@ +{ + "title": "404: Page not found", + "text": "Our journey ended here. Please don't leave us", + "back": "Back to safe grounds" +} diff --git a/src/locales/en/altText.json b/src/locales/en/altText.json new file mode 100644 index 0000000..15db42a --- /dev/null +++ b/src/locales/en/altText.json @@ -0,0 +1,6 @@ +{ + "altText.about": "2 members playing games together", + "altText.events": "Members playing board games", + "altText.boardMember": "Picture of board member", + "altText.flag": "Flag of Norway" +} diff --git a/src/locales/en/common.json b/src/locales/en/common.json new file mode 100644 index 0000000..5c58e85 --- /dev/null +++ b/src/locales/en/common.json @@ -0,0 +1,5 @@ +{ + "back": "Back", + "join": "Become a member", + "photo": "Photo" +} diff --git a/src/locales/en/index.json b/src/locales/en/index.json new file mode 100644 index 0000000..6d08844 --- /dev/null +++ b/src/locales/en/index.json @@ -0,0 +1,19 @@ +{ + "header.text": "A student organisation that aims to create an inclusive environment around gaming and e-sports for the students at UiO", + "about.title": "Who are we?", + "about.text": "UiO Gaming is a student organisation with a primary focus on creating an inclusive environment around gaming and e-sports. We wish to establish a community where it’s easy to make new friends and cultivate your gaming interests. Each week we host both casual and more intense gamenights, as well as physical events such as board game nights and other social gatherings. Our main channel is a Discord server where you can meet new people with common interests and play games with other students.", + "about.interested": "Interested?", + "events.title": "Upcoming events", + "events.readMore": "Read more", + "events.noEvents": "No upcoming events", + "office.title": "The office", + "office.text": "We have an office at Chateau Neuf where you can use our gear and hang out with other members!", + "boardMembers.title": "The board", + "boardMembers.noContact": "No contact info", + "contact.title": "Contact us", + "contact.email": "E-mail", + "footer.statutes": "Statutes (norwegian)", + "footer.sourcecode": "Source code", + "footer.admin": "Admin page", + "footer.orgnum": "OrgNum" +} diff --git a/src/locales/no/404.json b/src/locales/no/404.json new file mode 100644 index 0000000..6546830 --- /dev/null +++ b/src/locales/no/404.json @@ -0,0 +1,5 @@ +{ + "title": "404: Siden finnes ikke", + "text": "Du har nådd en blindvei, men ikke på Blindern", + "back": "Tilbake til hjemmesiden" +} diff --git a/src/locales/no/altText.json b/src/locales/no/altText.json new file mode 100644 index 0000000..c7dac42 --- /dev/null +++ b/src/locales/no/altText.json @@ -0,0 +1,6 @@ +{ + "altText.about": "2 medlemmer som spiller sammen", + "altText.events": "Medlemmer som spiller brettspill", + "altText.boardMember": "Bilde av styremedlem", + "altText.flag": "Britisk flagg" +} diff --git a/src/locales/no/common.json b/src/locales/no/common.json new file mode 100644 index 0000000..74a9217 --- /dev/null +++ b/src/locales/no/common.json @@ -0,0 +1,5 @@ +{ + "back": "Tilbake", + "join": "Bli medlem", + "photo": "Foto" +} diff --git a/src/locales/no/index.json b/src/locales/no/index.json new file mode 100644 index 0000000..bcf6587 --- /dev/null +++ b/src/locales/no/index.json @@ -0,0 +1,19 @@ +{ + "header.text": "En hobbyforening som ønsker å skape et sosialt miljø rundt gaming og e-sport på UiO", + "about.title": "Hvem er vi?", + "about.text": "UiO Gaming er en forening med hovedfokus på å danne et inkluderende fellesskap rundt videospill og e-sport. Hos oss er det enkelt å skaffe seg venner, ettersom alle har felles interesser. Vi arrangerer ukentlige spillkvelder og fysiske sosiale arrangementer, som for eksempel brettspillkvelder og sosiale sammenkomster. Vår hovedkanal er en aktiv Discord-server hvor man kan møte nye folk med felles interesser og game med andre studenter.", + "about.interested": "Interessert?", + "events.title": "Hva skjer?", + "events.readMore": "Les mer", + "events.noEvents": "Ingen kommende arrangementer", + "office.title": "Kontoret", + "office.text": "Vi har et foreningskontor på Chateau Neuf der man kan bruke utstyret vårt og henge med andre medlemmer!", + "boardMembers.title": "Styret", + "boardMembers.noContact": "Ingen kontaktinfo", + "contact.title": "Finn oss", + "contact.email": "E-mail", + "footer.statutes": "Vedtekter", + "footer.sourcecode": "Kildekode", + "footer.admin": "Adminområdet", + "footer.orgnum": "Org.Nr." +} diff --git a/src/pages/404.js b/src/pages/404.js index 1f358af..d3f62af 100644 --- a/src/pages/404.js +++ b/src/pages/404.js @@ -1,27 +1,48 @@ import * as React from "react" import * as styles from "./404.module.css" -import { Link } from "gatsby" +import { graphql } from "gatsby" +import { Link, useTranslation } from "gatsby-plugin-react-i18next" import Layout from "../components/layout" import Seo from "../components/seo" -const NotFoundPage = () => ( - - -
-

404: Siden finnes ikke

-

- Du har nådd en blindvei, men ikke på Blindern{" "} - - 👀 - -

- - Tilbake til hjemmesiden - -
-
-) +const NotFoundPage = () => { + const { t } = useTranslation() + + return ( + + +
+

{t("title")}

+

+ {t("text")}{" "} + + 👀 + +

+ + {t("back")} + +
+
+ ) +} export default NotFoundPage + +export const query = graphql` + query ($language: String!) { + locales: allLocale( + filter: { ns: { in: ["404"] }, language: { eq: $language } } + ) { + edges { + node { + ns + data + language + } + } + } + } +` diff --git a/src/pages/eventPost.js b/src/pages/eventPost.js index e079f27..54453e9 100644 --- a/src/pages/eventPost.js +++ b/src/pages/eventPost.js @@ -3,13 +3,14 @@ import * as styles from "./eventPost.module.css" import { graphql } from "gatsby" import moment from "moment-timezone" +import { useTranslation } from "gatsby-plugin-react-i18next" import Seo from "../components/seo" import Back from "../components/items/back" import { FaMapMarkerAlt, FaCalendarAlt } from "react-icons/fa" export const query = graphql` - query($id: String) { + query ($id: String, $language: String!) { sanityEvent(_id: { eq: $id }) { title location @@ -19,15 +20,27 @@ export const query = graphql` } description } + locales: allLocale( + filter: { ns: { in: ["common"] }, language: { eq: $language } } + ) { + edges { + node { + ns + data + language + } + } + } } ` -moment.locale("nb_NO") - const Event = ({ data }) => { + const { t, i18n } = useTranslation() + moment.locale(i18n.language) + const time = moment(data.sanityEvent.date) .tz("Europe/Oslo") - .format("dddd Do MMMM, [kl.] H:mm") + .format("dddd Do MMMM, H:mm") return ( <> diff --git a/src/pages/index.js b/src/pages/index.js index db70bc2..6ed6e30 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,8 +1,10 @@ import * as React from "react" +import { graphql } from "gatsby" import "../index.css" import Layout from "../components/layout" import Seo from "../components/seo" +import LanguageSelector from "../components/items/languageSelector" import Header from "../components/sections/header" import About from "../components/sections/about" @@ -13,16 +15,38 @@ import Contact from "../components/sections/contact" import Footer from "../components/sections/footer" const IndexPage = () => ( - - -
- - - - - -