From b1f417cbfb2a4a0d721e0fd43d97a85d89d3336b Mon Sep 17 00:00:00 2001 From: NEONKID Date: Sun, 15 Mar 2020 18:46:39 +0900 Subject: [PATCH 01/10] Remove previous translate files.. --- src/components/Server/index.tsx | 9 ------- src/locale/en/index.tsx | 44 --------------------------------- src/locale/index.tsx | 5 ---- src/locale/jp/index.tsx | 44 --------------------------------- src/locale/ko/index.tsx | 44 --------------------------------- 5 files changed, 146 deletions(-) delete mode 100644 src/components/Server/index.tsx delete mode 100644 src/locale/en/index.tsx delete mode 100644 src/locale/index.tsx delete mode 100644 src/locale/jp/index.tsx delete mode 100644 src/locale/ko/index.tsx diff --git a/src/components/Server/index.tsx b/src/components/Server/index.tsx deleted file mode 100644 index eefb793..0000000 --- a/src/components/Server/index.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import firebase from 'firebase/app'; -import 'firebase/firestore'; -import 'firebase/storage'; - -import config from './config.json'; - -const fb = firebase.initializeApp(config); - -export default fb; diff --git a/src/locale/en/index.tsx b/src/locale/en/index.tsx deleted file mode 100644 index d69c42d..0000000 --- a/src/locale/en/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -const ENG = { - en: { - 'menu-resume': 'Resume', - 'menu-portfolio': 'Portfolio', - 'menu-blog': 'Blog', - 'menu-contact': 'Contact', - 'intro-title': 'I am a developer who develops from a service point of view, opinion and convergence.', - 'intro-desc': - 'I am a style that develops quickly to requirements, meticulously tests and develops for accurate results, and actively adopts development using DevOps environments such as CI/CD to make these developments more efficient. In recent years, I have been interested in high-capacity data processing services in order to continue to grow as a back-end developer. In addition, I am studying RabbitMQ, Apache Spark, Spring Cloud, Spring Batch.', - 'name-title': 'Name', - name: 'Kwang Soo Jeong', - 'birth-title': 'Date of birth', - birth: 'August 25, 1993', - 'email-title': 'E-mail', - 'exp-year': ' year experience', - 'exp-years': ' years experience', - 'filter-all': 'All', - 'filter-desktop': 'Desktop App', - 'filter-mobile': 'Mobile App', - 'filter-web': 'Web App', - 'filter-ml': 'ML Model', - 'con-name-form': 'Name*', - 'con-email-form': 'E-mail*', - 'con-desc-form': 'Your Message', - 'con-name-error': 'Please enter a value with valid length', - 'con-email-error': 'Please enter a valid email address', - 'con-desc-error': 'Please enter a description', - 'con-loc-title': 'Location', - 'con-loc-content': 'Cheonan, Republic of KR', - 'con-email-title': 'E-mail', - 'con-send-btn': 'Send Message', - 'con-form-loading-title': 'Sending', - 'con-form-loading-body': 'Sending Please wait a moment.', - 'con-form-success-title': 'Success', - 'con-form-success-body': 'Your message has been sent.', - 'con-form-fail-title': 'Fail', - 'con-form-fail-body': 'Failed to send the message.', - 'con-form-error-title': 'Error', - 'con-form-error-body': 'Please write your inquiry correctly.', - 'con-form-ok-btn': 'OK', - }, -}; - -export default ENG; diff --git a/src/locale/index.tsx b/src/locale/index.tsx deleted file mode 100644 index aa7d14d..0000000 --- a/src/locale/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import en from './en'; -import jp from './jp'; -import ko from './ko'; - -export default Object.assign(en, jp, ko); diff --git a/src/locale/jp/index.tsx b/src/locale/jp/index.tsx deleted file mode 100644 index 6d84755..0000000 --- a/src/locale/jp/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -const JPN = { - jp: { - 'menu-resume': '履歴書', - 'menu-portfolio': 'ポートフォリオ', - 'menu-blog': 'ブログ', - 'menu-contact': 'コンタクト', - 'intro-title': 'サービスの観点から見て意見や収斂を通じて発展する開発者', - 'intro-desc': - '私の要件に合わせて迅速に開発して、正確な結果を得るため入念にテストして開発するスタイルであり、このような開発をより効率的に進めるためにCI/CD等のDevOps環境を使用した開発を積極的に採用しています。最近では、バックエンドの開発者としての持続的な成長のために大容量のデータ処理サービスに興味を持つようになり、これにより、Micro Service Architectureを知りました。これに加え、RabbitMQ、Apache Spark、Spring Cloud、Spring Batchを勉強しています。', - 'name-title': '名前', - name: '鄭 光 洙', - 'birth-title': '誕生日', - birth: '1993年 08月 25日', - 'email-title': 'メールアドレス', - 'exp-year': '年のキャリア', - 'exp-years': '年のキャリア', - 'filter-all': '全体', - 'filter-desktop': 'Desktop アプリ', - 'filter-mobile': 'Mobile アプリ', - 'filter-web': 'Web アプリ', - 'filter-ml': '人工知能', - 'con-name-form': '名前*', - 'con-email-form': 'メールアドレス*', - 'con-desc-form': 'メッセージを入力してください。', - 'con-name-error': '名前を入力してください。', - 'con-email-error': '有効なメールアドレスを入力してください。', - 'con-desc-error': '連絡することを入力してください。', - 'con-loc-title': '位置', - 'con-loc-content': '大韓民国 天安市', - 'con-email-title': 'メールアドレス', - 'con-send-btn': '転送', - 'con-form-loading-title': '転送中', - 'con-form-loading-body': '要求されたメッセージを転送しています。しばらくお待ちください。', - 'con-form-success-title': '転送完了', - 'con-form-success-body': 'メッセージが正常に送信されました。', - 'con-form-fail-title': '転送失敗', - 'con-form-fail-body': 'メッセージを転送するために失敗しました。', - 'con-form-error-title': 'エラー', - 'con-form-error-body': 'フォームを正しく記入してください。', - 'con-form-ok-btn': '確認', - }, -}; - -export default JPN; diff --git a/src/locale/ko/index.tsx b/src/locale/ko/index.tsx deleted file mode 100644 index 9d83688..0000000 --- a/src/locale/ko/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -const KOR = { - ko: { - 'menu-resume': '이력서', - 'menu-portfolio': '포트폴리오', - 'menu-blog': '블로그', - 'menu-contact': '문의', - 'intro-title': '서비스 관점에서 보고 의견과 수렴을 통해 발전하는 개발자', - 'intro-desc': - '요구 사항에 맞춰 빠르게 개발하고 정확한 결과를 위해 꼼꼼히 테스트하며 개발하는 스타일이며 이러한 개발을 보다 능률적으로 진행하기 위해 CI/CD 등의 DevOps 환경을 사용한 개발을 적극 채택하고 있습니다. 최근에는 백엔드 개발자로써의 지속적인 성장을 위해 대용량 데이터 처리 서비스에 관심을 가지게 되었고, 이를 통해 Micro Service Architecture를 알게 되었습니다. 이와 더불어, RabbitMQ, Apache Spark, Spring Cloud, Spring Batch를 공부하고 있습니다.', - 'name-title': '이름', - name: '정 광 수', - 'birth-title': '생년월일', - birth: '1993. 08. 25', - 'email-title': '이메일 주소', - 'exp-year': '년 사용', - 'exp-years': '년 사용', - 'filter-all': '전체', - 'filter-desktop': '데스크톱 앱', - 'filter-mobile': '모바일 앱', - 'filter-web': '웹 앱', - 'filter-ml': '머신 러닝', - 'con-name-form': '이름*', - 'con-email-form': '이메일 주소*', - 'con-desc-form': '메시지를 입력해주세요.', - 'con-name-error': '이름을 입력해주세요.', - 'con-email-error': '올바른 이메일 주소를 입력해주세요.', - 'con-desc-error': '문의하실 내용을 입력해주세요.', - 'con-loc-title': '위치', - 'con-loc-content': '대한민국 천안시', - 'con-email-title': '이메일 주소', - 'con-send-btn': '메시지 전송', - 'con-form-loading-title': '전송 중', - 'con-form-loading-body': '전송 중입니다. 잠시만 기다려주십시오.', - 'con-form-success-title': '전송 완료', - 'con-form-success-body': '메시지가 전송되었습니다.', - 'con-form-fail-title': '전송 실패', - 'con-form-fail-body': '메시지를 보내는 데 실패하였습니다.', - 'con-form-ok-btn': '확인', - 'con-form-error-title': '오류', - 'con-form-error-body': '문의 사항을 올바르게 적어주십시오.', - }, -}; - -export default KOR; From 4f673d80022e7f553229defd75a39c437388d86f Mon Sep 17 00:00:00 2001 From: NEONKID Date: Sun, 15 Mar 2020 18:49:43 +0900 Subject: [PATCH 02/10] Change translate dependencies react-intl to i18next.. --- package.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 5c00584..78f1bdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "neonkid-portpolio", - "version": "2.0.0", + "version": "2.1.0", "private": true, "dependencies": { "@types/jest": "24.0.18", @@ -11,6 +11,8 @@ "bootstrap": "^4.3.1", "bootstrap-validator": "^0.11.9", "firebase": "^7.2.1", + "i18next": "^19.3.2", + "i18next-browser-languagedetector": "^4.0.2", "ionicons": "^4.6.3", "isotope-layout": "^3.0.6", "jquery": "^3.4.1", @@ -22,9 +24,9 @@ "prop-types": "^15.7.2", "react": "^16.10.2", "react-dom": "^16.10.2", - "react-intl": "^3.3.2", + "react-i18next": "^11.3.3", "react-moment": "^0.9.6", - "react-scripts": "3.3.0", + "react-scripts": "^3.4.0", "react-scroll": "^1.7.14", "react-typed": "^1.2.0", "rss-parser": "^3.7.3", @@ -55,6 +57,7 @@ ] }, "devDependencies": { + "@testing-library/react": "^10.0.1", "@types/bootstrap": "^4.3.1", "@types/bootstrap-validator": "^0.11.2", "@types/isotope-layout": "^3.0.8", From f9ab309c58d63e5e4ee73e072705e016633fbc0e Mon Sep 17 00:00:00 2001 From: NEONKID Date: Sun, 15 Mar 2020 18:50:30 +0900 Subject: [PATCH 03/10] Change code for react-i18next.. --- src/components/Header/index.tsx | 62 ++-- .../Home/ContactForm/ContactModal/index.tsx | 17 +- src/components/Home/ContactForm/index.tsx | 301 ++++++++---------- .../Home/PortfolioContent/Work/index.tsx | 5 +- .../Home/PortfolioContent/index.tsx | 104 +++--- .../Home/ResumeContent/Education/index.tsx | 5 +- .../Home/ResumeContent/Experience/index.tsx | 5 +- .../Home/ResumeContent/Profile/index.tsx | 42 ++- .../ResumeContent/Skills/SkillItem/index.tsx | 11 +- src/components/Preloader/index.tsx | 2 +- src/index.tsx | 28 +- 11 files changed, 270 insertions(+), 312 deletions(-) diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index f00d40e..496953c 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,6 +1,6 @@ import React, { Component } from 'react'; +import { Translation } from 'react-i18next'; import { observer, inject } from 'mobx-react'; -import { FormattedMessage } from 'react-intl'; import * as Inject from '../../stores/MenuStateStore'; import './styles.css'; @@ -42,33 +42,39 @@ class Header extends Component { return (
Neon K.I.D -
    -
  • - -
  • - -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
+ + {(t, { i18n, lng }, ready) => ( +
    +
  • + {ready ? t('menu-resume') : 'default'} +
  • +
  • + {ready ? t('menu-portfolio') : 'default'} +
  • +
  • + {ready ? t('menu-blog') : 'default'} +
  • +
  • + {ready ? t('menu-contact') : 'default'} +
  • +
  • + +
  • +
+ )} +
); } diff --git a/src/components/Home/ContactForm/ContactModal/index.tsx b/src/components/Home/ContactForm/ContactModal/index.tsx index 7396692..cc4b44a 100644 --- a/src/components/Home/ContactForm/ContactModal/index.tsx +++ b/src/components/Home/ContactForm/ContactModal/index.tsx @@ -1,14 +1,13 @@ import React from 'react'; -import { injectIntl, IntlFormatters, WrappedComponentProps } from 'react-intl'; +import { Translation } from 'react-i18next'; type cmProps = { title?: string; message?: string; id: string; - intl?: IntlFormatters; }; -const ContactModal = ({ title, message, id, intl }: cmProps & WrappedComponentProps) => { +const ContactModal = ({ title, message, id }: cmProps) => { return ( @@ -30,4 +33,4 @@ const ContactModal = ({ title, message, id, intl }: cmProps & WrappedComponentPr ); }; -export default injectIntl(ContactModal); +export default ContactModal; diff --git a/src/components/Home/ContactForm/index.tsx b/src/components/Home/ContactForm/index.tsx index d0acc6b..5c50af3 100644 --- a/src/components/Home/ContactForm/index.tsx +++ b/src/components/Home/ContactForm/index.tsx @@ -1,7 +1,6 @@ -import React, { Component } from 'react'; -import { observer, inject } from 'mobx-react'; -import { injectIntl } from 'react-intl'; -import axios from 'axios'; +import React, { useState } from 'react'; +import { observer } from 'mobx-react'; +import { useTranslation, Translation } from 'react-i18next'; import 'bootstrap-validator'; @@ -11,205 +10,179 @@ import Textbox from './Textbox'; import Textarea from './Textarea'; import * as Inject from '../../../stores/MenuStateStore'; +import { sendMsg } from '../../Server/nkapi/contactMe'; import './styles.css'; -interface CFProps {} - -interface CFState { - name: string; - email: string; - msg: string; - - resTitle: string; - resBody: string; -} - -@inject((stores: Inject.Props) => ({ - contactState: stores.store.contactState, -})) -@observer -class ContactForm extends Component { - state: CFState = { - name: '', - email: '', - msg: '', - - resTitle: '', - resBody: '', +const useData = () => { + const { store } = Inject.useStores(); + + return { + contactState: store.contactState, }; +}; + +const ContactForm = () => { + const data = useData(); + const { t } = useTranslation(); + + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [msg, setMsg] = useState(''); + + const [resTitle, setResTitle] = useState(''); + const [resBody, setResBody] = useState(''); - emailChange = (e: any) => { + const emailChange = (e: React.ChangeEvent) => { const email = e.target.value; if (email.length < 5) return; if (!email.includes('@')) return; - this.setState({ - email: e.target.value, - }); + setEmail(email); }; - msgChange = (e: any) => { + const msgChange = (e: React.ChangeEvent) => { const msg = e.target.value; if (msg.length < 6) return; - this.setState({ - msg: e.target.value, - }); + setMsg(msg); }; - nameChange = (e: any) => { + const nameChange = (e: React.ChangeEvent) => { const name = e.target.value; - if (name.lengtn < 3) return; + if (name.length < 3) return; - this.setState({ - name: e.target.value, - }); + setName(name); }; - sendMessage = (event: any) => { - const { intl }: any = this.props; - + const sendMessage = (event: React.FormEvent) => { event.preventDefault(); - if (this.state.name === '' || this.state.email === '' || this.state.msg === '') { - this.setState({ - resTitle: intl.formatMessage({ id: 'con-form-error-title' }), - resBody: intl.formatMessage({ id: 'con-form-error-body' }), - }); + if (name === '' || email === '' || msg === '') { + setResTitle(t('con-form-error-title')); + setResBody(t('con-form-error-body')); return; } - this.setState({ - resTitle: intl.formatMessage({ id: 'con-form-loading-title' }), - resBody: intl.formatMessage({ id: 'con-form-loading-body' }), - }); + setResTitle(t('con-form-loading-title')); + setResBody(t('con-form-loading-body')); - axios - .post('https://apis.neonkid.xyz/v1/sendMessage', { - name: this.state.name, - email: this.state.email, - message: this.state.msg, - }) + sendMsg(name, email, msg) .then(res => { - this.setState({ - resTitle: intl.formatMessage({ id: 'con-form-success-title' }), - resBody: intl.formatMessage({ id: 'con-form-success-body' }), - }); + setResTitle(t('con-form-success-title')); + setResBody(t('con-form-success-body')); console.log(res); }) .catch(err => { - this.setState({ - resTitle: intl.formatMessage({ id: 'con-form-fail-title' }), - resBody: intl.formatMessage({ id: 'con-form-fail-body' }), - }); + setResTitle(t('con-form-fail-title')); + setResBody(t('con-form-fail-body')); console.log(err); }); }; - render() { - const { contactState, intl }: any = this.props; - const style = contactState ? 'content-blocks contact showx' : 'content-blocks contact'; - - return ( -
-
-
-

Get in touch

-
-
-
-
-
-
- -
-
- -
-
-