Add translations
This commit is contained in:
parent
1a81c7ead5
commit
e5cf8ff107
@ -28,6 +28,8 @@
|
||||
"date-holidays": "^1.5.3",
|
||||
"file-loader": "4.3.0",
|
||||
"html-webpack-plugin": "4.0.0-beta.11",
|
||||
"i18next": "^19.6.0",
|
||||
"i18next-browser-languagedetector": "^5.0.0",
|
||||
"moment": "^2.26.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.3",
|
||||
@ -40,6 +42,7 @@
|
||||
"react-app-polyfill": "^1.0.6",
|
||||
"react-dev-utils": "^10.2.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-i18next": "^11.7.0",
|
||||
"react-redux": "^7.2.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"redux": "^4.0.5",
|
||||
@ -52,7 +55,8 @@
|
||||
"webpack": "4.42.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "3.10.3",
|
||||
"workbox-webpack-plugin": "4.3.1"
|
||||
"workbox-webpack-plugin": "4.3.1",
|
||||
"yaml-loader": "^0.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "webpack-dev-server --mode development",
|
||||
|
96
src/app.tsx
96
src/app.tsx
@ -1,14 +1,9 @@
|
||||
import React, { Dispatch } from 'react';
|
||||
import React, { Dispatch, HTMLProps } from 'react';
|
||||
import { MuiThemeProvider as ThemeProvider, StylesProvider } from "@material-ui/core/styles";
|
||||
import { studentTheme } from "./ui/theme";
|
||||
import { MuiPickersUtilsProvider } from "@material-ui/pickers";
|
||||
import MomentUtils from "@date-io/moment";
|
||||
import { BrowserRouter, Link, Route, Switch } from "react-router-dom"
|
||||
|
||||
import "moment/locale/pl"
|
||||
import '@/styles/overrides.scss'
|
||||
import '@/styles/header.scss'
|
||||
|
||||
import moment, { Moment } from "moment";
|
||||
import { route, routes } from "@/routing";
|
||||
import { Provider, useDispatch, useSelector } from "react-redux";
|
||||
@ -16,6 +11,15 @@ import store from "@/state/store";
|
||||
import { AppState } from "@/state/reducer";
|
||||
import { StudentAction, StudentActions } from "@/state/actions/student";
|
||||
import { sampleStudent } from "@/provider/dummy/student";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { StudentState } from "@/state/reducer/student";
|
||||
import { Student } from "@/data";
|
||||
|
||||
import "moment/locale/pl"
|
||||
import '@/styles/overrides.scss'
|
||||
import '@/styles/header.scss'
|
||||
import classNames from "classnames";
|
||||
import { Button } from "@material-ui/core";
|
||||
|
||||
moment.locale("pl")
|
||||
|
||||
@ -25,10 +29,10 @@ class LocalizedMomentUtils extends MomentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
const UserMenu = () => {
|
||||
const student = useSelector<AppState>(state => state.student);
|
||||
|
||||
const UserMenu = (props: HTMLProps<HTMLUListElement>) => {
|
||||
const student = useSelector<AppState, Student>(state => state.student as Student);
|
||||
const dispatch = useDispatch<Dispatch<StudentAction>>();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleUserLogin = () => {
|
||||
dispatch({
|
||||
@ -41,41 +45,32 @@ const UserMenu = () => {
|
||||
dispatch({ type: StudentActions.Logout })
|
||||
}
|
||||
|
||||
return student ? <>
|
||||
zalogowany jako: <strong>Jan Kowalski</strong>
|
||||
{' '}
|
||||
(<Link to={'#'} onClick={ handleUserLogout }>wyloguj się</Link>)
|
||||
</> : <>
|
||||
<Link to={'#'} onClick={ handleUserLogin }>zaloguj się</Link>
|
||||
</>;
|
||||
return <ul {...props}>
|
||||
{
|
||||
student ? <>
|
||||
<Trans t={ t } i18nKey="logged-in-as">logged in as <strong>{{ name: student.name }}</strong></Trans>
|
||||
{' '}
|
||||
(<Link to={'#'} onClick={ handleUserLogout }>{ t('logout') }</Link>)
|
||||
</> : <>
|
||||
<Link to={'#'} onClick={ handleUserLogin }>{ t('login') }</Link>
|
||||
</>
|
||||
}
|
||||
</ul>;
|
||||
}
|
||||
|
||||
const AppHeader = () => {
|
||||
return <header className="header">
|
||||
<div id="logo" className="header__logo">
|
||||
<Link to={ route('home') }>
|
||||
<img src="img/pg-logotyp.svg"/>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="header__nav">
|
||||
<nav className="header__top">
|
||||
<ul className="header__menu"></ul>
|
||||
<div className="header__user">
|
||||
<UserMenu />
|
||||
</div>
|
||||
<div className="header__divider" />
|
||||
<ul className="header__language-switcher">
|
||||
<li>pl</li>
|
||||
<li>en</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav className="header__bottom">
|
||||
<ul className="header__menu header__menu--main"></ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
const LanguageSwitcher = ({ className, ...props }: HTMLProps<HTMLUListElement>) => {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const handleLanguageChange = (language: string) => () => {
|
||||
i18n.changeLanguage(language);
|
||||
}
|
||||
|
||||
return <ul className={ classNames(className, "language-switcher") } { ...props }>
|
||||
{ ['pl', 'en'].map(language => <li key={ language }>
|
||||
<Link to="#" onClick={ handleLanguageChange(language) }>{ language }</Link>
|
||||
</li>) }
|
||||
</ul>
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@ -84,7 +79,24 @@ function App() {
|
||||
<MuiPickersUtilsProvider utils={ LocalizedMomentUtils } libInstance={ moment }>
|
||||
<ThemeProvider theme={ studentTheme }>
|
||||
<BrowserRouter>
|
||||
<AppHeader />
|
||||
<header className="header">
|
||||
<div id="logo" className="header__logo">
|
||||
<Link to={ route('home') }>
|
||||
<img src="img/pg-logotyp.svg"/>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="header__nav">
|
||||
<nav className="header__top">
|
||||
<ul className="header__menu"></ul>
|
||||
<UserMenu className="header__user"/>
|
||||
<div className="header__divider" />
|
||||
<LanguageSwitcher className="header__language-switcher"/>
|
||||
</nav>
|
||||
<nav className="header__bottom">
|
||||
<ul className="header__menu header__menu--main"></ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<Switch>{ routes.map(({ name, content, ...route }) => <Route { ...route } key={ name }>{ content() }</Route>) }</Switch>
|
||||
</BrowserRouter>
|
||||
</ThemeProvider>
|
||||
|
26
src/i18n.ts
Normal file
26
src/i18n.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: require('../translations/en.yaml'),
|
||||
},
|
||||
pl: {
|
||||
translation: require('../translations/pl.yaml'),
|
||||
}
|
||||
}
|
||||
|
||||
i18n
|
||||
.use(I18nextBrowserLanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
fallbackLng: "en",
|
||||
debug: true,
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
}
|
||||
})
|
||||
|
||||
export default i18n;
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import "./i18n"
|
||||
import App from './app';
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -4,25 +4,29 @@ import { Container, Typography, Button, Divider, Box, Stepper, Step, StepLabel,
|
||||
import { InternshipForm } from "@/forms/Internship";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { route } from "@/routing";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export const MainPage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return <Page my={6}>
|
||||
<Container>
|
||||
<Typography variant="h2">Moja praktyka</Typography>
|
||||
<Typography variant="h2">{ t("sections.my-internship.header") }</Typography>
|
||||
<Stepper orientation="vertical" nonLinear>
|
||||
<Step completed active={false}>
|
||||
<StepLabel>
|
||||
Uzupełnienie danych w systemie
|
||||
{ t('steps.personal-data.header') }
|
||||
<Box>
|
||||
<Typography variant="subtitle2" color="textSecondary">do: 05.07.2020</Typography>
|
||||
<Typography variant="subtitle2" color="textSecondary">{ t('until', { date: '05.07.2020' }) }</Typography>
|
||||
</Box>
|
||||
</StepLabel>
|
||||
<StepContent>lol</StepContent>
|
||||
</Step>
|
||||
<Step active>
|
||||
<StepLabel>Zgłoszenie praktyki</StepLabel>
|
||||
<StepLabel>{ t('steps.internship-proposal.header')}</StepLabel>
|
||||
<StepContent>
|
||||
<Button to={ route("internship_proposal") } variant="contained" color="primary" component={ RouterLink }>Formularz zgłoszenia praktyki</Button>
|
||||
<Button to={ route("internship_proposal") } variant="contained" color="primary" component={ RouterLink }>
|
||||
{ t('steps.internship-proposal.form') }
|
||||
</Button>
|
||||
</StepContent>
|
||||
</Step>
|
||||
</Stepper>
|
||||
|
@ -57,7 +57,11 @@
|
||||
text-transform: uppercase;
|
||||
|
||||
li {
|
||||
padding: 7px;
|
||||
list-style: none;
|
||||
|
||||
a {
|
||||
padding: 7px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
17
translations/en.yaml
Normal file
17
translations/en.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
login: login
|
||||
logout: logout
|
||||
logged-in-as: logged in as <1>{{ name }}</1>
|
||||
|
||||
until: until {{ date }}
|
||||
|
||||
sections:
|
||||
my-internship:
|
||||
header: "My internship"
|
||||
|
||||
steps:
|
||||
personal-data:
|
||||
header: "Personal data"
|
||||
internship-proposal:
|
||||
header: "Internship proposal"
|
||||
form: "Internship proposal form"
|
17
translations/pl.yaml
Normal file
17
translations/pl.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
login: zaloguj się
|
||||
logout: wyloguj się
|
||||
logged-in-as: zalogowany jako <1>{{ name }}</1>
|
||||
|
||||
until: do {{ date }}
|
||||
|
||||
sections:
|
||||
my-internship:
|
||||
header: "Moja praktyka"
|
||||
|
||||
steps:
|
||||
personal-data:
|
||||
header: "Uzupełnienie informacji"
|
||||
internship-proposal:
|
||||
header: "Zgłoszenie praktyki"
|
||||
form: "Formularz zgłaszania praktyki"
|
@ -34,6 +34,10 @@ const config = {
|
||||
}, {
|
||||
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
||||
use: 'file-loader'
|
||||
}, {
|
||||
test: /\.ya?ml$/,
|
||||
type: 'json',
|
||||
use: 'yaml-loader'
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
|
51
yarn.lock
51
yarn.lock
@ -926,6 +926,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.10.1":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99"
|
||||
integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.10.1", "@babel/template@^7.8.6":
|
||||
version "7.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
|
||||
@ -4388,6 +4395,13 @@ html-minifier-terser@^5.0.1:
|
||||
relateurl "^0.2.7"
|
||||
terser "^4.6.3"
|
||||
|
||||
html-parse-stringify2@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz#dc5670b7292ca158b7bc916c9a6735ac8872834a"
|
||||
integrity sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=
|
||||
dependencies:
|
||||
void-elements "^2.0.1"
|
||||
|
||||
html-webpack-plugin@4.0.0-beta.11:
|
||||
version "4.0.0-beta.11"
|
||||
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz#3059a69144b5aecef97708196ca32f9e68677715"
|
||||
@ -4492,6 +4506,20 @@ hyphenate-style-name@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
|
||||
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
|
||||
|
||||
i18next-browser-languagedetector@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-5.0.0.tgz#9e946ed2ea5514a636913fe020a32455e82946e3"
|
||||
integrity sha512-ekeKbRvTOsSOABSEPHFqyb6Q37JagZXjkISgQKHP84t/VZRW/B3FMVz+tBNQDVdZLsEaOe8fuJpeZsw2TvWeVQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
|
||||
i18next@^19.6.0:
|
||||
version "19.6.0"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.6.0.tgz#3881b8e476e494dcdadcc8983e594080417fd82e"
|
||||
integrity sha512-t+pA7iN2WtwS1UQc4PFKHDIO4HYZIl2Wo8UC8gqt70Q1qY50FflAF5vV4IbQEqy4DuK3I9wv3BL1PMvkk238WA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.1"
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
@ -7323,6 +7351,14 @@ react-error-overlay@^6.0.7:
|
||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
|
||||
integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==
|
||||
|
||||
react-i18next@^11.7.0:
|
||||
version "11.7.0"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.7.0.tgz#f27c4c237a274e007a48ac1210db83e33719908b"
|
||||
integrity sha512-8tvVkpuxQlubcszZON+jmoCgiA9gCZ74OAYli9KChPhETtq8pJsANBTe9KRLRLmX3ubumgvidURWr0VvKz1tww==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
html-parse-stringify2 "2.0.1"
|
||||
|
||||
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.9.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
@ -8910,6 +8946,11 @@ vm-browserify@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
|
||||
|
||||
void-elements@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
||||
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
|
||||
|
||||
watchpack-chokidar2@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0"
|
||||
@ -9290,7 +9331,15 @@ yallist@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
|
||||
yaml@^1.7.2:
|
||||
yaml-loader@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.6.0.tgz#fe1c48b9f4803dace55a59a1474e790ba6ab1b48"
|
||||
integrity sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow==
|
||||
dependencies:
|
||||
loader-utils "^1.4.0"
|
||||
yaml "^1.8.3"
|
||||
|
||||
yaml@^1.7.2, yaml@^1.8.3:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
|
||||
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
|
||||
|
Loading…
Reference in New Issue
Block a user