Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Small fixes to language switcher #326

Merged
merged 5 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions src/renderer/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import logger from '../logger'
import theme from './theme'
import Home from './components/Home'

const locale = ipcRenderer.sendSync('get-locale') // navigator.language.slice(0, 2)
const initialLocale = ipcRenderer.sendSync('get-locale') // navigator.language.slice(0, 2)

const mdMsgs = {
en: require('../../translations/en.json'),
Expand All @@ -29,16 +29,30 @@ const allMsgs = {
pt: { ...mdMsgs.pt, ...mfMsgs.pt }
}

const App = () => (
<StylesProvider injectFirst>
<ThemeProvider theme={theme}>
<CssBaseline />
<IntlProvider locale={locale} messages={allMsgs[locale]}>
<Home />
</IntlProvider>
</ThemeProvider>
</StylesProvider>
)
const App = () => {
const [locale, setLocale] = React.useState(initialLocale)

const handleLanguageChange = React.useCallback(lang => {
ipcRenderer.send('set-locale', lang)
setLocale(lang)
// Ideally this would just re-render the app in the new locale, but the way
// we squeeze iD editor into React and patch in React Components on top of
// it, trying to call `id.ui().restart(locale)` causes problems, so we
// refresh instead
ipcRenderer.send('force-refresh-window')
}, [])

return (
<StylesProvider injectFirst>
<ThemeProvider theme={theme}>
<CssBaseline />
<IntlProvider locale={locale} messages={allMsgs[locale]}>
<Home onSelectLanguage={handleLanguageChange} />
</IntlProvider>
</ThemeProvider>
</StylesProvider>
)
}

ReactDOM.render(<App />, document.getElementById('root'))

Expand Down
14 changes: 10 additions & 4 deletions src/renderer/components/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function TabPanel (props) {

const useTabIndex = createPersistedState('currentView')

export default function Home () {
export default function Home ({ onSelectLanguage }) {
const [dialog, setDialog] = React.useState()
const [tabIndex, setTabIndex] = useTabIndex(0)
const { formatMessage: t } = useIntl()
Expand All @@ -171,7 +171,10 @@ export default function Home () {
ipcRenderer.on('force-refresh-window', refreshPage)
return () => {
ipcRenderer.removeListener('open-latlon-dialog', openLatLonDialog)
ipcRenderer.removeListener('change-language-request', openChangeLangDialog)
ipcRenderer.removeListener(
'change-language-request',
openChangeLangDialog
)
ipcRenderer.removeListener('force-refresh-window', openLatLonDialog)
}
}, [])
Expand Down Expand Up @@ -203,9 +206,12 @@ export default function Home () {
</TabContent>
<ChangeLanguage
open={dialog === 'ChangeLanguage'}
onClose={() => {
onCancel={() => {
setDialog(null)
}}
onSelectLanguage={lang => {
onSelectLanguage(lang)
setDialog(null)
ipcRenderer.send('force-refresh-window') // TODO: can we do this without sending ipc?
}}
/>
<LatLonDialog
Expand Down
13 changes: 11 additions & 2 deletions src/renderer/components/MapEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const MapEditor = () => {
const rootRef = React.useRef()
const id = React.useRef()
const customDefs = React.useRef()
const { formatMessage: t } = useIntl()
const { formatMessage: t, locale } = useIntl()
const [toolbarEl, setToolbarEl] = React.useState()

const zoomToData = React.useCallback((_, loc) => {
Expand Down Expand Up @@ -161,6 +161,10 @@ const MapEditor = () => {
.preauth({ url: serverUrl })
.minEditableZoom(window.localStorage.getItem('minEditableZoom') || 14)

// Calling iD.coreContext() detects the locale from the browser. We need
// to override it with the app locale, before we call ui()
id.current.locale(locale)

if (!customDefs.current) {
customDefs.current = id.current
.container()
Expand Down Expand Up @@ -224,7 +228,12 @@ const MapEditor = () => {
// setTimeout(() => id.current.flush(), 1500)
})
},
[t]
// This should have a dependency of `t` and `locale`, so that it re-runs if
// the locale or the `t` function changes, but we don't have an easy way to
// teardown iD editor and then recreate it, so we need to never re=-run this
// effect
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
)

function updateSettings () {
Expand Down
49 changes: 29 additions & 20 deletions src/renderer/components/dialogs/ChangeLanguage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import DialogContent from '@material-ui/core/DialogContent'
import DialogTitle from '@material-ui/core/DialogTitle'
import FormControl from '@material-ui/core/FormControl'
import React, { useState } from 'react'
import { ipcRenderer } from 'electron'

import { defineMessages, useIntl } from 'react-intl'

Expand All @@ -20,25 +19,28 @@ const languages = {

const m = defineMessages({
'dialog-enter-language': 'Choose a language',
'button-submit': 'Submit'
'button-submit': 'Submit',
'button-cancel': 'Cancel'
})

const ChangeLanguage = ({ onClose, open }) => {
const { formatMessage: t } = useIntl()
const [lang, setLang] = useState()

const submitHandler = event => {
ipcRenderer.send('set-locale', lang)
onClose()
if (event) {
event.preventDefault()
event.stopPropagation()
}
return false
const ChangeLanguage = ({ onCancel, onSelectLanguage, open }) => {
const { formatMessage: t, locale } = useIntl()
// Set default state to app locale
const [lang, setLang] = useState(locale)

const submitHandler = () => {
onSelectLanguage(lang)
}

const closeHandler = () => {
// This will remember state between open/close, so if the user cancels this
// should reset to the currently selected locale
setLang(locale)
onCancel()
}

return (
<Dialog open={open} onClose={onClose}>
<Dialog open={open} onClose={onCancel} fullWidth maxWidth='xs'>
<DialogTitle>{t(m['dialog-enter-language'])}</DialogTitle>
<DialogContent>
<FormControl>
Expand All @@ -47,15 +49,22 @@ const ChangeLanguage = ({ onClose, open }) => {
value={lang}
onChange={event => setLang(event.target.value)}
>
{Object.keys(languages).map((code) => (
<MenuItem key={code} value={code}>{languages[code]} ({code})</MenuItem>
{Object.keys(languages).map(code => (
<MenuItem key={code} value={code}>
{languages[code]} ({code})
</MenuItem>
))}
</Select>
<DialogActions>
<Button onClick={submitHandler}>{t(m['button-submit'])}</Button>
</DialogActions>
</FormControl>
</DialogContent>
<DialogActions>
<Button color='default' onClick={closeHandler}>
{t(m['button-cancel'])}
</Button>
<Button color='primary' onClick={submitHandler}>
{t(m['button-submit'])}
</Button>
</DialogActions>
</Dialog>
)
}
Expand Down