Add localization for header menus/some modals

This commit is contained in:
Justin Edmund 2022-03-04 18:42:06 -08:00
parent 5ea57f0e07
commit b91d84028f
7 changed files with 170 additions and 26 deletions

View file

@ -1,21 +1,24 @@
import React from 'react' import React from 'react'
import { useTranslation } from 'next-i18next'
import * as Dialog from '@radix-ui/react-dialog' import * as Dialog from '@radix-ui/react-dialog'
import CrossIcon from '~public/icons/Cross.svg' import CrossIcon from '~public/icons/Cross.svg'
import './index.scss' import './index.scss'
const AboutModal = () => { const AboutModal = () => {
const { t } = useTranslation('common')
return ( return (
<Dialog.Root> <Dialog.Root>
<Dialog.Trigger asChild> <Dialog.Trigger asChild>
<li className="MenuItem"> <li className="MenuItem">
<span>About</span> <span>{t('modals.about.title')}</span>
</li> </li>
</Dialog.Trigger> </Dialog.Trigger>
<Dialog.Portal> <Dialog.Portal>
<Dialog.Content className="About Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }> <Dialog.Content className="About Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
<div className="DialogHeader"> <div className="DialogHeader">
<Dialog.Title className="DialogTitle">About</Dialog.Title> <Dialog.Title className="DialogTitle">{t('menu.about')}</Dialog.Title>
<Dialog.Close className="DialogClose" asChild> <Dialog.Close className="DialogClose" asChild>
<span> <span>
<CrossIcon /> <CrossIcon />

View file

@ -98,6 +98,10 @@
font-size: $font-small; font-size: $font-small;
line-height: 1.1; line-height: 1.1;
max-width: 300px; max-width: 300px;
&.jp {
max-width: 270px;
}
} }
} }

View file

