Update en strings

This commit is contained in:
Zhiyuan Zheng 2021-01-20 00:39:39 +01:00
parent 5a248716bf
commit 314bc31e32
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
57 changed files with 826 additions and 191 deletions

28
.github/workflows/production.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: Publish production
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: -- Step 1 -- Checkout code
uses: actions/checkout@v2
- name: -- Step 2 -- Setup node
uses: actions/setup-node@v2
with:
node-version: 14.x
- name: -- Step 3 -- Use Expo action
uses: expo/expo-github-action@v5
with:
expo-version: 4.x
expo-username: ${{ secrets.EXPO_USERNAME }}
expo-token: ${{ secrets.EXPO_TOKEN }}
expo-cache: true
- name: -- Step 4 -- Install dependencies
run: yarn install
- name: -- Step 5 -- Publish
env:
SENTRY_DEPLOY_ENV: production
run: expo publish --release-channel=production

28
.github/workflows/staging.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: Publish staging
on:
push:
branches:
- staging
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: -- Step 1 -- Checkout code
uses: actions/checkout@v2
- name: -- Step 2 -- Setup node
uses: actions/setup-node@v2
with:
node-version: 14.x
- name: -- Step 3 -- Use Expo action
uses: expo/expo-github-action@v5
with:
expo-version: 4.x
expo-username: ${{ secrets.EXPO_USERNAME }}
expo-token: ${{ secrets.EXPO_TOKEN }}
expo-cache: true
- name: -- Step 4 -- Install dependencies
run: yarn install
- name: -- Step 5 -- Publish
env:
SENTRY_DEPLOY_ENV: staging
run: expo publish --release-channel=staging

View File

@ -24,7 +24,5 @@ jobs:
run: yarn install
- name: -- Step 5 -- Publish
env:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DEPLOY_ENV: testing
run: expo publish --release-channel=testing

View File

