From 77718e705705869d813a4d0c4782fec4bb45814c Mon Sep 17 00:00:00 2001 From: hyochan Date: Sat, 27 Jul 2024 13:44:23 +0900 Subject: [PATCH] feat: setup localizations --- .eslintrc.js | 23 +++++++-- app/(app)/(tabs)/_layout.tsx | 5 +- app/(app)/(tabs)/index.tsx | 5 +- app/(app)/(tabs)/profile.tsx | 5 +- app/(app)/details.tsx | 30 ------------ app/(app)/settings/index.tsx | 24 ++++------ app/(app)/settings/login-info.tsx | 42 ++++++++-------- app/(auth)/sign-in.tsx | 77 ++++++++++++++++-------------- app/_layout.tsx | 5 +- assets/langs/en.json | 43 +++++++++++++++-- assets/langs/ko.json | 41 ++++++++++++++-- bun.lockb | Bin 879832 -> 899616 bytes package.json | 8 +++- src/STRINGS.ts | 10 +++- src/uis/LottieView.web.tsx | 2 +- 15 files changed, 198 insertions(+), 122 deletions(-) delete mode 100644 app/(app)/details.tsx diff --git a/.eslintrc.js b/.eslintrc.js index 54b62a4..af7c9ae 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,11 +2,28 @@ const path = require('path'); module.exports = { root: true, - extends: [ - '@dooboo/eslint-config-react-native', - ], + extends: ['expo', 'prettier', 'plugin:i18n-json/recommended'], rules: { 'eslint-comments/no-unlimited-disable': 0, 'eslint-comments/no-unused-disable': 0, + 'i18n-json/identical-keys': [ + 2, + { + filePath: path.resolve('./assets/langs/ko.json'), + }, + ], + 'i18n-json/sorted-keys': [ + 2, + { + order: 'asc', + indentSpaces: 2, + }, + ], + 'i18n-json/valid-message-syntax': [ + 2, + { + syntax: path.resolve('./custom-syntax-validator.ts'), + }, + ], }, }; diff --git a/app/(app)/(tabs)/_layout.tsx b/app/(app)/(tabs)/_layout.tsx index 85abf45..4d55651 100644 --- a/app/(app)/(tabs)/_layout.tsx +++ b/app/(app)/(tabs)/_layout.tsx @@ -4,6 +4,7 @@ import {Link, Redirect, Tabs, useRouter} from 'expo-router'; import {useRecoilValue} from 'recoil'; import {authRecoilState} from '../../../src/recoil/atoms'; +import {t} from '../../../src/STRINGS'; function SettingsMenu(): JSX.Element { const {theme} = useDooboo(); @@ -49,7 +50,7 @@ export default function TabLayout(): JSX.Element { ( ), @@ -59,7 +60,7 @@ export default function TabLayout(): JSX.Element { , headerRight: () => {SettingsMenu()}, }} diff --git a/app/(app)/(tabs)/index.tsx b/app/(app)/(tabs)/index.tsx index 35f8b98..b7fd3db 100644 --- a/app/(app)/(tabs)/index.tsx +++ b/app/(app)/(tabs)/index.tsx @@ -1,7 +1,8 @@ import styled, {css} from '@emotion/native'; import {Fab, Typography} from 'dooboo-ui'; import StatusBarBrightness from 'dooboo-ui/uis/StatusbarBrightness'; -import {Stack} from 'expo-router'; + +import {t} from '../../../src/STRINGS'; const Container = styled.View` flex: 1; @@ -13,7 +14,7 @@ export default function Community(): JSX.Element { return ( - 커뮤니티 + {t('common.community')} - - 프로필 + + {t('common.profile')} ); } diff --git a/app/(app)/details.tsx b/app/(app)/details.tsx deleted file mode 100644 index 5822077..0000000 --- a/app/(app)/details.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import styled from '@emotion/native'; -import {Typography} from 'dooboo-ui'; -import {Stack} from 'expo-router'; - -import {t} from '../../src/STRINGS'; - -const Container = styled.View` - flex: 1; - align-self: stretch; - background-color: ${({theme}) => theme.bg.basic}; -`; - -const Content = styled.View` - padding: 16px; -`; - -export default function Details(): JSX.Element { - return ( - - - - {t('DETAILS')} - - - ); -} diff --git a/app/(app)/settings/index.tsx b/app/(app)/settings/index.tsx index 3fa6ecf..3fdd248 100644 --- a/app/(app)/settings/index.tsx +++ b/app/(app)/settings/index.tsx @@ -11,11 +11,9 @@ import {Stack, useRouter} from 'expo-router'; import * as SystemUI from 'expo-system-ui'; import {useRecoilValue} from 'recoil'; -import useAppState from '../../../src/hooks/useAppState'; import {authRecoilState} from '../../../src/recoil/atoms'; import {t} from '../../../src/STRINGS'; import CustomLoadingIndicator from '../../../src/uis/CustomLoadingIndicator'; -import {openURL} from '../../../src/utils/common'; import {AsyncStorageKey} from '../../../src/utils/constants'; const Container = styled.View` @@ -80,7 +78,6 @@ export default function Settings(): JSX.Element { const menus = useMemo( () => [ { - // 로그인 정보 onPress: () => push('/settings/login-info'), startElement: ( ), - title: '로그인 정보', + title: t('settings.loginInfo'), }, { - // 프로필 수정 onPress: () => push('/settings/profile-update'), startElement: ( ), - title: '프로필 수정', + title: t('settings.updateProfile'), }, { - // 차단한 사용자 onPress: () => push('/settings/block-users'), startElement: ( ), - title: '차단한 사용자', + title: t('settings.bannedUsers'), }, { - // 다크 모드 startElement: ( ), - title: '다크 모드', + title: t('settings.darkMode'), onPress: undefined, }, { - // 노티피케이션 startElement: ( ), - title: '알림 설정', + title: t('settings.notificationSettings'), onPress: undefined, }, { - // 약관 onPress: () => push('/termsofservice'), startElement: ( ), - title: '서비스 이용약관', + title: t('settings.termsOfService'), }, ], [hasNotificationPermission, themeType, changeThemeType, push], @@ -243,7 +235,7 @@ export default function Settings(): JSX.Element { if (!authId) { return ( <> - + ); @@ -251,7 +243,7 @@ export default function Settings(): JSX.Element { return ( - + - {iconName === 'Envelope' - ? '이메일' - : iconName === 'AppleLogo' - ? '애플' - : iconName === 'GoogleLogo' - ? '구글' - : '깃허브'} - 로 로그인됨 + {t('loginInfo.loggedInWith', { + provider: + iconName === 'Envelope' + ? 'Email' + : iconName === 'AppleLogo' + ? 'Apple' + : iconName === 'GoogleLogo' + ? 'Google' + : 'Github', + })} - + ); @@ -136,15 +139,16 @@ export default function LoginInfo({}: Props): JSX.Element { return ( - + - 로그인 수단 - + + {t('loginInfo.loginMethod')} + { alertDialog.open({ - title: '회원 탈퇴', - body: '탈퇴 시 앱 내 모든 데이터가 삭제됩니다. 정말 탈퇴 하시겠습니까?', + title: t('loginInfo.cancelAccount'), + body: t('loginInfo.cancelAccountDescription'), closeOnTouchOutside: false, actions: [