Skip to content

Commit

Permalink
feat(v2): add react-i18next and associated boilerplate for interface … (
Browse files Browse the repository at this point in the history
#3823)

* feat(v2): add react-i18next and associated boilerplate for interface i18n

* remove http backend

* address comments from karrui

* fix typo in types
  • Loading branch information
frankchn authored May 5, 2022
1 parent d481a78 commit 9640d77
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 3 deletions.
1 change: 1 addition & 0 deletions frontend/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
'@storybook/addon-essentials',
'@storybook/addon-a11y',
'storybook-preset-craco',
'storybook-react-i18next',
{
name: 'storybook-addon-turbo-build',
options: {
Expand Down
6 changes: 6 additions & 0 deletions frontend/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { initialize, mswDecorator } from 'msw-storybook-addon'
import { AuthProvider } from '~contexts/AuthContext'
import * as dayjsUtils from '~utils/dayjs'

import i18n from '../src/i18n/i18n'
import { theme } from '../src/theme'

import { StorybookTheme } from './themes'
Expand Down Expand Up @@ -41,6 +42,11 @@ const withHelmet: DecoratorFn = (storyFn) => (
export const decorators = [withReactQuery, withChakra, withHelmet, mswDecorator]

export const parameters = {
i18n,
locale: 'en-SG',
locales: {
'en-SG': 'English',
},
docs: {
theme: StorybookTheme.docs,
inlineStories: true,
Expand Down
147 changes: 145 additions & 2 deletions frontend/package-lock.json

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

6 changes: 6 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
"file-saver": "^2.0.5",
"focus-visible": "^5.2.0",
"framer-motion": "^5.4.5",
"i18next": "^21.6.16",
"i18next-browser-languagedetector": "^6.1.4",
"i18next-icu": "^2.0.3",
"immer": "^9.0.6",
"intl-messageformat": "^9.13.0",
"jszip": "^3.7.1",
"libphonenumber-js": "^1.9.44",
"lodash": "^4.17.21",
Expand All @@ -36,6 +40,7 @@
"react-helmet-async": "^1.2.3",
"react-highlight-words": "^0.17.0",
"react-hook-form": "^7.28.0",
"react-i18next": "^11.16.7",
"react-icons": "^4.3.1",
"react-markdown": "^7.1.1",
"react-query": "^3.34.2",
Expand Down Expand Up @@ -158,6 +163,7 @@
"rimraf": "^3.0.2",
"storybook-addon-turbo-build": "^1.1.0",
"storybook-preset-craco": "0.0.6",
"storybook-react-i18next": "^1.0.20",
"ts-jest": "^27.1.1",
"worker-loader": "^3.0.8"
},
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/features/login/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Link as ReactLink } from 'react-router-dom'
import {
Box,
Expand Down Expand Up @@ -134,6 +135,7 @@ const NonMobileSidebarGridArea: FC = ({ children }) => (
export const LoginPage = (): JSX.Element => {
const [, setIsAuthenticated] = useLocalStorage<boolean>(LOGGED_IN_KEY)
const [email, setEmail] = useState<string>()
const { t } = useTranslation()

const currentYear = new Date().getFullYear()
// `xs` breakpoint needs to be explicitly set, suspect ChakraUI bug where xs
Expand Down Expand Up @@ -183,7 +185,7 @@ export const LoginPage = (): JSX.Element => {
color="white"
mb="2.5rem"
>
Build secure government forms in minutes
{t('general.slogan')}
</Text>
<LoginImage aria-hidden />
</NonMobileSidebarGridArea>
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/i18n/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { initReactI18next } from 'react-i18next'
import i18n from 'i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import ICU from 'i18next-icu'

import { locales } from './locales'

i18n
.use(ICU)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources: locales,
fallbackLng: 'en-SG',
debug: true,
interpolation: {
escapeValue: false, // react already safes from xss
},
})
export default i18n
9 changes: 9 additions & 0 deletions frontend/src/i18n/locales/en-sg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Translation from './types'

export const enSG: Translation = {
translation: {
general: {
slogan: 'Build secure government forms in minutes',
},
},
}
7 changes: 7 additions & 0 deletions frontend/src/i18n/locales/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ResourceLanguage } from 'i18next'

import { enSG } from './en-sg'

export const locales = {
'en-SG': enSG as unknown as ResourceLanguage,
}
9 changes: 9 additions & 0 deletions frontend/src/i18n/locales/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
interface Translation {
translation: {
general: {
slogan: string
}
}
}

export default Translation
9 changes: 9 additions & 0 deletions frontend/src/i18n/react-i18next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'react-i18next'

import { enSG } from './locales/en-sg'

declare module 'react-i18next' {
interface CustomTypeOptions {
resources: typeof enSG
}
}
1 change: 1 addition & 0 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'focus-visible/dist/focus-visible.min.js'
import './assets/fonts/inter.css'
import './i18n/i18n'

import * as React from 'react'
import ReactDOM from 'react-dom'
Expand Down

0 comments on commit 9640d77

Please sign in to comment.