Add i18next

This commit is contained in:
Alfred Melch 2020-01-31 22:15:04 +01:00
parent f9ec31fd7a
commit ee62b85008
9 changed files with 109 additions and 5 deletions

30
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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>

View 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>
</>
)
}

View File

@ -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
View 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
View 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
View 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)

View File

@ -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')