@ -1,6 +1,8 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useCookies } from 'react-cookie' import { useCookies } from 'react-cookie'
import { useRouter } from 'next/router'
import { useSnapshot } from 'valtio' import { useSnapshot } from 'valtio'
import { useTranslation } from 'next-i18next'
import * as Dialog from '@radix-ui/react-dialog' import * as Dialog from '@radix-ui/react-dialog'
import * as Switch from '@radix-ui/react-switch' import * as Switch from '@radix-ui/react-switch'
@ -15,8 +17,13 @@ import CrossIcon from '~public/icons/Cross.svg'
import './index.scss' import './index.scss'
const AccountModal = () => { const AccountModal = () => {
const { t } = useTranslation('common')
const { account } = useSnapshot(accountState) const { account } = useSnapshot(accountState)
const router = useRouter()
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
// Cookies // Cookies
const [accountCookies] = useCookies(['account']) const [accountCookies] = useCookies(['account'])
const [userCookies, setUserCookies] = useCookies(['user']) const [userCookies, setUserCookies] = useCookies(['user'])
@ -46,7 +53,7 @@ const AccountModal = () => {
const pictureOptions = ( const pictureOptions = (
pictureData.sort((a, b) => (a.name.en > b.name.en) ? 1 : -1).map((item, i) => { pictureData.sort((a, b) => (a.name.en > b.name.en) ? 1 : -1).map((item, i) => {
return ( return (
<option key={`picture-${i}`} value={item.filename}>{item.name.en}</option> <option key={`picture-${i}`} value={item.filename}>{item.name[locale]}</option>
) )
}) })
) )
@ -109,14 +116,14 @@ const AccountModal = () => {
<Dialog.Root open={open} onOpenChange={openChange}> <Dialog.Root open={open} onOpenChange={openChange}>
<Dialog.Trigger asChild> <Dialog.Trigger asChild>
<li className="MenuItem"> <li className="MenuItem">
<span>Settings</span> <span>{t('menu.settings')}</span>
</li> </li>
</Dialog.Trigger> </Dialog.Trigger>
<Dialog.Portal> <Dialog.Portal>
<Dialog.Content className="Account Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }> <Dialog.Content className="Account Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
<div className="DialogHeader"> <div className="DialogHeader">
<div className="DialogTop"> <div className="DialogTop">
<Dialog.Title className="SubTitle">Account Settings</Dialog.Title> <Dialog.Title className="SubTitle">{t('modals.settings.title')}</Dialog.Title>
<Dialog.Title className="DialogTitle">@{account.user?.username}</Dialog.Title> <Dialog.Title className="DialogTitle">@{account.user?.username}</Dialog.Title>
</div> </div>
<Dialog.Close className="DialogClose" asChild> <Dialog.Close className="DialogClose" asChild>
@ -129,7 +136,7 @@ const AccountModal = () => {
<form onSubmit={update}> <form onSubmit={update}>
<div className="field"> <div className="field">
<div className="left"> <div className="left">
<label>Picture</label> <label>{t('modals.settings.labels.picture')}</label>
</div> </div>
<div className={`preview ${pictureData.find(i => i.filename === picture)?.element}`}> <div className={`preview ${pictureData.find(i => i.filename === picture)?.element}`}>
@ -147,18 +154,18 @@ const AccountModal = () => {
</div> </div>
<div className="field"> <div className="field">
<div className="left"> <div className="left">
<label>Language</label> <label>{t('modals.settings.labels.language')}</label>
</div> </div>
<select name="language" onChange={handleLanguageChange} value={language} ref={languageSelect}> <select name="language" onChange={handleLanguageChange} value={language} ref={languageSelect}>
<option key="en" value="en">English</option> <option key="en" value="en">{t('modals.settings.language.english')}</option>
<option key="jp" value="jp">Japanese</option> <option key="jp" value="jp">{t('modals.settings.language.japanese')}</option>
</select> </select>
</div> </div>
<div className="field"> <div className="field">
<div className="left"> <div className="left">
<label>Private</label> <label>{t('modals.settings.labels.private')}</label>
<p>Hide your profile and prevent your grids from showing up in collections</p> <p className={locale}>{t('modals.settings.descriptions.private')}</p>
</div> </div>
<Switch.Root className="Switch" onCheckedChange={handlePrivateChange} checked={privateProfile}> <Switch.Root className="Switch" onCheckedChange={handlePrivateChange} checked={privateProfile}>
@ -166,7 +173,7 @@ const AccountModal = () => {
</Switch.Root> </Switch.Root>
</div> </div>
<Button>Save settings</Button> <Button>{t('modals.settings.buttons.confirm')}</Button>
</form> </form>
</Dialog.Content> </Dialog.Content>
<Dialog.Overlay className="Overlay" /> <Dialog.Overlay className="Overlay" />

View file

@ -90,14 +90,14 @@ const BottomHeader = () => {
<AlertDialog.Overlay className="Overlay" /> <AlertDialog.Overlay className="Overlay" />
<AlertDialog.Content className="Dialog"> <AlertDialog.Content className="Dialog">
<AlertDialog.Title className="DialogTitle"> <AlertDialog.Title className="DialogTitle">
{t('delete_team.title')} {t('modals.delete_team.title')}
</AlertDialog.Title> </AlertDialog.Title>
<AlertDialog.Description className="DialogDescription"> <AlertDialog.Description className="DialogDescription">
{t('delete_team.description')} {t('modals.delete_team.description')}
</AlertDialog.Description> </AlertDialog.Description>
<div className="actions"> <div className="actions">
<AlertDialog.Cancel className="Button modal">{t('delete_team.buttons.cancel')}</AlertDialog.Cancel> <AlertDialog.Cancel className="Button modal">{t('modals.delete_team.buttons.cancel')}</AlertDialog.Cancel>
<AlertDialog.Action className="Button modal destructive" onClick={(e) => deleteTeam(e)}>{t('delete_team.buttons.confirm')}</AlertDialog.Action> <AlertDialog.Action className="Button modal destructive" onClick={(e) => deleteTeam(e)}>{t('modals.delete_team.buttons.confirm')}</AlertDialog.Action>
</div> </div>
</AlertDialog.Content> </AlertDialog.Content>
</AlertDialog.Portal> </AlertDialog.Portal>

View file

@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import Link from 'next/link' import Link from 'next/link'
import { useCookies } from 'react-cookie' import { useCookies } from 'react-cookie'
import { useTranslation } from 'next-i18next'
import AboutModal from '~components/AboutModal' import AboutModal from '~components/AboutModal'
import AccountModal from '~components/AccountModal' import AccountModal from '~components/AccountModal'
@ -16,6 +17,8 @@ interface Props {
} }
const HeaderMenu = (props: Props) => { const HeaderMenu = (props: Props) => {
const { t } = useTranslation('common')
const [accountCookies] = useCookies(['account']) const [accountCookies] = useCookies(['account'])
const [userCookies] = useCookies(['user']) const [userCookies] = useCookies(['user'])
@ -35,22 +38,22 @@ const HeaderMenu = (props: Props) => {
/profile/${userCookies.user.picture}@2x.png 2x`} /profile/${userCookies.user.picture}@2x.png 2x`}
src={`/profile/${userCookies.user.picture}.png`} src={`/profile/${userCookies.user.picture}.png`}
/> />
</div </div>
></Link> </Link>
</li> </li>
<li className="MenuItem"> <li className="MenuItem">
<Link href={`/saved` || ''}>Saved</Link> <Link href={`/saved` || ''}>{t('menu.saved')}</Link>
</li> </li>
</div> </div>
<div className="MenuGroup"> <div className="MenuGroup">
<li className="MenuItem"> <li className="MenuItem">
<Link href='/teams'>Teams</Link> <Link href='/teams'>{t('menu.teams')}</Link>
</li> </li>
<li className="MenuItem disabled"> <li className="MenuItem disabled">
<div> <div>
<span>Guides</span> <span>{t('menu.guides')}</span>
<i className="tag">Coming Soon</i> <i className="tag">{t('coming_soon')}</i>
</div> </div>
</li> </li>
</div> </div>
@ -58,7 +61,7 @@ const HeaderMenu = (props: Props) => {
<AboutModal /> <AboutModal />
<AccountModal /> <AccountModal />
<li className="MenuItem" onClick={props.logout}> <li className="MenuItem" onClick={props.logout}>
<span>Logout</span> <span>{t('menu.logout')}</span>
</li> </li>
</div> </div>
</ul> </ul>
@ -74,13 +77,13 @@ const HeaderMenu = (props: Props) => {
</div> </div>
<div className="MenuGroup"> <div className="MenuGroup">
<li className="MenuItem"> <li className="MenuItem">
<Link href='/teams'>Teams</Link> <Link href='/teams'>{t('menu.teams')}</Link>
</li> </li>
<li className="MenuItem disabled"> <li className="MenuItem disabled">
<div> <div>
<span>Guides</span> <span>{t('menu.guides')}</span>
<i className="tag">Coming Soon</i> <i className="tag">{t('menu.logout')}</i>
</div> </div>
</li> </li>
</div> </div>

View file

@ -0,0 +1,63 @@
{
"buttons": {
"copy": "Copy link",
"delete": "Delete team",
"edit_info": "Edit info",
"hide_info": "Hide info",
"menu": "Menu",
"new": "New"
},
"modals": {
"about": {
"title": "About"
},
"delete_team": {
"title": "Delete team",
"description": "Are you sure you want to permanently delete this team?",
"buttons": {
"confirm": "Yes, delete",
"cancel": "Nevermind"
}
},
"settings": {
"title": "Account Settings",
"labels": {
"picture": "Picture",
"language": "Language",
"private": "Private"
},
"descriptions": {
"private": "Hide your profile and prevent your grids from showing up in collections"
},
"language": {
"english": "English",
"japanese": "Japanese"
},
"buttons": {
"confirm": "Save settings"
}
}
},
"menu": {
"about": "About",
"guides": "Guides",
"saved": "Saved",
"settings": "Settings",
"teams": "Teams",
"logout": "Logout"
},
"party": {
"segmented_control": {
"class": "Class",
"characters": "Characters",
"weapons": "Weapons",
"summons": "Summons"
}
},
"teams": {
"title": "Discover Teams",
"loading": "Loading teams...",
"not_found": "No teams found"
},
"coming_soon": "Coming Soon"
}

View file

@ -0,0 +1,64 @@
{
"buttons": {
"copy": "リンクをコピー",
"delete": "編成を削除",
"show_info": "詳細を編集",
"hide_info": "詳細を非表示",
"menu": "メニュー",
"new": "作成"
},
"modals": {
"about": {
"title": "このサイトについて"
},
"delete_team": {
"title": "編成を削除しますか",
"description": "編成を削除する操作は取り消せません。",
"buttons": {
"confirm": "削除",
"cancel": "キャンセル"
}
},
"settings": {
"title": "アカウント設定",
"labels": {
"picture": "プロフィール画像",
"language": "言語",
"private": "プライベート"
},
"descriptions": {
"private": "プロフィールを隠し、編成をコレクションに表示されないようにします"
},
"language": {
"english": "英語",
"japanese": "日本語"
},
"buttons": {
"confirm": "設定を保存する"
}
}
},
"menu": {
"about": "このサイトについて",
"guides": "攻略",
"saved": "保存した編成",
"settings": "アカウント設定",
"teams": "編成一覧",
"logout": "ログアウト"
},
"party": {
"segmented_control": {
"class": "ジョブ",
"characters": "キャラ",
"weapons": "武器",
"summons": "召喚石"
}
},
"teams": {
"title": "編成一覧",
"loading": "ロード中...",
"not_found": "編成は見つかりませんでした"
},
"coming_soon": "開発中"
}