@ -1,4 +1,5 @@
import { ExpoConfig } from '@expo/config'
import 'dotenv/config'
export default (): ExpoConfig => ({
name: 'tooot',
@ -30,24 +31,31 @@ export default (): ExpoConfig => ({
googleServicesFile: './configs/google-services.json',
permissions: ['CAMERA', 'VIBRATE']
},
// locales: {
// zh: {
// CFBundleDisplayName: '嘟嘟嘟',
// NSCameraUsageDescription: '允许嘟嘟嘟用相机上传照片',
// NSPhotoLibraryUsageDescription: '允许嘟嘟嘟用相册上传照片'
// },
// en: {
// CFBundleDisplayName: 'tooot'
// }
// },
locales: {
zh: './src/i18n/zh-Hans/system.json'
// en: {
// NSCameraUsageDescription: '允许嘟嘟嘟用相机上传照片',
// NSPhotoLibraryUsageDescription: '允许嘟嘟嘟用相册上传照片'
// }
},
assetBundlePatterns: ['assets/*'],
hooks: {
postPublish: [
{
file: 'sentry-expo/upload-sourcemaps'
file: 'sentry-expo/upload-sourcemaps',
config: {
organization: process.env.SENTRY_ORGANIZATION,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
setCommits: process.env.GITHUB_SHA || undefined,
deployEnv: process.env.SENTRY_DEPLOY_ENV
}
}
]
},
extra: {
sentryDSN: process.env.SENTRY_DSN
},
web: {
config: {
firebase: {

View File

@ -99,6 +99,7 @@
"@welldone-software/why-did-you-render": "^6.0.4",
"babel-plugin-module-resolver": "^4.1.0",
"chalk": "^4.1.0",
"dotenv": "^8.2.0",
"jest": "^26.6.3",
"jest-expo": "^40.0.1",
"nock": "^13.0.5",

View File

@ -106,7 +106,7 @@ const GracefullyImage: React.FC<Props> = ({
}
return
} catch (error) {
if (__DEV__) console.warn('Image preview', error)
if (__DEV__) console.warn('Image', error)
}
}

View File

@ -96,7 +96,10 @@ const ComponentInstance: React.FC<Props> = ({
t('update.local.alert.title'),
t('update.local.alert.message'),
[
{ text: t('update.local.alert.buttons.cancel'), style: 'cancel' },
{
text: t('update.local.alert.buttons.cancel'),
style: 'cancel'
},
{
text: t('update.local.alert.buttons.continue'),
onPress: () => {
@ -232,23 +235,25 @@ const ComponentInstance: React.FC<Props> = ({
potentialWidth={4}
/>
</View>
<View style={styles.disclaimer}>
<Icon
name='Lock'
size={StyleConstants.Font.Size.S}
color={theme.secondary}
style={styles.disclaimerIcon}
/>
<Text
style={[styles.disclaimerText, { color: theme.secondary }]}
onPress={() => Linking.openURL('https://tooot.app/privacy')}
>
{t('server.disclaimer')}
<Text style={{ color: theme.blue }}>
https://tooot.app/privacy
{type === 'local' ? (
<View style={styles.disclaimer}>
<Icon
name='Lock'
size={StyleConstants.Font.Size.S}
color={theme.secondary}
style={styles.disclaimerIcon}
/>
<Text
style={[styles.disclaimerText, { color: theme.secondary }]}
onPress={() => Linking.openURL('https://tooot.app/privacy')}
>
{t('server.disclaimer')}
<Text style={{ color: theme.blue }}>
https://tooot.app/privacy
</Text>
</Text>
</Text>
</View>
</View>
) : null}
</View>
</View>

View File

@ -6,6 +6,7 @@ import {
useRelationshipMutation,
useRelationshipQuery
} from '@utils/queryHooks/relationship'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useQueryClient } from 'react-query'
@ -23,12 +24,16 @@ const RelationshipOutgoing = React.memo(
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }]
const queryClient = useQueryClient()
const mutation = useRelationshipMutation({
onSuccess: res => {
onSuccess: (res, { payload: { action } }) => {
haptics('Success')
queryClient.setQueryData<Mastodon.Relationship[]>(
queryKeyRelationship,
[res]
)
if (action === 'follow' || action === 'block') {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }]
queryClient.invalidateQueries(queryKey)
}
},
onError: (err: any, { payload: { action } }) => {
haptics('Error')

View File

@ -68,7 +68,7 @@ const Timeline: React.FC<Props> = ({
...queryKeyParams,
options: {
getPreviousPageParam: firstPage => {
return firstPage.length
return Array.isArray(firstPage) && firstPage.length
? {
direction: 'prev',
id: firstPage[0].last_status
@ -78,7 +78,7 @@ const Timeline: React.FC<Props> = ({
: undefined
},
getNextPageParam: lastPage => {
return lastPage.length
return Array.isArray(lastPage) && lastPage.length
? {
direction: 'next',
id: lastPage[lastPage.length - 1].last_status
@ -176,22 +176,22 @@ const Timeline: React.FC<Props> = ({
(isFetching && !isFetchingNextPage && !isLoading)
}
onRefresh={() => {
if (hasPreviousPage) {
fetchPreviousPage()
} else {
queryClient.setQueryData<InfiniteData<any> | undefined>(
queryKey,
data => {
if (data) {
return {
pages: data.pages.slice(1),
pageParams: data.pageParams.slice(1)
}
}
}
)
refetch()
}
// if (hasPreviousPage) {
// fetchPreviousPage()
// } else {
// queryClient.setQueryData<InfiniteData<any> | undefined>(
// queryKey,
// data => {
// if (data) {
// return {
// pages: data.pages.slice(1),
// pageParams: data.pageParams.slice(1)
// }
// }
// }
// )
refetch()
// }
}}
/>
),

View File

@ -169,27 +169,53 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
)
const childrenReblog = useMemo(
() => (
<Icon
name='Repeat'
color={
status.visibility === 'private' || status.visibility === 'direct'
? theme.disabled
: iconColorAction(status.reblogged)
}
size={StyleConstants.Font.Size.L}
/>
<>
<Icon
name='Repeat'
color={
status.visibility === 'private' || status.visibility === 'direct'
? theme.disabled
: iconColorAction(status.reblogged)
}
size={StyleConstants.Font.Size.L}
/>
{status.reblogs_count > 0 && (
<Text
style={{
color: theme.secondary,
...StyleConstants.FontStyle.M,
marginLeft: StyleConstants.Spacing.XS
}}
>
{status.reblogs_count}
</Text>
)}
</>
),
[status.reblogged]
[status.reblogged, status.reblogs_count]
)
const childrenFavourite = useMemo(
() => (
<Icon
name='Heart'
color={iconColorAction(status.favourited)}
size={StyleConstants.Font.Size.L}
/>
<>
<Icon
name='Heart'
color={iconColorAction(status.favourited)}
size={StyleConstants.Font.Size.L}
/>
{status.favourites_count > 0 && (
<Text
style={{
color: theme.secondary,
...StyleConstants.FontStyle.M,
marginLeft: StyleConstants.Spacing.XS
}}
>
{status.favourites_count}
</Text>
)}
</>
),
[status.favourited]
[status.favourited, status.favourites_count]
)
const childrenBookmark = useMemo(
() => (
@ -245,6 +271,7 @@ const styles = StyleSheet.create({
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingVertical: StyleConstants.Spacing.S
}
})

View File

@ -41,10 +41,7 @@ const HeaderActionsAccount: React.FC<Props> = ({
toast({
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(
`shared.header.actions.account.${property}.function`,
{ acct: account.acct }
)
function: t(`shared.header.actions.account.${property}.function`)
}),
...(err.status &&
typeof err.status === 'number' &&
@ -62,9 +59,7 @@ const HeaderActionsAccount: React.FC<Props> = ({
return (
<MenuContainer>
<MenuHeader
heading={t('shared.header.actions.account.heading')}
/>
<MenuHeader heading={t('shared.header.actions.account.heading')} />
<MenuRow
onPress={() => {
setBottomSheetVisible(false)
@ -91,12 +86,9 @@ const HeaderActionsAccount: React.FC<Props> = ({
})
}}
iconFront='XCircle'
title={t(
'shared.header.actions.account.block.button',
{
acct: account.acct
}
)}
title={t('shared.header.actions.account.block.button', {
acct: account.acct
})}
/>
<MenuRow
onPress={() => {
@ -109,12 +101,9 @@ const HeaderActionsAccount: React.FC<Props> = ({
})
}}
iconFront='Flag'
title={t(
'shared.header.actions.account.reports.button',
{
acct: account.acct
}
)}
title={t('shared.header.actions.account.reports.button', {
acct: account.acct
})}
/>
</MenuContainer>
)

View File

@ -128,7 +128,7 @@ const TimelinePoll: React.FC<Props> = ({
return (
<Text style={[styles.expiration, { color: theme.secondary }]}>
<Trans
i18nKey='timeline:shared.poll.meta.expiration.until'
i18nKey='componentTimeline:shared.poll.meta.expiration.until'
components={[<RelativeTime date={poll.expires_at} />]}
/>
</Text>

View File

@ -1,5 +1,32 @@
export default {
common: require('./common').default,
local: require('./screens/local').default,
public: require('./screens/public').default,
notifications: require('./screens/notifications').default,
meRoot: require('./screens/meRoot').default,
meConversations: require('./screens/meConversations').default,
meBookmarks: require('./screens/meBookmarks').default,
meFavourites: require('./screens/meFavourites').default,
meLists: require('./screens/meLists').default,
meListsList: require('./screens/meListsList').default,
meSettings: require('./screens/meSettings').default,
meSettingsUpdateRemote: require('./screens/meSettingsUpdateRemote').default,
meSwitch: require('./screens/meSwitch').default,
sharedAccount: require('./screens/sharedAccount').default,
sharedAnnouncements: require('./screens/sharedAnnouncements').default,
sharedCompose: require('./screens/sharedCompose').default,
sharedRelationships: require('./screens/sharedRelationships').default,
sharedSearch: require('./screens/sharedSearch').default,
sharedToot: require('./screens/sharedToot').default,
componentInstance: require('./components/instance').default,
componentParse: require('./components/parse').default,
componentRelationship: require('./components/relationship').default,
componentRelativeTime: require('./components/relativeTime').default,
componentTimeline: require('./components/timeline').default
}

View File

@ -1,31 +1,16 @@
export default {
headers: {
local: {
segments: {
left: 'Following',
right: 'Local'
}
buttons: {
cancel: 'Cancel'
},
toastMessage: {
success: {
message: '{{function}} succeed'
},
public: {
segments: {
left: 'Federated',
right: 'Others'
}
warning: {
message: ''
},
notifications: 'Notifications',
me: {
root: 'My Mastodon',
conversations: 'Messages',
bookmarks: 'Booksmarks',
favourites: 'Favourites',
lists: {
root: 'Lists',
list: 'List {{list}}'
},
settings: {
root: 'Settings',
language: 'Language'
}
error: {
message: '{{function}} failed, please retry'
}
}
}

View File

@ -0,0 +1,34 @@
export default {
server: {
textInput: { placeholder: "Instance' domain" },
button: {
local: 'Login',
remote: 'Peep'
},
information: {
name: 'Name',
description: { heading: 'Description', expandHint: 'description' },
accounts: 'Users',
statuses: 'Toots',
domains: 'Universes'
},
disclaimer:
"Logging in process uses system broswer that, your account informationo won't be visible to tooot app. Read more at: "
},
update: {
local: {
alert: {
title: 'Logged in to this instance',
message:
'You can login to another account, keeping existing logged in account',
buttons: {
cancel: '$t(common:buttons.cancel)',
continue: 'Continue'
}
}
},
remote: {
succeed: 'Register peeping succeed'
}
}
}

View File

@ -0,0 +1,8 @@
export default {
HTML: {
expanded: {
true: 'Fold {{hint}}',
false: 'Expand {{hint}}'
}
}
}

View File

@ -0,0 +1,16 @@
export default {
follow: {
function: 'Follow user'
},
block: {
function: 'Block user'
},
button: {
error: 'Loading error',
blocked_by: 'Blocked by user',
blocking: 'Unblock',
following: 'Unfollow',
requested: 'Withdraw request',
default: 'Follow'
}
}

View File

@ -0,0 +1,155 @@
export default {
empty: {
error: {
message: 'Loading error',
button: 'Retry'
},
success: {
message: 'Timeline empty'
}
},
end: {
message: 'The end, what about a cup of <0 />'
},
header: {
explanation:
'External instance might not be known to logged in instance, thus actions are not allowed but only for reading. You can switch to any instance in the settings.',
button: 'Go to settings'
},
shared: {
actioned: {
pinned: 'Pinned',
favourite: '{{name}} favourited your toot',
status: '{{name}} just posted',
follow: '{{name}} followed you',
follow_request: '{{name}} requested following you',
poll: 'A poll you have voted in has ended',
reblog: {
default: '{{name}} boosted',
notification: '{{name}} boosted your toot'
}
},
actions: {
favourited: {
function: 'Favourite toot'
},
reblogged: {
function: 'Boost toot'
},
bookmarked: {
function: 'Bookmark toot'
}
},
attachment: {
sensitive: {
button: 'Show sensitive media'
},
unsupported: {
text: 'Loading error',
button: 'Try remote link'
}
},
content: {
expandHint: 'hidden content'
},
header: {
shared: {
application: 'Tooted with {{application}}'
},
conversation: {
delete: {
function: 'Delete direct message'
}
},
actions: {
account: {
heading: 'About user',
mute: {
function: 'Mute user',
button: 'Mute @{{acct}}'
},
block: {
function: 'Block user',
button: 'Block @{{acct}}'
},
reports: {
function: 'Report user',
button: 'Report @{{acct}}'
}
},
domain: {
heading: 'About instance',
block: {
function: 'Block instance',
button: 'Block instance {{domain}}'
},
alert: {
title: 'Confirm blocking {{domain}} ?',
message:
'Mostly you can mute or block certain user.\n\nAfter blocking instance, all its content including followers from this instance will be removed!',
buttons: {
confirm: 'Confirm blocking',
cancel: '$t(common:buttons.cancel)'
}
}
},
share: {
status: { heading: 'Share toot', button: 'Share link to this toot' },
account: { heading: 'Share user', button: 'Share link to this user' }
},
status: {
heading: 'About toot',
delete: {
function: 'Delete toot',
button: 'Delete this toot'
},
edit: {
function: 'Delete toot',
button: 'Delete and re-draft',
alert: {
title: 'Confirm deleting toot?',
message:
'Are you sure to delete and re-draft this toot? All boosts and favourites will be cleared, including all replies.',
buttons: {
confirm: 'Confirm deleting',
cancel: '$t(common:buttons.cancel)'
}
}
},
mute: {
function: 'Mute toot',
button: {
positive: 'Mute this toot and replies',
negative: 'Unmute this toot and replies'
}
},
pin: {
function: 'Pin',
button: {
positive: 'Pin this toot',
negative: 'Unpin this toot'
}
}
}
}
},
poll: {
meta: {
button: {
vote: 'Vote',
refresh: 'Refresh'
},
count: {
voters: '{{count}} user voted • ',
voters_plural: '{{count}} users voted • ',
votes: '{{count}} vote • ',
votes_plural: '{{count}} votes • '
},
expiration: {
expired: 'Vote expired',
until: 'Open until <0 />'
}
}
}
}
}

View File

@ -0,0 +1,8 @@
export default {
heading: {
segments: {
left: 'Following',
right: 'Local'
}
}
}

View File

@ -0,0 +1,4 @@
export default {
heading: 'Bookmarks',
content: {}
}

View File

@ -0,0 +1,4 @@
export default {
heading: 'Direct messages',
content: {}
}

View File

@ -0,0 +1,4 @@
export default {
heading: 'Favourites',
content: {}
}

View File

@ -0,0 +1,4 @@
export default {
heading: 'Lists',
content: {}
}

View File

@ -0,0 +1,4 @@
export default {
heading: 'List: {{list}}',
content: {}
}

View File

@ -0,0 +1,29 @@
export default {
content: {
collections: {
conversations: '$t(meConversations:heading)',
bookmarks: '$t(meBookmarks:heading)',
favourites: '$t(meFavourites:heading)',
lists: '$t(meLists:heading)',
announcements: {
heading: '$t(sharedAnnouncements:heading)',
content: {
unread: '{{amount}} unread',
read: 'all read'
}
}
},
settings: '$t(meSettings:heading)',
logout: {
button: 'Log out',
alert: {
title: 'Logging out?',
message: 'After logging out, you need to log in again',
buttons: {
logout: 'Logout',
cancel: '$t(common:buttons.cancel)'
}
}
}
}
}

View File

@ -0,0 +1,49 @@
export default {
heading: 'Settings',
content: {
language: {
heading: 'Language',
options: {
en: 'English',
'zh-Hans': '简体中文',
cancel: '$t(common:buttons.cancel)'
}
},
theme: {
heading: 'Appearance',
options: {
auto: 'As system',
light: 'Light mode',
dark: 'Dark mode',
cancel: '$t(common:buttons.cancel)'
}
},
browser: {
heading: 'Opening link',
options: {
internal: 'Inside app',
external: 'Use system browser',
cancel: '$t(common:buttons.cancel)'
}
},
remote: {
heading: '$t(meSettingsUpdateRemote:heading)',
description: 'External instance can only be read'
},
cache: {
heading: 'Clear cache',
empty: 'Cache empty'
},
support: {
heading: 'Support tooot'
},
review: {
heading: 'Review tooot'
},
analytics: {
heading: 'Help us improve',
description: 'Collecting only non-user relative usage'
},
version: 'Version v{{version}}'
}
}

View File

@ -0,0 +1,3 @@
export default {
heading: 'Register external instance'
}

View File

@ -0,0 +1,7 @@
export default {
heading: 'Switch account',
content: {
existing: 'Choose from logged in',
new: 'Log in to instance'
}
}

View File

@ -0,0 +1,3 @@
export default {
heading: 'Notifications'
}

View File

@ -0,0 +1,8 @@
export default {
heading: {
segments: {
left: 'Federated',
right: 'External'
}
}
}

View File

@ -0,0 +1,10 @@
export default {
content: {
created_at: 'Registered: {{date}}',
summary: {
statuses_count: '{{count}} toots',
following_count: 'Following {{count}}',
followers_count: '{{count}} followers'
}
}
}

View File

@ -0,0 +1,10 @@
export default {
heading: 'Announcements',
content: {
published: 'Published <0 />',
button: {
read: 'Read',
unread: 'Mark read'
}
}
}

View File

@ -0,0 +1,144 @@
export default {
heading: {
left: {
button: 'Cancel',
alert: {
title: 'Cancel editing?',
buttons: {
exit: 'Confirm',
continue: 'Continue'
}
}
},
right: {
button: {
default: 'Toot',
conversation: 'Toot DM',
reply: 'Toot reply',
edit: 'Toot'
},
alert: {
title: 'Tooting failed',
button: 'Try again'
}
}
},
content: {
root: {
header: {
postingAs: 'Tooting as @{{acct}}@{{domain}}',
spoilerInput: {
placeholder: 'Spoiler warning message'
},
textInput: {
placeholder: "What's on your mind"
}
},
footer: {
attachments: {
sensitive: 'Mark attachments as sensitive'
},
poll: {
option: {
placeholder: {
single: 'Single choice',
multiple: 'Multiple choice'
}
},
multiple: {
heading: 'Choice type',
options: {
single: 'Single choice',
multiple: 'Multiple choice',
cancel: '$t(common:buttons.cancel)'
}
},
expiration: {
heading: 'Validity',
options: {
'300': '5 minutes',
'1800': '30 minutes',
'3600': '1 hour',
'21600': '6 hours',
'86400': '1 day',
'259200': '3 days',
'604800': '7 days',
cancel: '$t(common:buttons.cancel)'
}
}
}
},
actions: {
attachment: {
actions: {
options: {
library: 'Upload from photo library',
photo: 'Upload with camera',
cancel: '$t(common:buttons.cancel)'
},
library: {
alert: {
title: 'No permission',
message: 'Require photo library read permission to upload',
buttons: {
settings: 'Update setting',
cancel: 'Cancel'
}
}
},
photo: {
alert: {
title: 'No permission',
message: 'Require camera usage permission to upload',
buttons: {
settings: 'Update setting',
cancel: 'Cancel'
}
}
}
},
failed: {
alert: {
title: 'Upload failed',
button: 'Try again'
}
}
},
visibility: {
title: 'Toot visibility',
options: {
public: 'Public',
unlisted: 'Unlisted',
private: 'Followers only',
direct: 'Direct message',
cancel: '$t(common:buttons.cancel)'
}
}
}
},
editAttachment: {
header: {
left: 'Cancel',
right: {
button: 'Apply',
succeed: {
title: 'Apply update succeed',
button: 'Ok'
},
failed: {
title: 'Apply update failed',
button: 'Try again'
}
}
},
content: {
altText: {
heading: 'Describe media for the visually impaired',
placeholder:
'You can add a description, sometimes called alt-text, to your media so they are accessible to even more people, including those who are blind or visually impaired.\n\nGood descriptions are concise, but present what is in your media accurately enough to understand their context.'
},
imageFocus: 'Drag the focus circle to update focus point'
}
}
}
}

View File

@ -0,0 +1,8 @@
export default {
heading: {
segments: {
left: 'Following',
right: 'Followers'
}
}
}

View File

@ -0,0 +1,31 @@
export default {
content: {
header: {
prefix: 'Search',
placeholder: 'for...'
},
empty: {
general:
'Enter keyword to search for <bold>$t(sharedSearch:content.sections.accounts)</bold>、<bold>$t(sharedSearch:content.sections.hashtags)</bold> or <bold>$t(sharedSearch:content.sections.statuses)</bold>',
advanced: {
header: 'Advanced search',
example: {
account:
'$t(sharedSearch:content.header.prefix)$t(sharedSearch:content.sections.accounts)',
hashtag:
'$t(sharedSearch:content.header.prefix)$t(sharedSearch:content.sections.hashtags)',
statusLink:
'$t(sharedSearch:content.header.prefix)$t(sharedSearch:content.sections.statuses)',
accountLink:
'$t(sharedSearch:content.header.prefix)$t(sharedSearch:content.sections.accounts)'
}
}
},
sections: {
accounts: 'User',
hashtags: 'Hashtag',
statuses: 'Toot'
},
notFound: 'Cannot find <bold>{{searchTerm}}</bold> related {{type}}'
}
}

View File

@ -0,0 +1,3 @@
export default {
heading: 'Direct messages'
}

View File

@ -17,11 +17,10 @@ i18next.use(initReactI18next).init({
resources: { 'zh-Hans': zh_Hans, en },
saveMissing: true,
missingKeyHandler: (lng, ns, key, fallbackValue) => {
console.log('i18n missing: ' + lng + ' - ' + ns + ' : ' + key)
missingKeyHandler: (ns, key) => {
console.log('i18n missing: ' + ns + ' : ' + key)
},
// react options
interpolation: {
escapeValue: false
}

View File

@ -13,13 +13,13 @@ export default {
domains: '连结总数'
},
disclaimer:
'登录过程将使用系统浏览器,您的账户登录信息tooot应用无法读取。详见'
'登录过程将使用系统浏览器,你的账号登录信息tooot应用无法读取。详见'
},
update: {
local: {
alert: {
title: '此社区已登录',
message: '您可以登录同个社区的另一个账户,不影响现有账户',
message: '你可以登录同个社区的另一个账号,不影响已登录的账号',
buttons: {
cancel: '$t(common:buttons.cancel)',
continue: '继续'

View File

@ -2,8 +2,8 @@ export default {
strings: {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: '前',
suffixFromNow: '后',
suffixAgo: '前',
suffixFromNow: '后',
seconds: '%d秒',
minute: '1分钟',
minutes: '%d分钟',
@ -15,7 +15,6 @@ export default {
months: '%d月',
year: '大约1年',
years: '%d年',
wordSeparator: ''
}
}

View File

@ -19,14 +19,14 @@ export default {
shared: {
actioned: {
pinned: '置顶',
favourite: '{{name}} 喜欢了你的嘟',
favourite: '{{name}} 喜欢了你的嘟',
status: '{{name}} 刚刚发嘟',
follow: '{{name}} 开始关注你',
follow_request: '{{name}} 请求关注',
poll: '参与的投票已结束',
follow_request: '{{name}} 请求关注',
poll: '参与的投票已结束',
reblog: {
default: '{{name}} 转嘟了',
notification: '{{name}} 转嘟了的嘟文'
notification: '{{name}} 转嘟了的嘟文'
}
},
actions: {

View File

@ -1,4 +1,4 @@
export default {
heading: '列表 {{list}}',
heading: '列表{{list}}',
content: {}
}

View File

@ -1,5 +1,4 @@
export default {
heading: '我的长毛象',
content: {
collections: {
conversations: '$t(meConversations:heading)',

View File

@ -1,3 +1,3 @@
export default {
heading: '外站社区'
heading: '围观社区'
}

View File

@ -1,7 +1,7 @@
export default {
heading: '切换账号',
content: {
existing: '选择已账号',
existing: '选择已登录的账号',
new: '登录新社区'
}
}

View File

@ -1,7 +1,7 @@
export default {
heading: {
segments: {
left: '跨站关注',
left: '跨站嘟嘟',
right: '外站嘟嘟'
}
}

View File

@ -1,6 +1,6 @@
export default {
content: {
created_at: '加入时间:{{date}}',
created_at: '注册时间:{{date}}',
summary: {
statuses_count: '{{count}} 条嘟文',
following_count: '关注 {{count}} 人',

View File

@ -26,17 +26,17 @@ export default {
content: {
root: {
header: {
postingAs: '用 @{{acct}}@{{domain}} 发布',
postingAs: '以 @{{acct}}@{{domain}} 发嘟',
spoilerInput: {
placeholder: '折叠部分的警告信息'
},
textInput: {
placeholder: '想说点什么'
placeholder: '想说点什么'
}
},
footer: {
attachments: {
sensitive: '标记媒体为敏感内容'
sensitive: '标记附件为敏感内容'
},
poll: {
option: {
@ -79,9 +79,9 @@ export default {
library: {
alert: {
title: '无读取权限',
message: '需要相片权限才能上传附件',
message: '需要读取相册权限才能上传附件',
buttons: {
settings: '去系统设置',
settings: '去更新设置',
cancel: '取消上传'
}
}
@ -89,9 +89,9 @@ export default {
photo: {
alert: {
title: '无拍照权限',
message: '需要相机权限才能上传附件',
message: '需要使用相机权限才能上传附件',
buttons: {
settings: '去系统设置',
settings: '去更新设置',
cancel: '取消上传'
}
}

View File

@ -1,9 +1,8 @@
export default {
heading: '对话',
content: {
header: {
prefix: '搜索',
placeholder: '什么'
placeholder: '什么'
},
empty: {
general:

View File

@ -0,0 +1,4 @@
{
"NSCameraUsageDescription": "允许tooot使用相机拍摄上传附件",
"NSPhotoLibraryUsageDescription": "允许tooot读取相册上传附件"
}

View File

@ -73,6 +73,18 @@ const DevDebug: React.FC = () => {
destructive
onPress={() => persistor.purge()}
/>
<Button
type='text'
content={'Crash test'}
style={{
marginHorizontal: StyleConstants.Spacing.Global.PagePadding * 2,
marginBottom: StyleConstants.Spacing.Global.PagePadding * 2
}}
destructive
onPress={() => {
throw new Error('Testing crash')
}}
/>
</MenuContainer>
)
}

View File

@ -54,7 +54,11 @@ const AccountInformation: React.FC<Props> = ({
<AccountInformationName ref={shimmerNameRef} account={account} />
<AccountInformationAccount ref={shimmerAccountRef} account={account} />
<AccountInformationAccount
ref={shimmerAccountRef}
account={account}
ownAccount={ownAccount}
/>
{!ownAccount ? (
<>

View File

@ -1,4 +1,5 @@
import Icon from '@components/Icon'
import { getLocalUri } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { LinearGradient } from 'expo-linear-gradient'
@ -7,14 +8,17 @@ import { StyleSheet, Text, View } from 'react-native'
import ShimmerPlaceholder, {
createShimmerPlaceholder
} from 'react-native-shimmer-placeholder'
import { useSelector } from 'react-redux'
export interface Props {
account: Mastodon.Account | undefined
ownAccount?: boolean
}
const AccountInformationAccount = forwardRef<ShimmerPlaceholder, Props>(
({ account }, ref) => {
({ account, ownAccount }, ref) => {
const { theme } = useTheme()
const localUri = useSelector(getLocalUri)
const ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient)
@ -40,6 +44,7 @@ const AccountInformationAccount = forwardRef<ShimmerPlaceholder, Props>(
selectable
>
@{account?.acct}
{ownAccount ? `@${localUri}` : null}
</Text>
{account?.locked ? (
<Icon

View File

@ -1,41 +0,0 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import { persistor } from '@root/store'
import log from './log'
// Used to upgrade/invalidate secure storage
const dataKey = '@mastodon_app_database_version'
const currentVersion = '20210105'
const checkSecureStorageVersion = async (): Promise<any> => {
log(
'log',
'checkSecureStorageVersion',
'Start checking secure storage version'
)
try {
const value = await AsyncStorage.getItem(dataKey)
if (value !== currentVersion) {
log(
'warn',
'checkSecureStorageVersion',
`Version does not match. Prev: ${value}. Current: ${currentVersion}.`
)
persistor.purge()
try {
await AsyncStorage.setItem(dataKey, currentVersion)
} catch (e) {
log('error', 'checkSecureStorageVersion', 'Storing storage data error')
return Promise.reject()
}
} else {
log('log', 'checkSecureStorageVersion', 'Storing storage version matched')
}
return Promise.resolve()
} catch (e) {
log('error', 'checkSecureStorageVersion', 'Getting storage data error')
return Promise.reject()
}
}
export default checkSecureStorageVersion

View File

@ -1,12 +1,12 @@
import Constants from 'expo-constants'
import * as Sentry from 'sentry-expo'
import log from "./log"
import log from './log'
const sentry = () => {
log('log', 'Sentry', 'initializing')
Sentry.init({
dsn:
'https://c9e29aa05f774aca8f36def98244ce04@o389581.ingest.sentry.io/5571975',
enableInExpoDevelopment: false,
dsn: Constants.manifest.extra.sentryDSN,
enableInExpoDevelopment: true,
debug: __DEV__
})
}

View File

@ -254,9 +254,13 @@ export const getLocalActiveIndex = ({ instances: { local } }: RootState) =>
export const getLocalInstances = ({ instances: { local } }: RootState) =>
local.instances
export const getLocalUrl = ({ instances: { local } }: RootState) =>
local.activeIndex ? local.instances[local.activeIndex].url : undefined
// export const getLocalToken = ({ instances: { local } }: RootState) =>
// local && local.activeIndex && local.instances[local.activeIndex].token
local.activeIndex !== null
? local.instances[local.activeIndex].url
: undefined
export const getLocalUri = ({ instances: { local } }: RootState) =>
local.activeIndex !== null
? local.instances[local.activeIndex].url
: undefined
export const getLocalAccount = ({ instances: { local } }: RootState) =>
local.activeIndex !== null
? local.instances[local.activeIndex].account

View File

@ -11,12 +11,11 @@
"strict": true,
"baseUrl": "./",
"paths": {
// "@assets/*": ["./assets/*"],
"@api/*": ["./src/api/*"],
"@components/*": ["./src/components/*"],
"@screens/*": ["./src/screens/*"],
"@utils/*": ["./src/utils/*"],
"@root/*": ["./src/*"],
"@root/*": ["./src/*"]
}
},
"exclude": ["node_modules"]

View File

@ -3749,6 +3749,11 @@ domutils@^1.5.1, domutils@^1.7.0:
dom-serializer "0"
domelementtype "1"
dotenv@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
dup@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dup/-/dup-1.0.0.tgz#51fc5ac685f8196469df0b905e934b20af5b4029"