1
0
mirror of https://github.com/uetchy/namae.git synced 2025-08-20 09:58:13 +09:00

feat: i18n

This commit is contained in:
2019-08-03 13:36:29 +09:00
parent 984032c2ae
commit c1d0d3fd43
19 changed files with 239 additions and 34 deletions

View File

@@ -1,5 +1,7 @@
import React, { useState, useEffect, useRef } from 'react'
import styled, { createGlobalStyle } from 'styled-components'
import { Helmet } from 'react-helmet'
import { useTranslation } from 'react-i18next'
import Welcome from './components/Welcome'
import Footer from './components/Footer'
@@ -25,6 +27,7 @@ export default function App() {
const [query, setQuery] = useDeferredState(1000)
const [inputValue, setInputValue] = useState('')
const inputRef = useRef()
const { t } = useTranslation()
const queryGiven = query && query.length > 0
@@ -44,10 +47,18 @@ export default function App() {
return (
<>
<GlobalStyle />
<Helmet>
<title>namaæ {t('title')}</title>
</Helmet>
<Header>
<InputContainer>
<Logo onClick={onLogoClick}>namæ</Logo>
<Input onChange={onInputChange} value={inputValue} ref={inputRef} />
<Input
onChange={onInputChange}
value={inputValue}
ref={inputRef}
placeholder={t('placeholder')}
/>
</InputContainer>
</Header>
<Content>
@@ -146,7 +157,6 @@ const Logo = styled.div`
const Input = styled.input.attrs({
type: 'text',
placeholder: 'search',
autocomplete: 'off',
autocorrect: 'off',
autocapitalize: 'off',
@@ -158,6 +168,7 @@ const Input = styled.input.attrs({
text-align: center;
font-family: monospace;
font-size: 5rem;
line-height: 1.2em;
${mobile} {
font-size: 2rem;

View File

@@ -1,5 +1,6 @@
import React from 'react'
import styled from 'styled-components'
import { useTranslation } from 'react-i18next'
import { FaMapSigns } from 'react-icons/fa'
import { FaGithub } from 'react-icons/fa'
@@ -16,48 +17,47 @@ import { FaGem } from 'react-icons/fa'
import { mobile } from '../util/css'
export default function Welcome() {
const { t } = useTranslation()
return (
<Container>
<Hero>
<Header>name new project</Header>
<Text>
namæ saves your time searching around registries and checking if the
desired name is ready for use.
</Text>
<Header>{t('title')}</Header>
<Text>{t('description')}</Text>
</Hero>
<List>
<ListItem>
<FaMapSigns /> Domains
<FaMapSigns /> {t('providers.domains')}
</ListItem>
<ListItem>
<FaGithub /> GitHub Organization
<FaGithub /> {t('providers.github')}
</ListItem>
<ListItem>
<FaNpm /> npm
<FaNpm /> {t('providers.npm')}
</ListItem>
<ListItem>
<FaPython /> PyPI
<FaPython /> {t('providers.pypi')}
</ListItem>
<ListItem>
<FaGem /> RubyGems
<FaGem /> {t('providers.rubygems')}
</ListItem>
<ListItem>
<DiRust /> Rust
<DiRust /> {t('providers.rust')}
</ListItem>
<ListItem>
<IoIosBeer /> Homebrew
<IoIosBeer /> {t('providers.homebrew')}
</ListItem>
<ListItem>
<FaJsSquare /> js.org
<FaJsSquare /> {t('providers.jsorg')}
</ListItem>
<ListItem>
<FaAws /> AWS S3 Bucket
<FaAws /> {t('providers.s3')}
</ListItem>
<ListItem>
<FaTwitter /> Twitter
<FaTwitter /> {t('providers.twitter')}
</ListItem>
<ListItem>
<FaSlack /> Slack
<FaSlack /> {t('providers.slack')}
</ListItem>
</List>
</Container>
@@ -82,8 +82,12 @@ const Container = styled.div`
const Header = styled.h1`
font-size: 3.5em;
line-height: 0.8em;
line-height: 1em;
padding-bottom: 30px;
${mobile} {
font-size: 3em;
}
`
const Text = styled.p`

View File

@@ -1,13 +1,15 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { DiRust } from 'react-icons/di'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function CratesioCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card title="Rust" key={lowerCase} nameList={[lowerCase]}>
<Card title={t('providers.rust')} key={lowerCase} nameList={[lowerCase]}>
{(name) => (
<DedicatedAvailability
name={name}

View File

@@ -1,14 +1,16 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaMapSigns } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function DomainCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card
title="Domain"
title={t('providers.domains')}
key={lowerCase}
nameList={[`${lowerCase}.com`, `${lowerCase}app.com`, `${lowerCase}.app`]}
alternativeList={[

View File

@@ -1,15 +1,17 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaGithub } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
import { capitalize } from '../../util/text'
export default function GithubCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card
title="GitHub Organization"
title={t('providers.github')}
key={name}
nameList={[name]}
alternativeList={[

View File

@@ -1,13 +1,18 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { IoIosBeer } from 'react-icons/io'
import { Card } from '../Cards'
import { ExistentialAvailability } from '../Availability'
export default function HomebrewCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card title="Homebrew" key={lowerCase} nameList={[lowerCase]}>
<Card
title={t('providers.homebrew')}
key={lowerCase}
nameList={[lowerCase]}>
{(name) => (
<>
<ExistentialAvailability

View File

@@ -1,13 +1,15 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaJsSquare } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function JsOrgCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card title="js.org" key={lowerCase} nameList={[lowerCase]}>
<Card title={t('providers.jsorg')} key={lowerCase} nameList={[lowerCase]}>
{(name) => (
<DedicatedAvailability
name={`${name}.js.org`}

View File

@@ -1,14 +1,16 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaNpm } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function NpmCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card
title="npm"
title={t('providers.npm')}
key={lowerCase}
nameList={[lowerCase]}
alternativeList={[`${lowerCase}-js`]}>

View File

@@ -1,13 +1,16 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaPython } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
import { capitalize } from '../../util/text'
export default function PypiCard({ name }) {
const { t } = useTranslation()
return (
<Card
title="PyPI"
title={t('providers.pypi')}
key={name}
nameList={[name]}
alternativeList={[`Py${capitalize(name)}`]}>

View File

@@ -1,12 +1,15 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaGem } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function RubyGemsCard({ name }) {
const { t } = useTranslation()
return (
<Card
title="RubyGems"
title={t('providers.rubygems')}
key={name}
nameList={[name]}
alternativeList={[`${name.toLowerCase()}-rb`]}>

View File

@@ -1,13 +1,15 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaAws } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function S3Card({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card title="AWS S3" key={lowerCase} nameList={[lowerCase]}>
<Card title={t('providers.s3')} key={lowerCase} nameList={[lowerCase]}>
{(name) => (
<DedicatedAvailability
name={name}

View File

@@ -1,13 +1,15 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaSlack } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
export default function SlackCard({ name }) {
const { t } = useTranslation()
const lowerCase = name.toLowerCase()
return (
<Card title="Slack" key={lowerCase} nameList={[lowerCase]}>
<Card title={t('providers.slack')} key={lowerCase} nameList={[lowerCase]}>
{(name) => (
<DedicatedAvailability
name={name}

View File

@@ -1,13 +1,16 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaTwitter } from 'react-icons/fa'
import { Card } from '../Cards'
import { DedicatedAvailability } from '../Availability'
import { capitalize } from '../../util/text'
export default function TwitterCard({ name }) {
const { t } = useTranslation()
return (
<Card
title="Twitter"
title={t('providers.twitter')}
key={name}
nameList={[name]}
alternativeList={[

25
web/src/i18n.js Normal file
View File

@@ -0,0 +1,25 @@
import i18n from 'i18next'
import Backend from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
i18n
// load translation using xhr -> see /public/locales
// learn more: https://github.com/i18next/i18next-xhr-backend
.use(Backend)
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
.use(LanguageDetector)
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
fallbackLng: 'en',
debug: false,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
})
export default i18n

View File

@@ -1,10 +1,34 @@
import React from 'react'
import React, { Suspense } from 'react'
import styled from 'styled-components'
import ReactDOM from 'react-dom'
import ReactGA from 'react-ga'
import BarLoader from 'react-spinners/BarLoader'
import App from './App'
import * as serviceWorker from './serviceWorker'
ReactDOM.render(<App />, document.getElementById('root'))
import './i18n'
const Fallback = () => (
<Container>
<BarLoader />
</Container>
)
const Container = styled.div`
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`
ReactDOM.render(
<Suspense fallback={<Fallback />}>
<App />
</Suspense>,
document.getElementById('root')
)
ReactGA.initialize('UA-28919359-15')
ReactGA.pageview(window.location.pathname + window.location.search)