Add i18next
This commit is contained in:
parent
f9ec31fd7a
commit
ee62b85008
30
package-lock.json
generated
30
package-lock.json
generated
@ -5475,6 +5475,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-parse-stringify2": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
|
||||
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
|
||||
"requires": {
|
||||
"void-elements": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"html-webpack-plugin": {
|
||||
"version": "4.0.0-beta.11",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz",
|
||||
@ -5650,6 +5658,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"i18next": {
|
||||
"version": "19.1.0",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-19.1.0.tgz",
|
||||
"integrity": "sha512-ISbmukX4L6Dz0QoH9+EW1AnBw7j+NRLoMu9uLPMaNSSTP9Eie9/oUL0dOyWX15baB3gYOpkHJpGZRHOqcnl0ew==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@ -9497,6 +9513,15 @@
|
||||
"integrity": "sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==",
|
||||
"dev": true
|
||||
},
|
||||
"react-i18next": {
|
||||
"version": "11.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.3.1.tgz",
|
||||
"integrity": "sha512-S/CWHcnew1lXo8HeniGhBU5kTmPhZ4w4rtA4m/gDN07soCtKKYSAcLNm7zhwjI2OSR4Skd0vOtzNp/FzEEjxIw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"html-parse-stringify2": "2.0.1"
|
||||
}
|
||||
},
|
||||
"react-icons": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.8.0.tgz",
|
||||
@ -11548,6 +11573,11 @@
|
||||
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
|
||||
"dev": true
|
||||
},
|
||||
"void-elements": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
|
||||
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
|
||||
},
|
||||
"walk-back": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz",
|
||||
|
@ -18,8 +18,10 @@
|
||||
"axios": "^0.19.0",
|
||||
"classnames": "^2.2.6",
|
||||
"debounce": "^1.2.0",
|
||||
"i18next": "^19.1.0",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-i18next": "^11.3.1",
|
||||
"react-icons": "^3.8.0",
|
||||
"react-redux": "^7.1.3",
|
||||
"redux": "^4.0.4",
|
||||
|
@ -1,15 +1,19 @@
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { RsvpReader } from './components/RsvpReader'
|
||||
import { GutenbergSearch } from './components/GutenbergSearch'
|
||||
|
||||
import './App.css'
|
||||
import { LangSelect } from './components/LangSelect'
|
||||
|
||||
export const App = () => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<h1>The fast reader</h1>
|
||||
<h1>{t('title')}</h1>
|
||||
<LangSelect />
|
||||
</header>
|
||||
<main>
|
||||
<RsvpReader></RsvpReader>
|
||||
|
22
src/components/LangSelect.js
Normal file
22
src/components/LangSelect.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { languages } from '../i18n'
|
||||
|
||||
export const LangSelect = () => {
|
||||
const { i18n } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<select
|
||||
value={i18n.language}
|
||||
onChange={evt => i18n.changeLanguage(evt.target.value)}
|
||||
>
|
||||
{languages.map(lng => (
|
||||
<option key={lng} value={lng}>
|
||||
{lng}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</>
|
||||
)
|
||||
}
|
@ -5,10 +5,12 @@ import { debounce } from 'debounce'
|
||||
import { setMaxLength, setWpm, setOffset, setLang } from '../store/actions'
|
||||
import { Slider } from './Slider'
|
||||
import { selectOffset, selectLang } from '../store/selectors'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const availableLanguages = ['en', 'de']
|
||||
|
||||
export const Options = () => {
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useDispatch()
|
||||
const maxLength = useSelector(state => state.maxLength)
|
||||
const wpm = useSelector(state => state.wpm)
|
||||
@ -17,23 +19,23 @@ export const Options = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Options</h2>
|
||||
<h2>{t('options.title')}</h2>
|
||||
<Slider
|
||||
title={'Maximum segment length'}
|
||||
title={t('options.maxLength')}
|
||||
min={3}
|
||||
max={15}
|
||||
value={maxLength}
|
||||
onChange={debounce(val => dispatch(setMaxLength(val)), 100)}
|
||||
/>
|
||||
<Slider
|
||||
title={'Words per minute'}
|
||||
title={t('options.wpm')}
|
||||
min={100}
|
||||
max={1000}
|
||||
value={wpm}
|
||||
onChange={debounce(val => dispatch(setWpm(val)), 50)}
|
||||
/>
|
||||
<Slider
|
||||
title={'Offset from center'}
|
||||
title={t('options.offset')}
|
||||
min={-50}
|
||||
max={50}
|
||||
value={offset}
|
||||
|
10
src/i18n/de.json
Normal file
10
src/i18n/de.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "Der schnelle leser",
|
||||
"search": "Suche",
|
||||
"options": {
|
||||
"title": "Optionen",
|
||||
"maxLength": "Maximale Segmentlänge",
|
||||
"wpm": "Wörter pro Minute",
|
||||
"offset": "Versatz der Wortanzeige"
|
||||
}
|
||||
}
|
10
src/i18n/en.json
Normal file
10
src/i18n/en.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"title": "The Fast Reader",
|
||||
"search": "Search",
|
||||
"options": {
|
||||
"title": "Options",
|
||||
"maxLength": "Maximum segment length",
|
||||
"wpm": "Words per minute",
|
||||
"offset": "Offset from center"
|
||||
}
|
||||
}
|
22
src/i18n/index.js
Normal file
22
src/i18n/index.js
Normal file
@ -0,0 +1,22 @@
|
||||
import i18n from 'i18next'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
|
||||
import de from './de.json'
|
||||
import en from './en.json'
|
||||
|
||||
const resources = {
|
||||
en: { translation: en },
|
||||
de: { translation: de }
|
||||
}
|
||||
|
||||
console.log(de, en)
|
||||
i18n.use(initReactI18next).init({
|
||||
resources,
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
}
|
||||
})
|
||||
|
||||
export const languages = Object.keys(resources)
|
@ -7,6 +7,8 @@ import { Provider } from 'react-redux'
|
||||
import { App } from './App'
|
||||
import { store } from './store/index.js'
|
||||
|
||||
import './i18n'
|
||||
|
||||
function createRootElement() {
|
||||
const body = document.getElementsByTagName('body')[0]
|
||||
const root = document.createElement('div')
|
||||
|
Loading…
Reference in New Issue
Block a user