Merge pull request #210 from tooot-app/main

Test v3.4.0
This commit is contained in:
xmflsct 2022-02-06 23:28:33 +01:00 committed by GitHub
commit 5fea788b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 1931 additions and 80 deletions

View File

@ -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

View File

@ -1,4 +1,4 @@
languages(['zh-Hans', 'en-US'])
languages(['zh-Hans', 'vi', 'ko', 'en-US'])
name({
'default' => "tooot"

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

View File

@ -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

View File

@ -71,13 +71,15 @@
<string>armv7</string>
</array>
<key>UIRequiresFullScreen</key>
<true/>
<false/>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Automatic</string>

View File

@ -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",

View File

@ -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

View File

@ -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) {

View File

@ -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"
}
}

View File

@ -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": ""
}
}

View File

@ -0,0 +1,10 @@
{
"heading": "Ankündigungen",
"content": {
"published": "<0 /> veröffentlicht",
"button": {
"read": "Lesen",
"unread": "Als gelesen markieren"
}
}
}

View File

@ -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) => {

17
src/i18n/ko/_all.ts Normal file
View File

@ -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')
}

21
src/i18n/ko/common.json Normal file
View File

@ -0,0 +1,21 @@
{
"buttons": {
"apply": "적용",
"cancel": "취소"
},
"customEmoji": {
"accessibilityLabel": "커스텀 이모지 {{emoji}}"
},
"message": {
"success": {
"message": "{{function}} 성공"
},
"warning": {
"message": ""
},
"error": {
"message": "{{function}} 실패, 다시 시도해주세요"
}
},
"separator": ", "
}

View File

@ -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": "계속"
}
}
}
}

View File

@ -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)"
}
}
}
}

View File

@ -0,0 +1,9 @@
{
"HTML": {
"expanded": {
"true": "{{hint}} 접기",
"false": "{{hint}} 펼치기"
},
"defaultHint": "글"
}
}

View File

@ -0,0 +1,16 @@
{
"follow": {
"function": "사용자 팔로우"
},
"block": {
"function": "사용자 차단"
},
"button": {
"error": "불러오기 오류",
"blocked_by": "차단된 사용자",
"blocking": "차단 해제",
"following": "팔로우 해제",
"requested": "요청 취소",
"default": "팔로우"
}
}

View File

@ -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": ""
}
}

View File

@ -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 />후 만료"
}
}
}
}
}

14
src/i18n/ko/screens.json Normal file
View File

@ -0,0 +1,14 @@
{
"screenshot": {
"title": "개인정보 보호",
"message": "다른 사용자의 사용자 이름이나, 아바타 등의 정보를 유출하지 말아주세요. 고마워요!",
"button": "확인"
},
"localCorrupt": {
"message": "로그인이 만료되었어요. 다시 로그인해주세요"
},
"pushError": {
"message": "푸시 서비스 오류",
"description": "푸시 알림을 설정에서 다시 활성화해주세요"
}
}

View File

@ -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": "팔로우 요청"
}
}
}
}

View File

@ -0,0 +1,10 @@
{
"heading": "공지",
"content": {
"published": "올려짐 <0 />",
"button": {
"read": "읽음",
"unread": "읽음으로 표시"
}
}
}

View File

@ -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": "콘텐츠 빔"
}
}
}
}

View File

@ -0,0 +1,17 @@
{
"content": {
"actions": {
"accessibilityLabel": "이 이미지의 더 많은 동작",
"accessibilityHint": "이 이미지를 저장하거나 공유할 수 있어요"
},
"options": {
"save": "이미지 저장",
"share": "이미지 공유",
"cancel": "$t(common:buttons.cancel)"
},
"save": {
"succeed": "이미지 저장됨",
"failed": "이미지 저장 실패"
}
}
}

View File

@ -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": "<p>데모 툿이에요😊. 아래의 여러 옵션 중에서 선택할 수 있어요.<br /><br />이 설정은 툿의 메인 내용에만 적용되고, 다른 폰트 크기에 영향을 미치지 않아요.</p>",
"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>\"의 미디어</1>"
},
"search": {
"header": {
"prefix": "무엇을",
"placeholder": "검색할까요..."
},
"empty": {
"general": "키워드를 입력해 <bold>$t(screenTabs:shared.search.sections.accounts)</bold>, <bold>$t(screenTabs:shared.search.sections.hashtags)</bold>이나 <bold>$t(screenTabs:shared.search.sections.statuses)</bold>를 검색할 수 있어요",
"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": "<bold>{{searchTerm}}</bold>와 관련된 {{type}}을 찾을 수 없어요"
},
"toot": {
"name": "대화"
},
"users": {
"accounts": {
"following": "팔로잉 {{count}}",
"followers": "{{count}} 팔로워"
},
"statuses": {
"reblogged_by": "{{count}} 부스트함",
"favourited_by": "{{count}} 즐겨찾기함"
}
}
}
}

