Skip to content

Commit

Permalink
I18n (#3)
Browse files Browse the repository at this point in the history
* make locale toggle

* i18n next setup

* cleanup dependencies
  • Loading branch information
ann-kilzer authored Apr 21, 2024
1 parent e80a645 commit 1616fdd
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 10 deletions.
61 changes: 61 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
"@mui/icons-material": "5.15.15",
"@mui/material": "5.15.15",
"@vitest/coverage-istanbul": "1.5.0",
"i18next": "23.11.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-i18next": "14.1.0",
"react-router-dom": "6.22.3",
"styled-components": "6.1.8"
},
Expand Down
8 changes: 8 additions & 0 deletions src/@types/i18next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { resources, defaultNS } from './i18n';

declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: typeof defaultNS;
resources: typeof resources['en'];
}
}
31 changes: 31 additions & 0 deletions src/components/LocaleToggle/LocaleToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FC, useState } from 'react'
import ToggleButton from '@mui/material/ToggleButton'
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import { useTranslation } from 'react-i18next';
import Locale from '@/i18n/locales'

const LocaleToggle: FC = () => {
const [locale, setLocale] = useState(Locale.EN);
const { i18n } = useTranslation();

const handleChange = (_: React.MouseEvent<HTMLElement>, nextLocale: Locale) => {
const changeLanguage = async () => {
await i18n.changeLanguage(nextLocale).then(() =>
setLocale(nextLocale)
)
}
changeLanguage().catch((e: Error) => {
console.error(e)
})
}

return <ToggleButtonGroup
exclusive
value={locale}
onChange={handleChange}>
<ToggleButton value={Locale.EN}>English</ToggleButton>
<ToggleButton value={Locale.JA}>日本語</ToggleButton>
</ToggleButtonGroup>
}

export default LocaleToggle
3 changes: 2 additions & 1 deletion src/components/SideDrawer/DrawerContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ListItem from '@mui/material/ListItem'
import { useTheme } from '@mui/material/styles'
import useMediaQuery from '@mui/material/useMediaQuery'
import StyledNavLink from '../StyledNavLink/StyledNavLink'
import LocaleToggle from '../LocaleToggle/LocaleToggle'

