Add i18next

context-store
Alfred Melch 5 years ago
parent f9ec31fd7a
commit ee62b85008

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": { "html-webpack-plugin": {
"version": "4.0.0-beta.11", "version": "4.0.0-beta.11",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz", "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": { "iconv-lite": {
"version": "0.4.24", "version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@ -9497,6 +9513,15 @@
"integrity": "sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==", "integrity": "sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==",
"dev": true "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": { "react-icons": {
"version": "3.8.0", "version": "3.8.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.8.0.tgz", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.8.0.tgz",
@ -11548,6 +11573,11 @@
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
"dev": true "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": { "walk-back": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz",

@ -18,8 +18,10 @@
"axios": "^0.19.0", "axios": "^0.19.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"debounce": "^1.2.0", "debounce": "^1.2.0",
"i18next": "^19.1.0",
"react": "^16.12.0", "react": "^16.12.0",
"react-dom": "^16.12.0", "react-dom": "^16.12.0",
"react-i18next": "^11.3.1",
"react-icons": "^3.8.0", "react-icons": "^3.8.0",
"react-redux": "^7.1.3", "react-redux": "^7.1.3",
"redux": "^4.0.4", "redux": "^4.0.4",

@ -1,15 +1,19 @@
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next'
import { RsvpReader } from './components/RsvpReader' import { RsvpReader } from './components/RsvpReader'
import { GutenbergSearch } from './components/GutenbergSearch' import { GutenbergSearch } from './components/GutenbergSearch'
import './App.css' import './App.css'
import { LangSelect } from './components/LangSelect'
export const App = () => { export const App = () => {
const { t } = useTranslation()
return ( return (
<> <>
<header> <header>
<h1>The fast reader</h1> <h1>{t('title')}</h1>
<LangSelect />
</header> </header>
<main> <main>
<RsvpReader></RsvpReader> <RsvpReader></RsvpReader>

@ -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 { setMaxLength, setWpm, setOffset, setLang } from '../store/actions'
import { Slider } from './Slider' import { Slider } from './Slider'
import { selectOffset, selectLang } from '../store/selectors' import { selectOffset, selectLang } from '../store/selectors'
import { useTranslation } from 'react-i18next'
const availableLanguages = ['en', 'de'] const availableLanguages = ['en', 'de']
export const Options = () => { export const Options = () => {
const { t } = useTranslation()
const dispatch = useDispatch() const dispatch = useDispatch()
const maxLength = useSelector(state => state.maxLength) const maxLength = useSelector(state => state.maxLength)
const wpm = useSelector(state => state.wpm) const wpm = useSelector(state => state.wpm)
@ -17,23 +19,23 @@ export const Options = () => {
return ( return (
<div> <div>
<h2>Options</h2> <h2>{t('options.title')}</h2>
<Slider <Slider
title={'Maximum segment length'} title={t('options.maxLength')}
min={3} min={3}
max={15} max={15}
value={maxLength} value={maxLength}
onChange={debounce(val => dispatch(setMaxLength(val)), 100)} onChange={debounce(val => dispatch(setMaxLength(val)), 100)}
/> />
<Slider <Slider
title={'Words per minute'} title={t('options.wpm')}
min={100} min={100}
max={1000} max={1000}
value={wpm} value={wpm}
onChange={debounce(val => dispatch(setWpm(val)), 50)} onChange={debounce(val => dispatch(setWpm(val)), 50)}
/> />
<Slider <Slider
title={'Offset from center'} title={t('options.offset')}
min={-50} min={-50}
max={50} max={50}
value={offset} value={offset}

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

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

@ -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 { App } from './App'
import { store } from './store/index.js' import { store } from './store/index.js'
import './i18n'
function createRootElement() { function createRootElement() {
const body = document.getElementsByTagName('body')[0] const body = document.getElementsByTagName('body')[0]
const root = document.createElement('div') const root = document.createElement('div')

Loading…
Cancel
Save