View File

@ -1,6 +1,8 @@
const LOCALES = {
en: 'English',
ko: '한국어',
vi: 'Tiếng Việt',
'zh-Hans': '简体中文'
} as {en: string}
}
export { LOCALES }

17
src/i18n/vi/_all.ts Normal file
View File

@ -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')
}

21
src/i18n/vi/common.json Normal file
View File

@ -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": ", "
}

View File

@ -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"
}
}
}
}

View File

@ -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)"
}
}
}
}

View File

@ -0,0 +1,9 @@
{
"HTML": {
"expanded": {
"true": "Thu gọn {{hint}}",
"false": "Mở rộng {{hint}}"
},
"defaultHint": "Tút"
}
}

View File

@ -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"
}
}

View File

@ -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": ""
}
}

View File

@ -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 />"
}
}
}
}
}

14
src/i18n/vi/screens.json Normal file
View File

@ -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!"
}
}

View File

@ -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"
}
}
}
}

View File

@ -0,0 +1,10 @@
{
"heading": "Có gì mới?",
"content": {
"published": "Đã đăng <0 />",
"button": {
"read": "Đọc",
"unread": "Đánh dấu là đã đọc"
}
}
}

View File

@ -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"
}
}
}
}

View File

@ -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"
}
}
}

View File

@ -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": "<p>Đâ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.<br /><br />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.</p>",
"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</1>"
},
"search": {
"header": {
"prefix": "Đang tìm...",
"placeholder": "về..."
},
"empty": {
"general": "Nhập từ khóa <bold>$t(screenTabs:shared.search.sections.accounts)</bold>、<bold>$t(screenTabs:shared.search.sections.hashtags)</bold> hoặc<bold>$t(screenTabs:shared.search.sections.statuses)</bold>",
"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}} <bold>{{searchTerm}}</bold>"
},
"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"
}
}
}
}

View File

@ -144,7 +144,7 @@
}
},
"push": {
"notAvailable": "您的型暂不支持 tooot 推送通知",
"notAvailable": "您的机不支持tooot推送通知",
"enable": {
"direct": "启用推送通知",
"settings": "在系统设置中启用"

View File

@ -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<TabLocalStackParamList>()
@ -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 <TimelineDefault item={item} queryKey={queryKey} />
}
return <TimelineDefault item={item} queryKey={queryKey} />
}, [])
const renderItem = useCallback(
({ item }) => <TimelineDefault item={item} queryKey={queryKey} />,
[]
)
const children = useCallback(
() => (
<Timeline

View File

@ -85,17 +85,15 @@ const TabPublic = React.memo(
}
}) => {
const queryKey: QueryKeyTimeline = ['Timeline', { page }]
const renderItem = ({ item }: any) => {
if (timelinesLookback?.[page]?.ids?.[0] === item.id) {
return <TimelineDefault item={item} queryKey={queryKey} />
}
return <TimelineDefault item={item} queryKey={queryKey} />
}
return (
<Timeline
queryKey={queryKey}
lookback={page}
customProps={{ renderItem }}
customProps={{
renderItem: ({ item }: any) => (
<TimelineDefault item={item} queryKey={queryKey} />
)
}}
/>
)
},

View File

@ -53,7 +53,7 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
}, 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<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
)
} catch (err) {
if (Math.random() < 0.1) {
Sentry.Native.setExtras({
Sentry.Native.setContext('Scroll to Index', {
type: 'onScrollToIndexFailed',
index: error.index,
itemsLength

View File

@ -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 {

View File

@ -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<number>

View File

@ -169,10 +169,11 @@ const instancesSlice = createSlice({
action: PayloadAction<Instance['timelinesLookback']>
) => {
const activeIndex = findInstanceActive(instances)
instances[activeIndex].timelinesLookback = {
...instances[activeIndex].timelinesLookback,
...action.payload
}
instances[activeIndex] &&
(instances[activeIndex].timelinesLookback = {
...instances[activeIndex].timelinesLookback,
...action.payload
})
},
updateInstanceMePage: (
{ instances },

View File

@ -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

View File

@ -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"