const DrawerContents: FC = () => {
const theme = useTheme()
Expand All @@ -26,7 +27,7 @@ const DrawerContents: FC = () => {
<List>
{navList}
<ListItem>
Coming soon!
<LocaleToggle />
</ListItem>
</List>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import DrawerContents from '../DrawerContents'
describe('DrawerContents', () => {
it('should display the DrawerContents', async () => {
render(<DrawerContents />)
const home = await screen.findByText('Coming soon!')
expect(home).toBeVisible()
const japanese = await screen.findByText('日本語')
expect(japanese).toBeVisible()
})

it.todo('should show the NavLinks on mobile screens')
Expand Down
23 changes: 23 additions & 0 deletions src/i18n/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import i18next from 'i18next'
import { initReactI18next } from 'react-i18next'
import english from './en/translation.json'
import japanese from './ja/translation.json'
import Locale from './locales'

// eslint-disable-next-line @typescript-eslint/no-floating-promises
i18next.use(initReactI18next).init({
lng: Locale.EN, // if you're using a language detector, do not define the lng option
debug: true,
resources: {
en: {
translation: english
},
ja: {
translation: japanese
}

},
// if you see an error like: "Argument of type 'DefaultTFuncReturn' is not assignable to parameter of type xyz"
// set returnNull to false (and also in the i18next.d.ts options)
// returnNull: false,
});
5 changes: 5 additions & 0 deletions src/i18n/en/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"codeOfConduct": "Code of Conduct",
"helloWorld": "✨ Hello World ✨",
"joinUs": "✨ Join us on Slack ✨"
}
5 changes: 5 additions & 0 deletions src/i18n/ja/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"codeOfConduct": "行動規範",
"helloWorld": "✨ Hello 世界 ✨",
"joinUs": "✨ スラックに参加する ✨"
}
6 changes: 6 additions & 0 deletions src/i18n/locales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
enum Locale {
EN = 'en',
JA = 'ja'
}

export default Locale
1 change: 1 addition & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CssBaseline from '@mui/material/CssBaseline';
import Router from './routes/Router';
import GlobalStyles from '@mui/material/GlobalStyles';
import CustomThemeProvider from './theme/CustomThemeProvider';
import './i18n/config';
import './index.css'

import '@fontsource/noto-sans-jp/300.css'
Expand Down
13 changes: 10 additions & 3 deletions src/routes/BaseLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { FC } from 'react'
import { FC, Suspense } from 'react'
import Header from '@/components/Header/Header'
import Footer from '@/components/Footer/Footer'
import {
Outlet,
} from 'react-router-dom'

// loading component for suspense fallback
const Loader = () => (
<div>
<div>Loading...</div>
</div>
);

const BaseLayout: FC = () => {
return <>
return <Suspense fallback={<Loader />}>
<Header />
<Outlet />
<Footer />
</>
</Suspense>
}

export default BaseLayout
7 changes: 6 additions & 1 deletion src/routes/CodeOfConduct/CodeOfConduct.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import { FC } from 'react'
import Container from '@mui/material/Container'
import Stack from '@mui/material/Stack'
import { Typography } from '@mui/material'

import { useTranslation } from 'react-i18next';

const CodeOfConduct: FC = () => {
const { t } = useTranslation();

return <Container style={{ padding: 32 }}>
<Stack spacing={2}>
<Typography variant='h1'>
{t('codeOfConduct')}
</Typography>
<Typography variant='body2' >
Women in Software Engineering Japan (WiSE Japan) is dedicated to providing an empowering experience for everyone who participates in or supports our community. Our events are intended to inspire women to excel in technology careers, and anyone who is there for this purpose is welcome. Because we value the safety and security of our members and strive to have an inclusive community, we do not tolerate harassment of members or event participants in any form. This Code of Conduct was created to clearly define what we mean by a harassment-free experience, so that our community and those who support it are clear about our intent and have access to procedures for addressing issues, should they arise.
</Typography>
Expand Down
13 changes: 10 additions & 3 deletions src/routes/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import Stack from '@mui/material/Stack'
import Container from '@mui/material/Container'
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button'
import { useTranslation } from 'react-i18next';

const Home: FC = () => {
const { t } = useTranslation();

return <Container style={{ padding: 32 }}>
<Stack spacing={2}>
<Typography variant="h2">✨ Hello World ✨</Typography>
<Typography variant="h1">{t('helloWorld')}</Typography>
<Typography variant="body1">
Many of us were saddened to hear of the sudden closure of Women Who Code.
There is a need for an organization to empower diverse women in technology careers in Tokyo and across Japan.
Expand All @@ -23,8 +26,12 @@ const Home: FC = () => {
Software-adjacent roles like Data Science, Product, UI/UX, Machine Learning, etc., are welcome, too.
</Typography>

<Button variant='contained' href='https://join.slack.com/t/womencodersjapan/shared_invite/zt-2h79966bm-dE7SyiGvv2CXBxbz_0JzKw' target='_blank'>
✨ Join us on Slack ✨
<Button
variant='contained'
href='https://join.slack.com/t/womencodersjapan/shared_invite/zt-2h79966bm-dE7SyiGvv2CXBxbz_0JzKw'
target='_blank'
>
{t('joinUs')}
</Button>
</Stack>
</Container>
Expand Down
1 change: 1 addition & 0 deletions src/tests/customRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { render, RenderOptions } from '@testing-library/react'
import CssBaseline from '@mui/material/CssBaseline';
import CustomThemeProvider from '@/theme/CustomThemeProvider';
import { MemoryRouter } from 'react-router-dom';
import '@/i18n/config';

// eslint-disable-next-line react-refresh/only-export-components
const AllTheProviders = ({ children }: { children: React.ReactNode }) => {
Expand Down

0 comments on commit 1616fdd

Please sign in to comment.