Skip to content

Commit

Permalink
i18n support
Browse files Browse the repository at this point in the history
  • Loading branch information
saulipurhonen committed Oct 7, 2021
1 parent eebc8b6 commit 4258fd0
Show file tree
Hide file tree
Showing 28 changed files with 391 additions and 71 deletions.
38 changes: 38 additions & 0 deletions cypress/integration/i18n.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
describe("Internationalization", function () {
it("should login with finnish translation when finnish locale is chosen", () => {
const baseUrl = "http://localhost:" + Cypress.env("port") + "/"

cy.visit(baseUrl)

cy.get("#lang-selector").click()
cy.get("li[role=menuitem]").contains("Fi").click()

cy.get('[alt="CSC Login"]').click()
cy.wait(1000)

cy.get("[data-testid='logged-in-as'").contains("Kirjautuneena")
})

it("should change translation seamlessly", () => {
cy.login()

cy.get("[data-testid='logged-in-as'").contains("Logged in as")

cy.get("#lang-selector").click()
cy.get("li[role=menuitem]").contains("Fi").click()
cy.url().should("include", "/fi/")

cy.get("[data-testid='logged-in-as'").contains("Kirjautuneena")
})

it("should navigate with selected locale", () => {
cy.login()

cy.get("#lang-selector").click()
cy.get("li[role=menuitem]").contains("Fi").click()

cy.get("button", { timeout: 10000 }).contains("Create Submission").click()

cy.url().should("include", "/fi/newdraft")
})
})
88 changes: 79 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
"ajv": "^8.6.3",
"ajv-formats": "^2.1.1",
"apisauce": "^2.1.1",
"i18next": "^21.2.4",
"jest": "26.6.0",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hook-form": "^7.16.2",
"react-i18next": "^11.12.0",
"react-redux": "^7.2.5",
"react-router-dom": "^5.3.0",
"react-scripts": "^4.0.3"
Expand Down
44 changes: 36 additions & 8 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import React, { useEffect } from "react"
import Container from "@material-ui/core/Container"
import CssBaseline from "@material-ui/core/CssBaseline"
import { makeStyles } from "@material-ui/core/styles"
import { useDispatch } from "react-redux"
import { Switch, Route, useLocation } from "react-router-dom"
import i18n from "i18next"
import { useDispatch, useSelector } from "react-redux"
import { Switch, Route, useLocation, Redirect } from "react-router-dom"

import SelectedFolderDetails from "components/Home/SelectedFolderDetails"
import SubmissionFolderList from "components/Home/SubmissionFolderList"
import Nav from "components/Nav"
import { ObjectTypes } from "constants/wizardObject"
import { setLocale } from "features/localeSlice"
import { setObjectTypesArray } from "features/objectTypesArraySlice"
import schemaAPIService from "services/schemaAPI"
import Page400 from "views/ErrorPages/Page400"
Expand Down Expand Up @@ -67,9 +69,13 @@ const App = (): React$Element<typeof React.Fragment> => {
const classes = useStyles()
const dispatch = useDispatch()

const locale = useSelector(state => state.locale)

// Fetch array of schemas from backend and store it in frontend
// Fetch only if the initial array is empty
// if there is any errors while fetching, it will return a manually created ObjectsArray instead
// &&
// Handle initial locale setting
useEffect(() => {
if (location.pathname === "/" || pathsWithoutNav.indexOf(location.pathname) !== -1) return
let isMounted = true
Expand Down Expand Up @@ -98,18 +104,40 @@ const App = (): React$Element<typeof React.Fragment> => {
}
}
}

// Get locale from url and set application wide locale setting
const getLocale = () => {
let locale: string
const locales = ["en", "fi"]
const currentLocale = location.pathname.split("/")[1]

if (locales.indexOf(currentLocale) > -1) {
locale = currentLocale
} else locale = "en"

i18n.changeLanguage(locale)

dispatch(setLocale(locale))
}

getSchemas()
getLocale()
return () => {
isMounted = false
}
}, [])

const setPath = (path: string) => {
return `/:locale(en|fi)/${path}`
}

return (
<React.Fragment>
<CssBaseline />
<NavigationMenu />
<Switch>
<Route path="/newdraft">
<Redirect exact from="/home" to={`/${locale}/home`} />
<Route path="/:locale/newdraft">
<Container component="main" maxWidth={false} className={classes.wizardContent}>
<NewDraftWizard />
</Container>
Expand All @@ -119,27 +147,27 @@ const App = (): React$Element<typeof React.Fragment> => {
<Login />
</Container>
</Route>
<Route exact path="/home">
<Route exact path={setPath("home")}>
<Container component="main" maxWidth="md" className={classes.content}>
<Home />
</Container>
</Route>
<Route exact path="/home/drafts">
<Route exact path={setPath("home/drafts")}>
<Container component="main" maxWidth="md" className={classes.content}>
<SubmissionFolderList />
</Container>
</Route>
<Route path="/home/drafts/:folderId">
<Route path={setPath("home/drafts/:folderId")}>
<Container component="main" maxWidth="md" className={classes.content}>
<SelectedFolderDetails />
</Container>
</Route>
<Route exact path="/home/published">
<Route exact path={setPath("home/published")}>
<Container component="main" maxWidth="md" className={classes.content}>
<SubmissionFolderList />
</Container>
</Route>
<Route path="/home/published/:folderId">
<Route path={setPath("home/published/:folderId")}>
<Container component="main" maxWidth="md" className={classes.content}>
<SelectedFolderDetails />
</Container>
Expand Down
6 changes: 5 additions & 1 deletion src/__tests__/Home.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import App from "App"
const middlewares = [thunk]
const mockStore = configureStore(middlewares)

jest.mock("react-i18next", () => ({
useTranslation: () => ({ t: key => key }),
}))

describe("HomePage", () => {
const store = mockStore({
user: { name: "Test User" },
Expand All @@ -27,7 +31,7 @@ describe("HomePage", () => {
beforeEach(() => {
render(
<Provider store={store}>
<MemoryRouter initialEntries={["/home"]}>
<MemoryRouter initialEntries={["/en/home"]}>
<App />
</MemoryRouter>
</Provider>
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/Nav.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe("NavBar", () => {
beforeEach(() => {
component = render(
<Provider store={store}>
<MemoryRouter initialEntries={["/home"]}>
<MemoryRouter initialEntries={["/en/home"]}>
<Nav />
</MemoryRouter>
</Provider>
Expand All @@ -27,7 +27,7 @@ describe("NavBar", () => {

test("has correct nav links rendered", () => {
const nav = component.container.querySelector("nav")
const expectedLinksLength = 5
const expectedLinksLength = 6
const expectedLinks = ["Open submissions", "Submissions", "Create Submission", "Log out"]
expect(nav.children).toHaveLength(expectedLinksLength)
expectedLinks.forEach(link => {
Expand Down
Loading

0 comments on commit 4258fd0

Please sign in to comment.