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", | ||||
|  | ||||
							
								
								
									
										90
									
								
								src/app.tsx
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								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,42 +45,33 @@ const UserMenu = () => { | ||||
|         dispatch({ type: StudentActions.Logout }) | ||||
|     } | ||||
| 
 | ||||
|     return student ? <> | ||||
|         zalogowany jako: <strong>Jan Kowalski</strong> | ||||
|     return <ul {...props}> | ||||
|         { | ||||
|             student ? <> | ||||
|                 <Trans t={ t } i18nKey="logged-in-as">logged in as <strong>{{ name: student.name }}</strong></Trans> | ||||
|                 {' '} | ||||
|         (<Link to={'#'} onClick={ handleUserLogout }>wyloguj się</Link>) | ||||
|                 (<Link to={'#'} onClick={ handleUserLogout }>{ t('logout') }</Link>) | ||||
|             </> : <> | ||||
|         <Link to={'#'} onClick={ handleUserLogin }>zaloguj się</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> | ||||
| 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> | ||||
|             </nav> | ||||
|             <nav className="header__bottom"> | ||||
|                 <ul className="header__menu header__menu--main"></ul> | ||||
|             </nav> | ||||
|         </div> | ||||
|     </header> | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| function App() { | ||||
|     return ( | ||||
|         <Provider store={ store }> | ||||
| @ -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