diff --git a/README.md b/README.md index 88871488..d3be720b 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,8 @@ [![GPL-3.0](https://img.shields.io/github/license/tooot-app/push)](LICENSE) ![GitHub issues](https://img.shields.io/github/issues/tooot-app/app) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/tooot-app/app?include_prereleases) ![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/tooot-app/app) [![Crowdin](https://badges.crowdin.net/tooot/localized.svg)](https://crowdin.tooot.app/project/tooot) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tooot-app/app/build) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/candidate?label=build%20candidate) ![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/tooot-app/app/build/release?label=build%20release) + +## Special thanks + +@hellojaccc for Korean translation +@duy@mas.to for Vietnamese translation \ No newline at end of file diff --git a/fastlane/Deliverfile b/fastlane/Deliverfile index 966e0dd0..41d6b634 100644 --- a/fastlane/Deliverfile +++ b/fastlane/Deliverfile @@ -1,4 +1,4 @@ -languages(['zh-Hans', 'en-US']) +languages(['zh-Hans', 'vi', 'ko', 'en-US']) name({ 'default' => "tooot" diff --git a/fastlane/screenshots/en-US/0_iPad.png b/fastlane/screenshots/en-US/0_iPad.png new file mode 100644 index 00000000..35363cf7 Binary files /dev/null and b/fastlane/screenshots/en-US/0_iPad.png differ diff --git a/fastlane/screenshots/en-US/0_ipadPro129.png b/fastlane/screenshots/en-US/0_ipadPro129.png new file mode 100644 index 00000000..35363cf7 Binary files /dev/null and b/fastlane/screenshots/en-US/0_ipadPro129.png differ diff --git a/fastlane/screenshots/en-US/1_iPad.png b/fastlane/screenshots/en-US/1_iPad.png new file mode 100644 index 00000000..26a2e0ec Binary files /dev/null and b/fastlane/screenshots/en-US/1_iPad.png differ diff --git a/fastlane/screenshots/en-US/1_ipadPro129.png b/fastlane/screenshots/en-US/1_ipadPro129.png new file mode 100644 index 00000000..26a2e0ec Binary files /dev/null and b/fastlane/screenshots/en-US/1_ipadPro129.png differ diff --git a/fastlane/screenshots/en-US/2_iPad.png b/fastlane/screenshots/en-US/2_iPad.png new file mode 100644 index 00000000..312537e8 Binary files /dev/null and b/fastlane/screenshots/en-US/2_iPad.png differ diff --git a/fastlane/screenshots/en-US/2_ipadPro129.png b/fastlane/screenshots/en-US/2_ipadPro129.png new file mode 100644 index 00000000..312537e8 Binary files /dev/null and b/fastlane/screenshots/en-US/2_ipadPro129.png differ diff --git a/fastlane/screenshots/en-US/3_iPad.png b/fastlane/screenshots/en-US/3_iPad.png new file mode 100644 index 00000000..22231cd9 Binary files /dev/null and b/fastlane/screenshots/en-US/3_iPad.png differ diff --git a/fastlane/screenshots/en-US/3_ipadPro129.png b/fastlane/screenshots/en-US/3_ipadPro129.png new file mode 100644 index 00000000..22231cd9 Binary files /dev/null and b/fastlane/screenshots/en-US/3_ipadPro129.png differ diff --git a/fastlane/screenshots/zh-Hans/0_iPad.png b/fastlane/screenshots/zh-Hans/0_iPad.png new file mode 100644 index 00000000..5dbf6196 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/0_iPad.png differ diff --git a/fastlane/screenshots/zh-Hans/0_ipadPro129.png b/fastlane/screenshots/zh-Hans/0_ipadPro129.png new file mode 100644 index 00000000..5dbf6196 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/0_ipadPro129.png differ diff --git a/fastlane/screenshots/zh-Hans/1_iPad.png b/fastlane/screenshots/zh-Hans/1_iPad.png new file mode 100644 index 00000000..2e6de471 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/1_iPad.png differ diff --git a/fastlane/screenshots/zh-Hans/1_ipadPro129.png b/fastlane/screenshots/zh-Hans/1_ipadPro129.png new file mode 100644 index 00000000..2e6de471 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/1_ipadPro129.png differ diff --git a/fastlane/screenshots/zh-Hans/2_iPad.png b/fastlane/screenshots/zh-Hans/2_iPad.png new file mode 100644 index 00000000..02c6b176 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/2_iPad.png differ diff --git a/fastlane/screenshots/zh-Hans/2_ipadPro129.png b/fastlane/screenshots/zh-Hans/2_ipadPro129.png new file mode 100644 index 00000000..02c6b176 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/2_ipadPro129.png differ diff --git a/fastlane/screenshots/zh-Hans/3_iPad.png b/fastlane/screenshots/zh-Hans/3_iPad.png new file mode 100644 index 00000000..e5376321 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/3_iPad.png differ diff --git a/fastlane/screenshots/zh-Hans/3_ipadPro129.png b/fastlane/screenshots/zh-Hans/3_ipadPro129.png new file mode 100644 index 00000000..e5376321 Binary files /dev/null and b/fastlane/screenshots/zh-Hans/3_ipadPro129.png differ diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 90e1f496..f24b1e4f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -454,11 +454,11 @@ PODS: - React-Core - RNFastImage (8.5.11): - React-Core - - SDWebImage (~> 5.11.1) + - SDWebImage (~> 5.12.3) - SDWebImageWebPCoder (~> 0.8.4) - RNGestureHandler (2.2.0): - React-Core - - RNReanimated (2.3.1): + - RNReanimated (2.4.0): - DoubleConversion - FBLazyVector - FBReactNativeSpec @@ -494,9 +494,9 @@ PODS: - Sentry (= 7.9.0) - RNSVG (12.1.1): - React - - SDWebImage (5.11.1): - - SDWebImage/Core (= 5.11.1) - - SDWebImage/Core (5.11.1) + - SDWebImage (5.12.3): + - SDWebImage/Core (= 5.12.3) + - SDWebImage/Core (5.12.3) - SDWebImageWebPCoder (0.8.4): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.10) @@ -850,13 +850,13 @@ SPEC CHECKSUMS: React-runtimeexecutor: dec32ee6f2e2a26e13e58152271535fadff5455a ReactCommon: 57b69f6383eafcbd7da625bfa6003810332313c4 RNCAsyncStorage: 6bd5a7ba3dde1c3facba418aa273f449bdc5437a - RNFastImage: 1f2cab428712a4baaf78d6169eaec7f622556dd7 + RNFastImage: cced864a4a2eac27c5c10ac16bd5e8b9d2be4504 RNGestureHandler: bf572f552ea324acd5b5464b8d30755b2d8c1de6 - RNReanimated: da3860204e5660c0dd66739936732197d359d753 + RNReanimated: fb56abd99a5d7efe91ae3c7bf3cd3663cee1b21b RNScreens: d6da2b9e29cf523832c2542f47bf1287318b1868 RNSentry: 0aa1567f66c20390f3834637fc4f73380dcd0774 RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f - SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d + SDWebImage: 53179a2dba77246efa8a9b85f5c5b21f8f43e38f SDWebImageWebPCoder: f93010f3f6c031e2f8fb3081ca4ee6966c539815 Sentry: 2f7e91f247cfb05b05bd01e0b5d0692557a7687b UMTaskManagerInterface: 6f7150f9ec9bc6f2760eeae532a70de71ff951c1 diff --git a/ios/tooot/Info.plist b/ios/tooot/Info.plist index 7baa3965..932e4fba 100644 --- a/ios/tooot/Info.plist +++ b/ios/tooot/Info.plist @@ -71,13 +71,15 @@ armv7 UIRequiresFullScreen - + UIStatusBarHidden UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight UIUserInterfaceStyle Automatic diff --git a/package.json b/package.json index 24e1c339..4684fad2 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "tooot", "versions": { - "native": "220204", + "native": "220206", "major": 3, - "minor": 3, + "minor": 4, "patch": 0, "expo": "44.0.0" }, @@ -39,7 +39,7 @@ "@reduxjs/toolkit": "1.7.2", "@sentry/react-native": "3.2.13", "@sharcoux/slider": "5.6.4", - "axios": "0.25.0", + "axios": "0.24.0", "expo": "44.0.6", "expo-auth-session": "3.5.0", "expo-av": "10.2.1", @@ -78,13 +78,13 @@ "react-native-gesture-handler": "2.2.0", "react-native-htmlview": "0.16.0", "react-native-pager-view": "5.4.9", - "react-native-reanimated": "2.3.1", + "react-native-reanimated": "2.4.0", "react-native-safe-area-context": "3.3.2", "react-native-screens": "3.10.2", "react-native-svg": "12.1.1", "react-native-swipe-list-view": "3.2.9", "react-native-tab-view": "3.1.1", - "react-query": "3.34.12", + "react-query": "3.34.14", "react-redux": "7.2.6", "react-timeago": "6.2.1", "redux-persist": "6.0.0", diff --git a/patches/react-native-fast-image+8.5.11.patch b/patches/react-native-fast-image+8.5.11.patch index a4b97089..3d5f42e9 100644 --- a/patches/react-native-fast-image+8.5.11.patch +++ b/patches/react-native-fast-image+8.5.11.patch @@ -1,3 +1,15 @@ +diff --git a/node_modules/react-native-fast-image/RNFastImage.podspec b/node_modules/react-native-fast-image/RNFastImage.podspec +index db0fada..9a2457c 100644 +--- a/node_modules/react-native-fast-image/RNFastImage.podspec ++++ b/node_modules/react-native-fast-image/RNFastImage.podspec +@@ -16,6 +16,6 @@ Pod::Spec.new do |s| + s.source_files = "ios/**/*.{h,m}" + + s.dependency 'React-Core' +- s.dependency 'SDWebImage', '~> 5.11.1' ++ s.dependency 'SDWebImage', '~> 5.12.3' + s.dependency 'SDWebImageWebPCoder', '~> 0.8.4' + end diff --git a/node_modules/react-native-fast-image/android/build.gradle b/node_modules/react-native-fast-image/android/build.gradle index 5b21cd5..19d82f8 100644 --- a/node_modules/react-native-fast-image/android/build.gradle diff --git a/src/components/mediaSelector.ts b/src/components/mediaSelector.ts index 478bf3ec..4a5af36b 100644 --- a/src/components/mediaSelector.ts +++ b/src/components/mediaSelector.ts @@ -4,7 +4,7 @@ import * as ImageManipulator from 'expo-image-manipulator' import * as ImagePicker from 'expo-image-picker' import { ImageInfo } from 'expo-image-picker/build/ImagePicker.types' import i18next from 'i18next' -import { Alert, Linking } from 'react-native' +import { Alert, Linking, Platform } from 'react-native' export interface Props { mediaTypes?: ImagePicker.MediaTypeOptions @@ -91,7 +91,11 @@ const mediaSelector = async ({ } else { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes, - exif: false + exif: false, + presentationStyle: + Platform.OS === 'ios' && parseInt(Platform.Version) < 13 + ? 0 + : -2 }) if (!result.cancelled) { diff --git a/src/i18n/de/components/relationship.json b/src/i18n/de/components/relationship.json new file mode 100644 index 00000000..b14fab56 --- /dev/null +++ b/src/i18n/de/components/relationship.json @@ -0,0 +1,16 @@ +{ + "follow": { + "function": "Folgen" + }, + "block": { + "function": "Blockieren" + }, + "button": { + "error": "Fehler beim Laden", + "blocked_by": "Zugriff durch Nutzer:in verweigert", + "blocking": "Entblocken", + "following": "Entfolgen", + "requested": "Anfrage zurückziehen", + "default": "Folgen" + } +} \ No newline at end of file diff --git a/src/i18n/de/components/relativeTime.json b/src/i18n/de/components/relativeTime.json new file mode 100644 index 00000000..afe2da03 --- /dev/null +++ b/src/i18n/de/components/relativeTime.json @@ -0,0 +1,20 @@ +{ + "strings": { + "prefixAgo": "", + "prefixFromNow": "", + "suffixAgo": "her", + "suffixFromNow": "", + "seconds": "%d Sekunden", + "minute": "etwa eine Minute", + "minutes": "%d Minuten", + "hour": "etwa eine Stunde", + "hours": "etwa %d Stunden", + "day": "1 Tag", + "days": "%d Tage", + "month": "etwa 1 Monat", + "months": "%d Monate", + "year": "etwa 1 Jahr", + "years": "%d Jahre", + "wordSeparator": "" + } +} \ No newline at end of file diff --git a/src/i18n/de/screens/announcements.json b/src/i18n/de/screens/announcements.json new file mode 100644 index 00000000..dc8fa60b --- /dev/null +++ b/src/i18n/de/screens/announcements.json @@ -0,0 +1,10 @@ +{ + "heading": "Ankündigungen", + "content": { + "published": "<0 /> veröffentlicht", + "button": { + "read": "Lesen", + "unread": "Als gelesen markieren" + } + } +} \ No newline at end of file diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index 54bf2b44..0199f4f2 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -2,6 +2,8 @@ import i18n from 'i18next' import { initReactI18next } from 'react-i18next' import en from '@root/i18n/en/_all' +import ko from '@root/i18n/ko/_all' +import vi from '@root/i18n/vi/_all' import zh_Hans from '@root/i18n/zh-Hans/_all' i18n.use(initReactI18next).init({ @@ -11,7 +13,7 @@ i18n.use(initReactI18next).init({ ns: ['common'], defaultNS: 'common', - resources: { 'zh-Hans': zh_Hans, en }, + resources: { 'zh-Hans': zh_Hans, vi, ko, en }, saveMissing: true, missingKeyHandler: (ns, key) => { diff --git a/src/i18n/ko/_all.ts b/src/i18n/ko/_all.ts new file mode 100644 index 00000000..d4c1b7c5 --- /dev/null +++ b/src/i18n/ko/_all.ts @@ -0,0 +1,17 @@ +export default { + common: require('./common'), + + screens: require('./screens'), + screenActions: require('./screens/actions'), + screenAnnouncements: require('./screens/announcements'), + screenCompose: require('./screens/compose'), + screenImageViewer: require('./screens/imageViewer'), + screenTabs: require('./screens/tabs'), + + componentInstance: require('./components/instance'), + componentMediaSelector: require('./components/mediaSelector'), + componentParse: require('./components/parse'), + componentRelationship: require('./components/relationship'), + componentRelativeTime: require('./components/relativeTime'), + componentTimeline: require('./components/timeline') +} diff --git a/src/i18n/ko/common.json b/src/i18n/ko/common.json new file mode 100644 index 00000000..572eabf7 --- /dev/null +++ b/src/i18n/ko/common.json @@ -0,0 +1,21 @@ +{ + "buttons": { + "apply": "적용", + "cancel": "취소" + }, + "customEmoji": { + "accessibilityLabel": "커스텀 이모지 {{emoji}}" + }, + "message": { + "success": { + "message": "{{function}} 성공" + }, + "warning": { + "message": "" + }, + "error": { + "message": "{{function}} 실패, 다시 시도해주세요" + } + }, + "separator": ", " +} \ No newline at end of file diff --git a/src/i18n/ko/components/instance.json b/src/i18n/ko/components/instance.json new file mode 100644 index 00000000..b1abaf03 --- /dev/null +++ b/src/i18n/ko/components/instance.json @@ -0,0 +1,28 @@ +{ + "server": { + "textInput": { + "placeholder": "인스턴스의 도메인" + }, + "button": "로그인", + "information": { + "name": "이름", + "accounts": "사용자", + "statuses": "툿", + "domains": "연합" + }, + "disclaimer": { + "base": "로그인 과정에서는 시스템 브라우저를 사용해, tooot 앱이 당신의 계정 정보를 볼 수 없어요.\n더 알아보기 ", + "privacy": "개인정보 정책" + } + }, + "update": { + "alert": { + "title": "이 인스턴스에 로그인했어요", + "message": "기존에 로그인한 계정을 유지한 채로, 새 계정에 로그인할 수 있어요", + "buttons": { + "cancel": "$t(common:buttons.cancel)", + "continue": "계속" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/components/mediaSelector.json b/src/i18n/ko/components/mediaSelector.json new file mode 100644 index 00000000..7d9fb7ce --- /dev/null +++ b/src/i18n/ko/components/mediaSelector.json @@ -0,0 +1,28 @@ +{ + "title": "미디어 소스 선택", + "options": { + "library": "라이브러리에서 업로드", + "photo": "사진 촬영", + "cancel": "$t(common:buttons.cancel)" + }, + "library": { + "alert": { + "title": "권한 없음", + "message": "업로드를 위해 사진 라이브러리 권한이 필요해요", + "buttons": { + "settings": "설정 업데이트", + "cancel": "$t(common:buttons.cancel)" + } + } + }, + "photo": { + "alert": { + "title": "권한 없음", + "message": "업로드를 위해 카메라 사용 권한이 필요해요", + "buttons": { + "settings": "설정 업데이트", + "cancel": "$t(common:buttons.cancel)" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/components/parse.json b/src/i18n/ko/components/parse.json new file mode 100644 index 00000000..ff5d8d24 --- /dev/null +++ b/src/i18n/ko/components/parse.json @@ -0,0 +1,9 @@ +{ + "HTML": { + "expanded": { + "true": "{{hint}} 접기", + "false": "{{hint}} 펼치기" + }, + "defaultHint": "글" + } +} \ No newline at end of file diff --git a/src/i18n/ko/components/relationship.json b/src/i18n/ko/components/relationship.json new file mode 100644 index 00000000..db7896c1 --- /dev/null +++ b/src/i18n/ko/components/relationship.json @@ -0,0 +1,16 @@ +{ + "follow": { + "function": "사용자 팔로우" + }, + "block": { + "function": "사용자 차단" + }, + "button": { + "error": "불러오기 오류", + "blocked_by": "차단된 사용자", + "blocking": "차단 해제", + "following": "팔로우 해제", + "requested": "요청 취소", + "default": "팔로우" + } +} \ No newline at end of file diff --git a/src/i18n/ko/components/relativeTime.json b/src/i18n/ko/components/relativeTime.json new file mode 100644 index 00000000..4d09558f --- /dev/null +++ b/src/i18n/ko/components/relativeTime.json @@ -0,0 +1,20 @@ +{ + "strings": { + "prefixAgo": "", + "prefixFromNow": "", + "suffixAgo": "전", + "suffixFromNow": "", + "seconds": "%d초", + "minute": "약 1분", + "minutes": "%d분", + "hour": "약 1시간", + "hours": "약 %d시간", + "day": "하루", + "days": "%d일", + "month": "약 1달", + "months": "%d달", + "year": "약 1년", + "years": "%d년", + "wordSeparator": "" + } +} \ No newline at end of file diff --git a/src/i18n/ko/components/timeline.json b/src/i18n/ko/components/timeline.json new file mode 100644 index 00000000..f78c80a4 --- /dev/null +++ b/src/i18n/ko/components/timeline.json @@ -0,0 +1,211 @@ +{ + "empty": { + "error": { + "message": "불러오기 오류", + "button": "다시 시도" + }, + "success": { + "message": "타임라인 빔" + } + }, + "end": { + "message": "끝, <0 /> 한 잔 어때요" + }, + "lookback": { + "message": "마지막 읽음" + }, + "refresh": { + "fetchPreviousPage": "여기부터 더 새로운", + "refetch": "가장 최신으로" + }, + "shared": { + "actioned": { + "pinned": "고정됨", + "favourite": "{{name}}이 내 툿을 즐겨찾기했어요", + "status": "{{name}}이 방금 포스트했어요", + "follow": "{{name}}님이 나를 팔로우했어요", + "follow_request": "{{name}}이 나에게 팔로우 요청을 보냈어요", + "poll": "내가 참여한 투표가 끝났어요", + "reblog": { + "default": "{{name}}님이 부스트했어요", + "notification": "{{name}}이 내 툿을 부스트했어요" + } + }, + "actions": { + "reply": { + "accessibilityLabel": "이 툿에 답장" + }, + "reblogged": { + "accessibilityLabel": "이 툿 부스트", + "function": "툿 부스트" + }, + "favourited": { + "accessibilityLabel": "이 툿 즐겨찾기에 추가", + "function": "툿 즐겨찾기" + }, + "bookmarked": { + "accessibilityLabel": "툿 북마크에 추가", + "function": "툿 북마크" + } + }, + "actionsUsers": { + "reblogged_by": { + "accessibilityLabel": "{{count}}명의 사용자가 이 툿을 부스트했어요", + "accessibilityHint": "유저를 보려면 탭하세요", + "text": "$t(screenTabs:shared.users.statuses.reblogged_by)" + }, + "favourited_by": { + "accessibilityLabel": "{{count}}명의 사용자가 이 툿을 즐겨찾기했어요", + "accessibilityHint": "유저를 보려면 탭하세요", + "text": "$t(screenTabs:shared.users.statuses.favourited_by)" + } + }, + "attachment": { + "sensitive": { + "button": "민감한 미디어 표시" + }, + "unsupported": { + "text": "불러오기 오류", + "button": "원격 링크 시도" + } + }, + "avatar": { + "accessibilityLabel": "{{name}}의 아바타", + "accessibilityHint": "{{name}}의 페이지로 가려면 탭하세요" + }, + "content": { + "expandHint": "숨겨진 콘텐츠" + }, + "filtered": "필터됨", + "fullConversation": "대화 보기", + "translate": { + "default": "번역", + "succeed": "{{source}}에서 {{provider}}으로 번역됨", + "failed": "번역 실패" + }, + "header": { + "shared": { + "account": { + "name": { + "accessibilityHint": "사용자 표시 이름" + }, + "account": { + "accessibilityHint": "사용자 계정" + } + }, + "application": "{{application}}으로 툿", + "muted": { + "accessibilityLabel": "툿 음소거됨" + }, + "visibility": { + "direct": { + "accessibilityLabel": "툿이 개인 메시지에요" + }, + "private": { + "accessibilityLabel": "툿이 팔로워에게만 보여요" + } + } + }, + "conversation": { + "withAccounts": "와", + "delete": { + "function": "개인 메시지 삭제" + } + }, + "actions": { + "accessibilityHint": "이 툿에 할 동작, 툿 자체나 포스트한 사용자", + "account": { + "heading": "사용자 정보", + "mute": { + "function": "사용자 음소거", + "button": "@{{acct}} 음소거" + }, + "block": { + "function": "사용자 차단", + "button": "@{{acct}} 차단" + }, + "reports": { + "function": "사용자 신고", + "button": "@{{acct}} 신고" + } + }, + "domain": { + "heading": "인스턴스 정보", + "block": { + "function": "인스턴스 차단", + "button": "인스턴스 {{domain}} 차단" + }, + "alert": { + "title": "{{domain}}을 정말 차단할까요?", + "message": "보통은 유저 음소거나 차단으로 충분해요.\n\n인스턴스를 차단하면, 팔로워를 포함하는 인스턴스의 모든 콘텐츠가 삭제됩니다!", + "buttons": { + "confirm": "차단 확인", + "cancel": "$t(common:buttons.cancel)" + } + } + }, + "share": { + "status": { + "heading": "툿 공유", + "button": "이 툿의 링크 공유" + }, + "account": { + "heading": "사용자 공유", + "button": "이 사용자에게 링크 공유" + } + }, + "status": { + "heading": "툿 정보", + "delete": { + "function": "툿 삭제", + "button": "이 툿 삭제" + }, + "edit": { + "function": "툿 삭제", + "button": "삭제하고 다시 쓰기", + "alert": { + "title": "툿을 정말 삭제할까요?", + "message": "이 툿을 삭제하고 다시 초안을 작성하시겠어요? 모든 답장, 부스트와 즐겨찾기가 지워져요.", + "buttons": { + "confirm": "삭제 확인", + "cancel": "$t(common:buttons.cancel)" + } + } + }, + "mute": { + "function": "툿 음소거", + "button": { + "positive": "이 툿과 답장 음소거", + "negative": "이 툿과 답장 음소거 해제" + } + }, + "pin": { + "function": "고정", + "button": { + "positive": "이 툿 고정", + "negative": "이 툿 고정 해제" + } + } + } + } + }, + "poll": { + "meta": { + "button": { + "vote": "투표", + "refresh": "새로고침" + }, + "count": { + "voters": "{{count}}명의 사용자가 투표", + "voters_plural": "{{count}}명의 사용자가 투표", + "votes": "{{count}} 투표", + "votes_plural": "{{count}} 투표" + }, + "expiration": { + "expired": "투표 종료됨", + "until": "<0 />후 만료" + } + } + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/screens.json b/src/i18n/ko/screens.json new file mode 100644 index 00000000..369590d9 --- /dev/null +++ b/src/i18n/ko/screens.json @@ -0,0 +1,14 @@ +{ + "screenshot": { + "title": "개인정보 보호", + "message": "다른 사용자의 사용자 이름이나, 아바타 등의 정보를 유출하지 말아주세요. 고마워요!", + "button": "확인" + }, + "localCorrupt": { + "message": "로그인이 만료되었어요. 다시 로그인해주세요" + }, + "pushError": { + "message": "푸시 서비스 오류", + "description": "푸시 알림을 설정에서 다시 활성화해주세요" + } +} \ No newline at end of file diff --git a/src/i18n/ko/screens/actions.json b/src/i18n/ko/screens/actions.json new file mode 100644 index 00000000..d516ac7d --- /dev/null +++ b/src/i18n/ko/screens/actions.json @@ -0,0 +1,19 @@ +{ + "content": { + "button": { + "apply": "$t(common:buttons.apply)", + "cancel": "$t(common:buttons.cancel)" + }, + "notificationsFilter": { + "heading": "알림 종류 표시", + "content": { + "follow": "$t(screenTabs:me.push.follow.heading)", + "favourite": "$t(screenTabs:me.push.favourite.heading)", + "reblog": "$t(screenTabs:me.push.reblog.heading)", + "mention": "$t(screenTabs:me.push.mention.heading)", + "poll": "$t(screenTabs:me.push.poll.heading)", + "follow_request": "팔로우 요청" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/screens/announcements.json b/src/i18n/ko/screens/announcements.json new file mode 100644 index 00000000..d94cb379 --- /dev/null +++ b/src/i18n/ko/screens/announcements.json @@ -0,0 +1,10 @@ +{ + "heading": "공지", + "content": { + "published": "올려짐 <0 />", + "button": { + "read": "읽음", + "unread": "읽음으로 표시" + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/screens/compose.json b/src/i18n/ko/screens/compose.json new file mode 100644 index 00000000..6ab71fd6 --- /dev/null +++ b/src/i18n/ko/screens/compose.json @@ -0,0 +1,169 @@ +{ + "heading": { + "left": { + "button": "취소", + "alert": { + "title": "편집을 취소할까요?", + "buttons": { + "save": "초안 저장", + "delete": "초안 삭제", + "cancel": "취소" + } + } + }, + "right": { + "button": { + "default": "툿", + "conversation": "툿 DM", + "reply": "툿 답장", + "edit": "툿" + }, + "alert": { + "default": { + "title": "툿 실패", + "button": "다시 시도해주세요" + }, + "removeReply": { + "title": "답장한 툿을 찾을 수 없어요", + "description": "답장한 툿이 삭제되었을 수 있어요. 참조에서 제거할까요?", + "cancel": "$t(common:buttons.cancel)", + "confirm": "참조 제거" + } + } + } + }, + "content": { + "root": { + "header": { + "postingAs": "@{{acct}}@{{domain}}으로 툿", + "spoilerInput": { + "placeholder": "스포일러 경고 메시지" + }, + "textInput": { + "placeholder": "무엇을 생각하고 있나요?" + } + }, + "footer": { + "attachments": { + "sensitive": "첨부 파일 민감함으로 표시", + "remove": { + "accessibilityLabel": "업로드한 첨부 파일 삭제, 번호 {{attachment}}" + }, + "edit": { + "accessibilityLabel": "업로드한 첨부 파일 수정, 번호 {{attachment}}" + }, + "upload": { + "accessibilityLabel": "더 많은 첨부 파일 업로드" + } + }, + "emojis": { + "accessibilityHint": "툿에 이모지를 추가하려면 탭하세요" + }, + "poll": { + "option": { + "placeholder": { + "accessibilityLabel": "투표 옵션 {{index}}", + "single": "단일 선택", + "multiple": "다중 선택" + } + }, + "quantity": { + "reduce": { + "accessibilityLabel": "투표 옵션 {{amount}}으로 줄이기", + "accessibilityHint": "최소 투표 옵션 개수를 달성했어요, 현재 {{amount}}개에요" + }, + "increase": { + "accessibilityLabel": "투표 옵션 {{amount}}으로 늘리기", + "accessibilityHint": "최대 투표 옵션 개수를 달성했어요, 현재 {{amount}}개에요" + } + }, + "multiple": { + "heading": "선택 유형", + "options": { + "single": "단일 선택", + "multiple": "다중 선택", + "cancel": "$t(common:buttons.cancel)" + } + }, + "expiration": { + "heading": "유효기간", + "options": { + "300": "5분", + "1800": "30분", + "3600": "1시간", + "21600": "6시간", + "86400": "1일", + "259200": "3일", + "604800": "7일", + "cancel": "$t(common:buttons.cancel)" + } + } + } + }, + "actions": { + "attachment": { + "accessibilityLabel": "첨부 파일 업로드", + "accessibilityHint": "첨부 파일이 있으면 투표 기능은 비활성화되어요", + "failed": { + "alert": { + "title": "업로드 실패", + "button": "다시 시도해주세요" + } + } + }, + "poll": { + "accessibilityLabel": "투표 추가", + "accessibilityHint": "투표가 추가되면 첨부 파일 기능은 비활성화되어요" + }, + "visibility": { + "accessibilityLabel": "툿 공개 범위 {{visibility}}", + "title": "툿 공개 범위", + "options": { + "public": "공개", + "unlisted": "공개 타임라인에 비표시", + "private": "팔로워만", + "direct": "개인 메시지", + "cancel": "$t(common:buttons.cancel)" + } + }, + "spoiler": { + "accessibilityLabel": "스포일러" + }, + "emoji": { + "accessibilityLabel": "이모지 추가", + "accessibilityHint": "이모지 선택 패널 열기, 가로로 스와이프해서 페이지를 바꿀 수 있어요" + } + }, + "drafts": "초안 ({{count}})", + "drafts_plural": "초안 ({{count}})" + }, + "editAttachment": { + "header": { + "title": "첨부파일 편집", + "right": { + "accessibilityLabel": "첨부 파일 편집 저장", + "failed": { + "title": "편집 실패", + "button": "다시 시도해주세요" + } + } + }, + "content": { + "altText": { + "heading": "시각장애인을 위한 미디어 설명", + "placeholder": "미디어에 alt-text라고도 하는 설명을 추가하여 시각 장애가 있는 사람들을 포함하여 더 많은 사람들이 액세스할 수 있도록 할 수 있어요. \n\n좋은 설명은 간결하지만 미디어에 있는 내용을 정확하게 제시하여 컨텍스트를 파악할 수 있는 것이에요." + }, + "imageFocus": "포커스 원을 드래그하여 포커스 포인트를 업데이트할 수 있어요" + } + }, + "draftsList": { + "header": { + "title": "초안" + }, + "content": { + "accessibilityHint": "저장된 초안, 수정하려면 탭하세요", + "textEmpty": "콘텐츠 빔" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/screens/imageViewer.json b/src/i18n/ko/screens/imageViewer.json new file mode 100644 index 00000000..87bbff9d --- /dev/null +++ b/src/i18n/ko/screens/imageViewer.json @@ -0,0 +1,17 @@ +{ + "content": { + "actions": { + "accessibilityLabel": "이 이미지의 더 많은 동작", + "accessibilityHint": "이 이미지를 저장하거나 공유할 수 있어요" + }, + "options": { + "save": "이미지 저장", + "share": "이미지 공유", + "cancel": "$t(common:buttons.cancel)" + }, + "save": { + "succeed": "이미지 저장됨", + "failed": "이미지 저장 실패" + } + } +} \ No newline at end of file diff --git a/src/i18n/ko/screens/tabs.json b/src/i18n/ko/screens/tabs.json new file mode 100644 index 00000000..d7f6ef59 --- /dev/null +++ b/src/i18n/ko/screens/tabs.json @@ -0,0 +1,322 @@ +{ + "tabs": { + "local": { + "name": "팔로우 중" + }, + "public": { + "name": "", + "segments": { + "left": "연합", + "right": "로컬" + } + }, + "notifications": { + "name": "알림" + }, + "me": { + "name": "내 소개" + } + }, + "common": { + "search": { + "accessibilityLabel": "검색", + "accessibilityHint": "해시태그, 유저나 툿을 검색할 수 있어요" + } + }, + "notifications": { + "filter": { + "accessibilityLabel": "필터", + "accessibilityHint": "받는 알림 종류 선택" + } + }, + "me": { + "stacks": { + "bookmarks": { + "name": "북마크" + }, + "conversations": { + "name": "개인 메시지" + }, + "favourites": { + "name": "즐겨찾기" + }, + "fontSize": { + "name": "툿 폰트 크기" + }, + "lists": { + "name": "목록" + }, + "list": { + "name": "목록: {{list}}" + }, + "push": { + "name": "푸시 알림" + }, + "profile": { + "name": "프로필 편집" + }, + "profileName": { + "name": "표시 이름 편집" + }, + "profileNote": { + "name": "설명 편집" + }, + "profileFields": { + "name": "메타데이터 편집" + }, + "settings": { + "name": "앱 설정" + }, + "switch": { + "name": "계정 전환" + } + }, + "fontSize": { + "showcase": "예시 툿", + "demo": "

데모 툿이에요😊. 아래의 여러 옵션 중에서 선택할 수 있어요.

이 설정은 툿의 메인 내용에만 적용되고, 다른 폰트 크기에 영향을 미치지 않아요.

", + "availableSizes": "사용할 수 있는 크기", + "sizes": { + "S": "작게", + "M": "중간 - 기본값", + "L": "크게", + "XL": "더 크게", + "XXL": "아주 크게" + } + }, + "profile": { + "cancellation": { + "title": "변경사항이 저장되지 않음", + "message": "변경 사항이 저장되지 않았어요. 변경 사항 적용을 취소할까요?", + "buttons": { + "cancel": "$t(common:buttons.cancel)", + "discard": "취소" + } + }, + "feedback": { + "succeed": "{{type}} 업데이트됨", + "failed": "{{type}} 업데이트 실패, 다시 시도해주세요" + }, + "root": { + "name": { + "title": "표시 이름" + }, + "avatar": { + "title": "아바타", + "description": "400x400px으로 다운스케일되어요" + }, + "header": { + "title": "배너", + "description": "1500x500px으로 다운스케일되어요" + }, + "note": { + "title": "설명" + }, + "fields": { + "title": "메타데이터", + "total": "{{count}}개 필드", + "total_plural": "{{count}}개 필드" + }, + "visibility": { + "title": "공개 범위", + "options": { + "public": "공개", + "unlisted": "공개 타임라인에 비표시", + "private": "팔로워만", + "cancel": "$t(common:buttons.cancel)" + } + }, + "sensitive": { + "title": "미디어 민감함으로 포스트" + }, + "lock": { + "title": "계정 잠그기", + "description": "내가 직접 팔로워를 수락해야해요" + }, + "bot": { + "title": "봇 계정", + "description": "이 계정이 대부분 자동으로 작업을 수행하고 잘 확인하지 않는다는 것을 알려요." + } + }, + "fields": { + "group": "그룹 {{index}}", + "label": "라벨", + "content": "내용" + } + }, + "push": { + "notAvailable": "이 기기는 tooot의 푸시 알림을 지원하지 않아요", + "enable": { + "direct": "푸시 알림 활성화", + "settings": "설정에서 활성화" + }, + "global": { + "heading": "{{acct}} 활성화", + "description": "메시지는 tooot의 서버를 거쳐 라우트되어요" + }, + "decode": { + "heading": "메시지 세부 정보", + "description": "tooot의 서버를 거치는 메시지는 암호화되지만, 메시지를 서버에서 복호화하도록 설정할 수 있습니다. 서버의 소스는 오픈 소스이고, 로그하지 않습니다." + }, + "default": { + "heading": "기본값" + }, + "follow": { + "heading": "새 팔로워" + }, + "favourite": { + "heading": "즐겨찾기됨" + }, + "reblog": { + "heading": "부스트됨" + }, + "mention": { + "heading": "멘션했어요" + }, + "poll": { + "heading": "투표 업데이트" + }, + "howitworks": "라우팅 방법 알아보기" + }, + "root": { + "announcements": { + "content": { + "unread": "{{amount}}개 안 읽음", + "read": "모두 읽음", + "empty": "없음" + } + }, + "push": { + "content": { + "enabled": "활성화됨", + "disabled": "비활성화됨" + } + }, + "update": { + "title": "최신 버전으로 업데이트" + }, + "logout": { + "button": "로그아웃", + "alert": { + "title": "로그아웃할까요?", + "message": "로그아웃한 이후, 다시 로그인해야해요", + "buttons": { + "logout": "로그아웃", + "cancel": "$t(common:buttons.cancel)" + } + } + } + }, + "settings": { + "fontsize": { + "heading": "$t(me.stacks.fontSize.name)", + "content": { + "S": "$t(me.fontSize.sizes.S)", + "M": "$t(me.fontSize.sizes.M)", + "L": "$t(me.fontSize.sizes.L)", + "XL": "$t(me.fontSize.sizes.XL)", + "XXL": "$t(me.fontSize.sizes.XXL)" + } + }, + "language": { + "heading": "언어", + "options": { + "cancel": "$t(common:buttons.cancel)" + } + }, + "theme": { + "heading": "모양", + "options": { + "auto": "시스템과 동일", + "light": "밝은 모드", + "dark": "어두운 모드", + "cancel": "$t(common:buttons.cancel)" + } + }, + "browser": { + "heading": "링크 열기", + "options": { + "internal": "앱 안에서", + "external": "시스템 브라우저 사용", + "cancel": "$t(common:buttons.cancel)" + } + }, + "support": { + "heading": "tooot 기부" + }, + "review": { + "heading": "tooot 리뷰" + }, + "contact": { + "heading": "tooot 연락" + }, + "analytics": { + "heading": "개선할 수 있도록 도와주세요", + "description": "유저와 관련이 없는 사용량만 수집해요" + }, + "version": "버전 v{{version}}" + }, + "switch": { + "existing": "로그인된 것 중 선택", + "new": "인스턴스에 로그인" + } + }, + "shared": { + "account": { + "actions": { + "accessibilityLabel": "사용자 {{user}}에 대한 동작", + "accessibilityHint": "이 사용자를 뮤트, 차단, 신고 또는 공유할 수 있어요" + }, + "moved": "유저가 이동함", + "created_at": "등록된 날: {{date}}", + "summary": { + "statuses_count": "{{count}} 툿", + "following_count": "$t(shared.users.accounts.following)", + "followers_count": "$t(shared.users.accounts.followers)" + }, + "toots": { + "default": "툿", + "all": "툿과 답장" + } + }, + "attachments": { + "name": "<0 /><1>\"의 미디어" + }, + "search": { + "header": { + "prefix": "무엇을", + "placeholder": "검색할까요..." + }, + "empty": { + "general": "키워드를 입력해 $t(screenTabs:shared.search.sections.accounts), $t(screenTabs:shared.search.sections.hashtags)이나 $t(screenTabs:shared.search.sections.statuses)를 검색할 수 있어요", + "advanced": { + "header": "고급 검색", + "example": { + "account": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)", + "hashtag": "$t(shared.search.header.prefix) $t(shared.search.sections.hashtags)", + "statusLink": "$t(shared.search.header.prefix) $t(shared.search.sections.statuses)", + "accountLink": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)" + } + } + }, + "sections": { + "accounts": "사용자", + "hashtags": "해시태그", + "statuses": "툿" + }, + "notFound": "{{searchTerm}}와 관련된 {{type}}을 찾을 수 없어요" + }, + "toot": { + "name": "대화" + }, + "users": { + "accounts": { + "following": "팔로잉 {{count}}", + "followers": "{{count}} 팔로워" + }, + "statuses": { + "reblogged_by": "{{count}} 부스트함", + "favourited_by": "{{count}} 즐겨찾기함" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/locales.ts b/src/i18n/locales.ts index 532f37a6..593b400a 100644 --- a/src/i18n/locales.ts +++ b/src/i18n/locales.ts @@ -1,6 +1,8 @@ const LOCALES = { en: 'English', + ko: '한국어', + vi: 'Tiếng Việt', 'zh-Hans': '简体中文' -} as {en: string} +} export { LOCALES } diff --git a/src/i18n/vi/_all.ts b/src/i18n/vi/_all.ts new file mode 100644 index 00000000..d4c1b7c5 --- /dev/null +++ b/src/i18n/vi/_all.ts @@ -0,0 +1,17 @@ +export default { + common: require('./common'), + + screens: require('./screens'), + screenActions: require('./screens/actions'), + screenAnnouncements: require('./screens/announcements'), + screenCompose: require('./screens/compose'), + screenImageViewer: require('./screens/imageViewer'), + screenTabs: require('./screens/tabs'), + + componentInstance: require('./components/instance'), + componentMediaSelector: require('./components/mediaSelector'), + componentParse: require('./components/parse'), + componentRelationship: require('./components/relationship'), + componentRelativeTime: require('./components/relativeTime'), + componentTimeline: require('./components/timeline') +} diff --git a/src/i18n/vi/common.json b/src/i18n/vi/common.json new file mode 100644 index 00000000..813185d7 --- /dev/null +++ b/src/i18n/vi/common.json @@ -0,0 +1,21 @@ +{ + "buttons": { + "apply": "Áp dụng", + "cancel": "Hủy bỏ" + }, + "customEmoji": { + "accessibilityLabel": "Tùy chỉnh emoji {{emoji}}" + }, + "message": { + "success": { + "message": "Đã {{function}} xong!" + }, + "warning": { + "message": "" + }, + "error": { + "message": "{{function}} thất bại, xin thử lại sau" + } + }, + "separator": ", " +} \ No newline at end of file diff --git a/src/i18n/vi/components/instance.json b/src/i18n/vi/components/instance.json new file mode 100644 index 00000000..52931919 --- /dev/null +++ b/src/i18n/vi/components/instance.json @@ -0,0 +1,28 @@ +{ + "server": { + "textInput": { + "placeholder": "Máy chủ" + }, + "button": "Đăng nhập", + "information": { + "name": "Tên", + "accounts": "Người dùng", + "statuses": "Tút", + "domains": "Liên hợp" + }, + "disclaimer": { + "base": "tooot sẽ không thấy được thông tin tài khoản của bạn. Tìm hiểu thêm ", + "privacy": "Bảo mật" + } + }, + "update": { + "alert": { + "title": "Đang đăng nhập vào máy chủ", + "message": "Bạn có thể đăng nhập nhiều tài khoản cùng lúc", + "buttons": { + "cancel": "$t(common:buttons.cancel)", + "continue": "Tiếp tục" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/components/mediaSelector.json b/src/i18n/vi/components/mediaSelector.json new file mode 100644 index 00000000..022097e8 --- /dev/null +++ b/src/i18n/vi/components/mediaSelector.json @@ -0,0 +1,28 @@ +{ + "title": "Chọn nguồn", + "options": { + "library": "Từ thiết bị", + "photo": "Chụp ảnh", + "cancel": "$t(common:buttons.cancel)" + }, + "library": { + "alert": { + "title": "Chưa được cấp quyền", + "message": "Bạn cần cấp quyền đọc thư viện ảnh trước", + "buttons": { + "settings": "Cài đặt cập nhật", + "cancel": "$t(common:buttons.cancel)" + } + } + }, + "photo": { + "alert": { + "title": "Chưa cấp quyền", + "message": "Cần cấp quyền sử dụng camera trước", + "buttons": { + "settings": "Cài đặt cập nhật", + "cancel": "$t(common:buttons.cancel)" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/components/parse.json b/src/i18n/vi/components/parse.json new file mode 100644 index 00000000..3240627b --- /dev/null +++ b/src/i18n/vi/components/parse.json @@ -0,0 +1,9 @@ +{ + "HTML": { + "expanded": { + "true": "Thu gọn {{hint}}", + "false": "Mở rộng {{hint}}" + }, + "defaultHint": "Tút" + } +} \ No newline at end of file diff --git a/src/i18n/vi/components/relationship.json b/src/i18n/vi/components/relationship.json new file mode 100644 index 00000000..f9ccf6c6 --- /dev/null +++ b/src/i18n/vi/components/relationship.json @@ -0,0 +1,16 @@ +{ + "follow": { + "function": "Theo dõi người này" + }, + "block": { + "function": "Chặn người này" + }, + "button": { + "error": "Xảy ra lỗi khi tải", + "blocked_by": "Đã chặn", + "blocking": "Bỏ chặn", + "following": "Ngưng theo dõi", + "requested": "Yêu cầu theo dõi", + "default": "Theo dõi" + } +} \ No newline at end of file diff --git a/src/i18n/vi/components/relativeTime.json b/src/i18n/vi/components/relativeTime.json new file mode 100644 index 00000000..501807fe --- /dev/null +++ b/src/i18n/vi/components/relativeTime.json @@ -0,0 +1,20 @@ +{ + "strings": { + "prefixAgo": "", + "prefixFromNow": "", + "suffixAgo": "trước", + "suffixFromNow": "", + "seconds": "%d giây", + "minute": "một phút", + "minutes": "%d phút", + "hour": "một giờ", + "hours": "khoảng %d giờ", + "day": "một ngày", + "days": "%d ngày", + "month": "khoảng một tháng", + "months": "%d tháng", + "year": "khoảng một năm", + "years": "%d năm", + "wordSeparator": "" + } +} \ No newline at end of file diff --git a/src/i18n/vi/components/timeline.json b/src/i18n/vi/components/timeline.json new file mode 100644 index 00000000..2e4d305c --- /dev/null +++ b/src/i18n/vi/components/timeline.json @@ -0,0 +1,211 @@ +{ + "empty": { + "error": { + "message": "Lỗi khi tải dữ liệu", + "button": "Thử lại" + }, + "success": { + "message": "Bảng tin trống trơn" + } + }, + "end": { + "message": "Đã xem hết, uống <0 /> nha" + }, + "lookback": { + "message": "Đọc lần cuối lúc" + }, + "refresh": { + "fetchPreviousPage": "Trước đó", + "refetch": "Trang cuối" + }, + "shared": { + "actioned": { + "pinned": "Đã ghim", + "favourite": "{{name}} thích tút của bạn", + "status": "{{name}} đăng tút mới", + "follow": "{{name}} theo dõi bạn", + "follow_request": "{{name}} yêu cầu theo dõi bạn", + "poll": "Cuộc bình chọn đã kết thúc", + "reblog": { + "default": "{{name}} đã chia sẻ", + "notification": "{{name}} chia sẻ tút của bạn" + } + }, + "actions": { + "reply": { + "accessibilityLabel": "Trả lời tút này" + }, + "reblogged": { + "accessibilityLabel": "Chia sẻ tút này", + "function": "Chia sẻ tút" + }, + "favourited": { + "accessibilityLabel": "Thích tút này", + "function": "Thích tút" + }, + "bookmarked": { + "accessibilityLabel": "Lưu tút này", + "function": "Lưu tút" + } + }, + "actionsUsers": { + "reblogged_by": { + "accessibilityLabel": "{{count}} người đã chia sẻ tút này", + "accessibilityHint": "Xem những ai chia sẻ", + "text": "$t(screenTabs:shared.users.statuses.reblogged_by)" + }, + "favourited_by": { + "accessibilityLabel": "{{count}} người đã thích tút này", + "accessibilityHint": "Xem những ai thích", + "text": "$t(screenTabs:shared.users.statuses.favourited_by)" + } + }, + "attachment": { + "sensitive": { + "button": "Hiện nội dung nhạy cảm" + }, + "unsupported": { + "text": "Không hỗ trợ định dạng", + "button": "Thử liên kết từ xa" + } + }, + "avatar": { + "accessibilityLabel": "Ảnh đại diện của {{name}}", + "accessibilityHint": "Đến trang cá nhân {{name}}" + }, + "content": { + "expandHint": "nội dung bị ẩn" + }, + "filtered": "Đã lọc", + "fullConversation": "Xem thêm", + "translate": { + "default": "Dịch", + "succeed": "Dịch bằng {{provider}} từ {{source}}", + "failed": "Không thể dịch!" + }, + "header": { + "shared": { + "account": { + "name": { + "accessibilityHint": "Tên hiển thị" + }, + "account": { + "accessibilityHint": "Tài khoản" + } + }, + "application": "Đăng bằng {{application}}", + "muted": { + "accessibilityLabel": "Đã ẩn tút" + }, + "visibility": { + "direct": { + "accessibilityLabel": "Tút này là dạng nhắn riêng" + }, + "private": { + "accessibilityLabel": "Tuta này chỉ hiển thị với người theo dõi" + } + } + }, + "conversation": { + "withAccounts": "Với", + "delete": { + "function": "Xóa nhắn riêng" + } + }, + "actions": { + "accessibilityHint": "Hành động cho tút này, bao gồm đăng thủ công hay đăng tự động", + "account": { + "heading": "Đối với người dùng", + "mute": { + "function": "Ẩn người dùng", + "button": "Ẩn @{{acct}}" + }, + "block": { + "function": "Chặn người dùng", + "button": "Chặn @{{acct}}" + }, + "reports": { + "function": "Báo cáo người dùng", + "button": "Báo cáo @{{acct}}" + } + }, + "domain": { + "heading": "Đối với máy chủ", + "block": { + "function": "Chặn máy chủ", + "button": "Chặn {{domain}}" + }, + "alert": { + "title": "Bạn có chắc muốn chặn {{domain}}?", + "message": "Bạn có thể ẩn hoặc chặn bất kỳ người nào.\n\nĐối với máy chủ, toàn bộ nội dung bao gồm người theo dõi bạn từ máy chủ đó cũng sẽ bị chặn!", + "buttons": { + "confirm": "Tiếp tục chặn", + "cancel": "$t(common:buttons.cancel)" + } + } + }, + "share": { + "status": { + "heading": "Tút", + "button": "Chia sẻ URL tút" + }, + "account": { + "heading": "Chia sẻ người dùng", + "button": "Chia sẻ URL người dùng này" + } + }, + "status": { + "heading": "Về tút", + "delete": { + "function": "Xóa tút", + "button": "Xóa tút này" + }, + "edit": { + "function": "Xóa tút", + "button": "Xóa và viết lại", + "alert": { + "title": "Tiếp tục xóa tút?", + "message": "Bạn có chắc muốn xóa và viết lại tút này? Toàn bộ lượt thích, chia sẻ và trả lời tút cũng sẽ bị xóa theo.", + "buttons": { + "confirm": "Tiếp tục xóa", + "cancel": "$t(common:buttons.cancel)" + } + } + }, + "mute": { + "function": "Ẩn tút", + "button": { + "positive": "Ẩn tút này", + "negative": "Bỏ ẩn tút này" + } + }, + "pin": { + "function": "Ghim", + "button": { + "positive": "Ghim tút này", + "negative": "Bỏ ghim tút này" + } + } + } + } + }, + "poll": { + "meta": { + "button": { + "vote": "Bình chọn", + "refresh": "Làm mới" + }, + "count": { + "voters": "{{count}} người bình chọn", + "voters_plural": "{{count}} người bình chọn", + "votes": "{{count}} bình chọn", + "votes_plural": "{{count}} bình chọn" + }, + "expiration": { + "expired": "Đã kết thúc", + "until": "Kết thúc sau <0 />" + } + } + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens.json b/src/i18n/vi/screens.json new file mode 100644 index 00000000..5de1f9fc --- /dev/null +++ b/src/i18n/vi/screens.json @@ -0,0 +1,14 @@ +{ + "screenshot": { + "title": "Bảo vệ quyền riêng tư", + "message": "Hãy tôn trọng thông tin cá nhân của người khác như tên tài khoản, ảnh đại diện, nhắn riêng etc. Cám ơn!", + "button": "Xác nhận" + }, + "localCorrupt": { + "message": "Phiên đăng nhập hết hạn, hãy đăng nhập lại!" + }, + "pushError": { + "message": "Lỗi thông báo đẩy", + "description": "Hãy cho phép thông báo đẩy trong mục cài đặt!" + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens/actions.json b/src/i18n/vi/screens/actions.json new file mode 100644 index 00000000..ff9993c3 --- /dev/null +++ b/src/i18n/vi/screens/actions.json @@ -0,0 +1,19 @@ +{ + "content": { + "button": { + "apply": "$t(common:buttons.apply)", + "cancel": "$t(common:buttons.cancel)" + }, + "notificationsFilter": { + "heading": "Hiện những dạng thông báo", + "content": { + "follow": "$t(screenTabs:me.push.follow.heading)", + "favourite": "$t(screenTabs:me.push.favourite.heading)", + "reblog": "$t(screenTabs:me.push.reblog.heading)", + "mention": "$t(screenTabs:me.push.mention.heading)", + "poll": "$t(screenTabs:me.push.poll.heading)", + "follow_request": "Yêu cầu theo dõi" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens/announcements.json b/src/i18n/vi/screens/announcements.json new file mode 100644 index 00000000..451c3d5e --- /dev/null +++ b/src/i18n/vi/screens/announcements.json @@ -0,0 +1,10 @@ +{ + "heading": "Có gì mới?", + "content": { + "published": "Đã đăng <0 />", + "button": { + "read": "Đọc", + "unread": "Đánh dấu là đã đọc" + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens/compose.json b/src/i18n/vi/screens/compose.json new file mode 100644 index 00000000..ebc28f52 --- /dev/null +++ b/src/i18n/vi/screens/compose.json @@ -0,0 +1,169 @@ +{ + "heading": { + "left": { + "button": "Hủy bỏ", + "alert": { + "title": "Không đăng nữa?", + "buttons": { + "save": "Lưu bản nháp", + "delete": "Xóa bản nháp", + "cancel": "Hủy bỏ" + } + } + }, + "right": { + "button": { + "default": "Tút", + "conversation": "Tin nhắn", + "reply": "Lượt trả lời", + "edit": "Tút" + }, + "alert": { + "default": { + "title": "Đăng tút thất bại", + "button": "Thử lại" + }, + "removeReply": { + "title": "Tút trả lời sẽ không tìm thấy", + "description": "Đã xóa tút trả lời. Bạn có muốn xóa nguồn luôn không?", + "cancel": "$t(common:buttons.cancel)", + "confirm": "Xóa nguồn" + } + } + } + }, + "content": { + "root": { + "header": { + "postingAs": "Đăng với tư cách @{{acct}}@{{domain}}", + "spoilerInput": { + "placeholder": "Viết nội dung ẩn của bạn ở đây" + }, + "textInput": { + "placeholder": "Bạn đang nghĩ về điều gì?" + } + }, + "footer": { + "attachments": { + "sensitive": "Đánh dấu tập tin đính kèm là nhạy cảm", + "remove": { + "accessibilityLabel": "Xóa tập tin đính kèm, số {{attachment}}" + }, + "edit": { + "accessibilityLabel": "Sửa tập tin đính kèm, số {{attachment}}" + }, + "upload": { + "accessibilityLabel": "Tải lên thêm" + } + }, + "emojis": { + "accessibilityHint": "Chèn emoji" + }, + "poll": { + "option": { + "placeholder": { + "accessibilityLabel": "Tùy chọn bình chọn {{index}}", + "single": "Chỉ được chọn một", + "multiple": "Nhiều lựa chọn" + } + }, + "quantity": { + "reduce": { + "accessibilityLabel": "Giảm lựa chọn bình chọn tới {{amount}}", + "accessibilityHint": "Đã đạt số lựa chọn tối thiểu, gần đây là {{amount}}" + }, + "increase": { + "accessibilityLabel": "Tăng số lựa chọn lên {{amount}}", + "accessibilityHint": "Đã đạt số lựa chọn tối đa, hiện tại là {{amount}}" + } + }, + "multiple": { + "heading": "Kiểu bình chọn", + "options": { + "single": "Một lựa chọn", + "multiple": "Nhiều lựa chọn", + "cancel": "$t(common:buttons.cancel)" + } + }, + "expiration": { + "heading": "Thời hạn", + "options": { + "300": "5 phút", + "1800": "30 phút", + "3600": "1 giờ", + "21600": "6 giờ", + "86400": "1 ngày", + "259200": "3 ngày", + "604800": "7 ngày", + "cancel": "$t(common:buttons.cancel)" + } + } + } + }, + "actions": { + "attachment": { + "accessibilityLabel": "Tải lên đính kèm", + "accessibilityHint": "Không thể đính kèm tập tin trong cuộc bình chọn", + "failed": { + "alert": { + "title": "Tải lên thất bại", + "button": "Thử lại" + } + } + }, + "poll": { + "accessibilityLabel": "Tạo bình chọn", + "accessibilityHint": "Không thể đính kèm tập tin trong cuộc bình chọn" + }, + "visibility": { + "accessibilityLabel": "Tút thuộc dạng {{visibility}}", + "title": "Dạng tút", + "options": { + "public": "Công khai", + "unlisted": "Hạn chế", + "private": "Riêng tư", + "direct": "Nhắn riêng", + "cancel": "$t(common:buttons.cancel)" + } + }, + "spoiler": { + "accessibilityLabel": "Nội dung ẩn" + }, + "emoji": { + "accessibilityLabel": "Chèn emoji", + "accessibilityHint": "Mở bảng chọn emoji, vuốt qua lại để xem toàn bộ" + } + }, + "drafts": "Nháp ({{count}})", + "drafts_plural": "Nháp ({{count}})" + }, + "editAttachment": { + "header": { + "title": "Sửa tập tin đính kèm", + "right": { + "accessibilityLabel": "Lưu chỉnh sửa", + "failed": { + "title": "Không thể lưu những thay đổi", + "button": "Thử lại" + } + } + }, + "content": { + "altText": { + "heading": "Mô tả cho người khiếm thị", + "placeholder": "Bạn có thể thêm mô tả hay còn gọi là văn bản thay thế cho media, để những người mù hoặc khiếm thị có thể tiếp cận dễ dàng hơn.\n\nBạn có thể giới thiệu tóm tắt hoặc mô tả bối cảnh của nội dung media mà bạn sắp tải lên." + }, + "imageFocus": "Kéo thả vòng tròn để chọn phần hiển thị trên hình thu nhỏ" + } + }, + "draftsList": { + "header": { + "title": "Nháp" + }, + "content": { + "accessibilityHint": "Đã lưu nháp, nhấn để tiếp tục viết", + "textEmpty": "Chưa có nội dung" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens/imageViewer.json b/src/i18n/vi/screens/imageViewer.json new file mode 100644 index 00000000..a815b0cd --- /dev/null +++ b/src/i18n/vi/screens/imageViewer.json @@ -0,0 +1,17 @@ +{ + "content": { + "actions": { + "accessibilityLabel": "Thêm hành động cho ảnh này", + "accessibilityHint": "Bạn có thể lưu hoặc chia sẻ ảnh này" + }, + "options": { + "save": "Lưu ảnh", + "share": "Chia sẻ ảnh", + "cancel": "$t(common:buttons.cancel)" + }, + "save": { + "succeed": "Đã lưu ảnh", + "failed": "Lưu ảnh thất bại" + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens/tabs.json b/src/i18n/vi/screens/tabs.json new file mode 100644 index 00000000..60ac665b --- /dev/null +++ b/src/i18n/vi/screens/tabs.json @@ -0,0 +1,322 @@ +{ + "tabs": { + "local": { + "name": "Đang theo dõi" + }, + "public": { + "name": "", + "segments": { + "left": "Liên hợp", + "right": "Máy chủ" + } + }, + "notifications": { + "name": "Thông báo" + }, + "me": { + "name": "Tôi" + } + }, + "common": { + "search": { + "accessibilityLabel": "Tìm kiếm", + "accessibilityHint": "Thử tìm hashtag, người dùng hoặc tút" + } + }, + "notifications": { + "filter": { + "accessibilityLabel": "Lọc", + "accessibilityHint": "Lọc các dạng thông báo" + } + }, + "me": { + "stacks": { + "bookmarks": { + "name": "Đã lưu" + }, + "conversations": { + "name": "Nhắn riêng" + }, + "favourites": { + "name": "Lượt thích" + }, + "fontSize": { + "name": "Kích cỡ phông chữ" + }, + "lists": { + "name": "Danh sách" + }, + "list": { + "name": "Danh sách: {{list}}" + }, + "push": { + "name": "Thông báo đẩy" + }, + "profile": { + "name": "Trang cá nhân" + }, + "profileName": { + "name": "Tên hiển thị mới" + }, + "profileNote": { + "name": "Mô tả" + }, + "profileFields": { + "name": "Metadata" + }, + "settings": { + "name": "Cài đặt App" + }, + "switch": { + "name": "Chuyển đổi tài khoản" + } + }, + "fontSize": { + "showcase": "Kết quả", + "demo": "

Đây là một tút mẫu 😊 Bạn có thể chọn một trong nhiều lựa chọn bên dưới.

Tùy chọn này chỉ áp dụng cho nội dung tút chứ không thay đổi những phần khác của app.

", + "availableSizes": "Kích cỡ", + "sizes": { + "S": "S", + "M": "M - Mặc định", + "L": "L", + "XL": "XL", + "XXL": "XXL" + } + }, + "profile": { + "cancellation": { + "title": "Những thay đổi chưa được lưu", + "message": "Những thay đổi của bạn chưa được lưu. Bạn có muốn hủy bỏ?", + "buttons": { + "cancel": "$t(common:buttons.cancel)", + "discard": "Hủy bỏ" + } + }, + "feedback": { + "succeed": "Đã cập nhật {{type}}", + "failed": "Cập nhật {{type}} thất bại, xin thử lại" + }, + "root": { + "name": { + "title": "Tên hiển thị" + }, + "avatar": { + "title": "Ảnh đại diện", + "description": "Sẽ tự động chuyển còn 400x400px" + }, + "header": { + "title": "Ảnh bìa", + "description": "Sẽ tự động chuyển còn 1500x1500px" + }, + "note": { + "title": "Mô tả" + }, + "fields": { + "title": "Metadata", + "total": "{{count}} trường", + "total_plural": "{{count}} trường" + }, + "visibility": { + "title": "Dạng tút", + "options": { + "public": "Công khai", + "unlisted": "Hạn chế", + "private": "Riêng tư", + "cancel": "$t(common:buttons.cancel)" + } + }, + "sensitive": { + "title": "Đăng nội dung nhạy cảm" + }, + "lock": { + "title": "Đây là tài khoản riêng tư", + "description": "Tự bạn sẽ phê duyệt người theo dõi" + }, + "bot": { + "title": "Tài khoản bot", + "description": "Tài khoản này tự động thực hiện các hành động và không được quản lý bởi người thật" + } + }, + "fields": { + "group": "Nhóm {{index}}", + "label": "Nhãn", + "content": "Nội dung" + } + }, + "push": { + "notAvailable": "Điện thoại của bạn chưa bật thông báo đẩy", + "enable": { + "direct": "Bật thông báo đẩy", + "settings": "Bật trong cài đặt" + }, + "global": { + "heading": "Bật khi {{acct}}", + "description": "Thông báo được truyền qua máy chủ tooot" + }, + "decode": { + "heading": "Chi tiết thông báo", + "description": "Theo mặc định, thông báo truyền qua máy chủ tooot sẽ được mã hóa, nhưng bạn cũng có thể chọn không mã hóa. Máy chủ của chúng tôi luôn công khai mã nguồn và không lưu lại bất cứ gì." + }, + "default": { + "heading": "Mặc định" + }, + "follow": { + "heading": "Người theo dõi mới" + }, + "favourite": { + "heading": "Lượt thích" + }, + "reblog": { + "heading": "Lượt chia sẻ" + }, + "mention": { + "heading": "Lượt nhắc đến" + }, + "poll": { + "heading": "Kết quả bình chọn" + }, + "howitworks": "Tìm hiểu cách truyền" + }, + "root": { + "announcements": { + "content": { + "unread": "{{amount}} chưa đọc", + "read": "Tất cả đã đọc", + "empty": "Trống" + } + }, + "push": { + "content": { + "enabled": "Đã bật", + "disabled": "Đã tắt" + } + }, + "update": { + "title": "Cập nhật phiên bản mới" + }, + "logout": { + "button": "Đăng xuất", + "alert": { + "title": "Vẫn đăng xuất?", + "message": "Sau khi đăng xuất, bạn sẽ phải nhập lại mật khẩu", + "buttons": { + "logout": "Đăng xuất", + "cancel": "$t(common:buttons.cancel)" + } + } + } + }, + "settings": { + "fontsize": { + "heading": "$t(me.stacks.fontSize.name)", + "content": { + "S": "$t(me.fontSize.sizes.S)", + "M": "$t(me.fontSize.sizes.M)", + "L": "$t(me.fontSize.sizes.L)", + "XL": "$t(me.fontSize.sizes.XL)", + "XXL": "$t(me.fontSize.sizes.XXL)" + } + }, + "language": { + "heading": "Ngôn ngữ", + "options": { + "cancel": "$t(common:buttons.cancel)" + } + }, + "theme": { + "heading": "Giao diện", + "options": { + "auto": "Theo thiết bị", + "light": "Sáng", + "dark": "Tối", + "cancel": "$t(common:buttons.cancel)" + } + }, + "browser": { + "heading": "Mở liên kết", + "options": { + "internal": "Bằng app", + "external": "Bằng trình duyệt", + "cancel": "$t(common:buttons.cancel)" + } + }, + "support": { + "heading": "Ủng hộ tooot" + }, + "review": { + "heading": "Đánh giá tooot" + }, + "contact": { + "heading": "Liên hệ tooot" + }, + "analytics": { + "heading": "Đóng góp ý kiến", + "description": "Chỉ thu thập thông tin không liên quan người dùng" + }, + "version": "Phiên bản {{version}}" + }, + "switch": { + "existing": "Chọn từ màn hình đăng nhập", + "new": "Đăng nhập máy chủ" + } + }, + "shared": { + "account": { + "actions": { + "accessibilityLabel": "Hành động đối với {{user}}", + "accessibilityHint": "Bạn có thể ẩn, chặn, báo cáo hoặc chia sẻ người này" + }, + "moved": "Đã chuyển đi", + "created_at": "Đã tham gia {{date}}", + "summary": { + "statuses_count": "{{count}} tút", + "following_count": "$t(shared.users.accounts.following)", + "followers_count": "$t(shared.users.accounts.followers)" + }, + "toots": { + "default": "Tút", + "all": "Lượt trả lời" + } + }, + "attachments": { + "name": "<0 /><1>'s media" + }, + "search": { + "header": { + "prefix": "Đang tìm...", + "placeholder": "về..." + }, + "empty": { + "general": "Nhập từ khóa $t(screenTabs:shared.search.sections.accounts)$t(screenTabs:shared.search.sections.hashtags) hoặc$t(screenTabs:shared.search.sections.statuses)", + "advanced": { + "header": "Tìm kiếm nâng cao", + "example": { + "account": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)", + "hashtag": "$t(shared.search.header.prefix) $t(shared.search.sections.hashtags)", + "statusLink": "$t(shared.search.header.prefix) $t(shared.search.sections.statuses)", + "accountLink": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)" + } + } + }, + "sections": { + "accounts": "Người dùng", + "hashtags": "Hashtag", + "statuses": "Tút" + }, + "notFound": "Không tìm thấy {{type}} {{searchTerm}}" + }, + "toot": { + "name": "Thảo luận" + }, + "users": { + "accounts": { + "following": "Đang theo dõi {{count}}", + "followers": "{{count}} người theo dõi" + }, + "statuses": { + "reblogged_by": "{{count}} người chia sẻ", + "favourited_by": "{{count}} người thích" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/zh-Hans/screens/tabs.json b/src/i18n/zh-Hans/screens/tabs.json index e9dc4611..3c9ea0f6 100644 --- a/src/i18n/zh-Hans/screens/tabs.json +++ b/src/i18n/zh-Hans/screens/tabs.json @@ -144,7 +144,7 @@ } }, "push": { - "notAvailable": "您的机型暂不支持 tooot 推送通知", + "notAvailable": "您的手机不支持tooot推送通知", "enable": { "direct": "启用推送通知", "settings": "在系统设置中启用" diff --git a/src/screens/Tabs/Local.tsx b/src/screens/Tabs/Local.tsx index 8f444231..53cadbb2 100644 --- a/src/screens/Tabs/Local.tsx +++ b/src/screens/Tabs/Local.tsx @@ -8,11 +8,9 @@ import { TabLocalStackParamList } from '@utils/navigation/navigators' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import { getInstanceTimelinesLookback } from '@utils/slices/instancesSlice' import React, { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { Platform } from 'react-native' -import { useSelector } from 'react-redux' import TabSharedRoot from './Shared/Root' const Stack = createNativeStackNavigator() @@ -45,17 +43,11 @@ const TabLocal = React.memo( [i18n.language] ) - const timelinesLookback = useSelector( - getInstanceTimelinesLookback, - () => true - ) const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }] - const renderItem = useCallback(({ item }) => { - if (timelinesLookback?.['Following']?.ids?.[0] === item.id) { - return - } - return - }, []) + const renderItem = useCallback( + ({ item }) => , + [] + ) const children = useCallback( () => ( { const queryKey: QueryKeyTimeline = ['Timeline', { page }] - const renderItem = ({ item }: any) => { - if (timelinesLookback?.[page]?.ids?.[0] === item.id) { - return - } - return - } return ( ( + + ) + }} /> ) }, diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index e4f3408b..990ddb96 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -53,7 +53,7 @@ const TabSharedToot: React.FC> = ({ }, 500) } catch (err) { if (Math.random() < 0.1) { - Sentry.Native.setExtras({ + Sentry.Native.setContext('Scroll to Index', { type: 'original', index: pointer, itemsLength: flattenData.length, @@ -84,7 +84,7 @@ const TabSharedToot: React.FC> = ({ ) } catch (err) { if (Math.random() < 0.1) { - Sentry.Native.setExtras({ + Sentry.Native.setContext('Scroll to Index', { type: 'onScrollToIndexFailed', index: error.index, itemsLength diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index 66a55d96..384db03e 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -2,10 +2,7 @@ import apiInstance, { InstanceResponse } from '@api/instance' import haptics from '@components/haptics' import queryClient from '@helpers/queryClient' import { store } from '@root/store' -import { - getInstanceNotificationsFilter, - updateInstanceTimelineLookback -} from '@utils/slices/instancesSlice' +import { getInstanceNotificationsFilter } from '@utils/slices/instancesSlice' import { AxiosError } from 'axios' import { uniqBy } from 'lodash' import { diff --git a/src/utils/slices/contextsSlice.ts b/src/utils/slices/contextsSlice.ts index 24c93cd6..65d7c2e1 100644 --- a/src/utils/slices/contextsSlice.ts +++ b/src/utils/slices/contextsSlice.ts @@ -3,8 +3,6 @@ import { RootState } from '@root/store' import * as Updates from 'expo-updates' import * as StoreReview from 'expo-store-review' -export const supportedLngs = ['zh-Hans', 'en'] - export type ContextsState = { storeReview: { context: Readonly diff --git a/src/utils/slices/instancesSlice.ts b/src/utils/slices/instancesSlice.ts index 80d825aa..3bc3b4d9 100644 --- a/src/utils/slices/instancesSlice.ts +++ b/src/utils/slices/instancesSlice.ts @@ -169,10 +169,11 @@ const instancesSlice = createSlice({ action: PayloadAction ) => { const activeIndex = findInstanceActive(instances) - instances[activeIndex].timelinesLookback = { - ...instances[activeIndex].timelinesLookback, - ...action.payload - } + instances[activeIndex] && + (instances[activeIndex].timelinesLookback = { + ...instances[activeIndex].timelinesLookback, + ...action.payload + }) }, updateInstanceMePage: ( { instances }, diff --git a/src/utils/slices/settingsSlice.ts b/src/utils/slices/settingsSlice.ts index fb2a6bb1..0436af47 100644 --- a/src/utils/slices/settingsSlice.ts +++ b/src/utils/slices/settingsSlice.ts @@ -1,14 +1,10 @@ import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' +import { LOCALES } from '@root/i18n/locales' import { RootState } from '@root/store' import * as Analytics from 'expo-firebase-analytics' import * as Localization from 'expo-localization' import { pickBy } from 'lodash' -enum AvailableLanguages { - 'zh-Hans', - 'en' -} - export const changeAnalytics = createAsyncThunk( 'settings/changeAnalytics', async (newValue: SettingsState['analytics']) => { @@ -31,12 +27,10 @@ export const settingsInitialState = { enabled: false }, language: Object.keys( - pickBy(AvailableLanguages, (_, key) => Localization.locale.includes(key)) + pickBy(LOCALES, (_, key) => Localization.locale.startsWith(key)) ) ? Object.keys( - pickBy(AvailableLanguages, (_, key) => - Localization.locale.includes(key) - ) + pickBy(LOCALES, (_, key) => Localization.locale.startsWith(key)) )[0] : 'en', theme: 'auto', @@ -88,10 +82,6 @@ export const getSettingsBrowser = (state: RootState) => state.settings.browser export const getSettingsAnalytics = (state: RootState) => state.settings.analytics -export const { - changeFontsize, - changeLanguage, - changeTheme, - changeBrowser -} = settingsSlice.actions +export const { changeFontsize, changeLanguage, changeTheme, changeBrowser } = + settingsSlice.actions export default settingsSlice.reducer diff --git a/yarn.lock b/yarn.lock index f9d0ace2..ca667ec9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2676,12 +2676,12 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -axios@0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== +axios@0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== dependencies: - follow-redirects "^1.14.7" + follow-redirects "^1.14.4" babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" @@ -4170,7 +4170,7 @@ flow-parser@^0.121.0: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f" integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg== -follow-redirects@^1.14.7: +follow-redirects@^1.14.4: version "1.14.7" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== @@ -6524,10 +6524,10 @@ react-native-pager-view@5.4.9: resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-5.4.9.tgz#c0d40847cfeda5a4e729b53271b0ee0fedff3eb5" integrity sha512-D6tzxpwMGdl6CXgtskGWhKRc5cJakCazESRGt7PkqnpyiH3N35ft1KmR82pCSQetAFlytFiToeu3a/dG5CELvA== -react-native-reanimated@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.3.1.tgz#c7abad48f9e6c84610b0d5e270088ecd61750382" - integrity sha512-nzjVqwkB8eeyPKT2KoiA9EEz17ZMFSGMoOTC17Z9b5nE2Z4ZHjHM5EKhY0TlwzXFUuJAE9PhOfxF0wIO/maZSA== +react-native-reanimated@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.4.0.tgz#660860f3c9d36dc09e80e784306591c67060f940" + integrity sha512-KogpQaRxFu2jgIEWRwoHaTQ2TQbHva49rJFnXtEdMZ5LJefVMFITiEwRuyjlD4ZWpstFiaP0mWkR6uuS2APutA== dependencies: "@babel/plugin-transform-object-assign" "^7.10.4" "@types/invariant" "^2.2.35" @@ -6613,10 +6613,10 @@ react-native@0.66.4: whatwg-fetch "^3.0.0" ws "^6.1.4" -react-query@3.34.12: - version "3.34.12" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.12.tgz#dcaaf7b629f0868aae8afef9fb7692f6ea7643bf" - integrity sha512-flDdudQVH4CqE+kNYYYyo4g2Yjek3H/36G3b9bK5oe26jD5gFnx+PPwnq0gayq5z2dcSfr2z4+drvuyeZ3A5QQ== +react-query@3.34.14: + version "3.34.14" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.14.tgz#ba944c1c36bbeab3e7037c42e8e862acd73111ff" + integrity sha512-KVMnM8omt+81oO9fPZfM65pGhQilpWzGsNwAqeeLMB2sG3xwY3bpIEYbhDf7FFgsqhAQfSzmCL4gRSiJaWIDwA== dependencies: "@babel/runtime" "^7.5.5" broadcast-channel "^3.4.1"