Internationalization & localization (#1822)
* install and setup lingui * setup dynamic locale activation and async loading * first pass of automated replacement of text messages * add some more documentaton * fix nits * add `es` and `hi`locales for testing purposes * make accessibilityLabel localized * compile and extract new messages * fix merge conflicts * fix eslint warning * change instructions from sending email to opening PR * fix comments
This commit is contained in:
parent
82059b7ee1
commit
4c7850f8c4
108 changed files with 10334 additions and 1365 deletions
|
|
@ -13,6 +13,8 @@ import {
|
|||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import * as Toast from '../util/Toast'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['70%']
|
||||
|
|
@ -55,6 +57,7 @@ const shadesOfBlue: string[] = [
|
|||
export function Component({}: {}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const [name, setName] = useState(
|
||||
shadesOfBlue[Math.floor(Math.random() * shadesOfBlue.length)],
|
||||
|
|
@ -121,15 +124,19 @@ export function Component({}: {}) {
|
|||
<View>
|
||||
{!appPassword ? (
|
||||
<Text type="lg" style={[pal.text]}>
|
||||
Please enter a unique name for this App Password or use our randomly
|
||||
generated one.
|
||||
<Trans>
|
||||
Please enter a unique name for this App Password or use our
|
||||
randomly generated one.
|
||||
</Trans>
|
||||
</Text>
|
||||
) : (
|
||||
<Text type="lg" style={[pal.text]}>
|
||||
<Text type="lg-bold" style={[pal.text]}>
|
||||
Here is your app password.
|
||||
</Text>{' '}
|
||||
Use this to sign into the other app along with your handle.
|
||||
<Text type="lg-bold" style={[pal.text, s.mr5]}>
|
||||
<Trans>Here is your app password.</Trans>
|
||||
</Text>
|
||||
<Trans>
|
||||
Use this to sign into the other app along with your handle.
|
||||
</Trans>
|
||||
</Text>
|
||||
)}
|
||||
{!appPassword ? (
|
||||
|
|
@ -154,7 +161,7 @@ export function Component({}: {}) {
|
|||
returnKeyType="done"
|
||||
onEndEditing={createAppPassword}
|
||||
accessible={true}
|
||||
accessibilityLabel="Name"
|
||||
accessibilityLabel={_(msg`Name`)}
|
||||
accessibilityHint="Input name for app password"
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -163,13 +170,15 @@ export function Component({}: {}) {
|
|||
style={[pal.border, styles.passwordContainer, pal.btn]}
|
||||
onPress={onCopy}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Copy"
|
||||
accessibilityLabel={_(msg`Copy`)}
|
||||
accessibilityHint="Copies app password">
|
||||
<Text type="2xl-bold" style={[pal.text]}>
|
||||
{appPassword}
|
||||
</Text>
|
||||
{wasCopied ? (
|
||||
<Text style={[pal.textLight]}>Copied</Text>
|
||||
<Text style={[pal.textLight]}>
|
||||
<Trans>Copied</Trans>
|
||||
</Text>
|
||||
) : (
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'clone']}
|
||||
|
|
@ -182,14 +191,18 @@ export function Component({}: {}) {
|
|||
</View>
|
||||
{appPassword ? (
|
||||
<Text type="lg" style={[pal.textLight, s.mb10]}>
|
||||
For security reasons, you won't be able to view this again. If you
|
||||
lose this password, you'll need to generate a new one.
|
||||
<Trans>
|
||||
For security reasons, you won't be able to view this again. If you
|
||||
lose this password, you'll need to generate a new one.
|
||||
</Trans>
|
||||
</Text>
|
||||
) : (
|
||||
<Text type="xs" style={[pal.textLight, s.mb10, s.mt2]}>
|
||||
Can only contain letters, numbers, spaces, dashes, and underscores.
|
||||
Must be at least 4 characters long, but no more than 32 characters
|
||||
long.
|
||||
<Trans>
|
||||
Can only contain letters, numbers, spaces, dashes, and underscores.
|
||||
Must be at least 4 characters long, but no more than 32 characters
|
||||
long.
|
||||
</Trans>
|
||||
</Text>
|
||||
)}
|
||||
<View style={styles.btnContainer}>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import {Text} from '../util/text/Text'
|
|||
import LinearGradient from 'react-native-linear-gradient'
|
||||
import {isAndroid, isWeb} from 'platform/detection'
|
||||
import {ImageModel} from 'state/models/media/image'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['fullscreen']
|
||||
|
|
@ -30,6 +32,7 @@ interface Props {
|
|||
export function Component({image}: Props) {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
const [altText, setAltText] = useState(image.altText)
|
||||
const windim = useWindowDimensions()
|
||||
const {closeModal} = useModalControls()
|
||||
|
|
@ -90,7 +93,7 @@ export function Component({image}: Props) {
|
|||
placeholderTextColor={pal.colors.textLight}
|
||||
value={altText}
|
||||
onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))}
|
||||
accessibilityLabel="Image alt text"
|
||||
accessibilityLabel={_(msg`Image alt text`)}
|
||||
accessibilityHint=""
|
||||
accessibilityLabelledBy="imageAltText"
|
||||
autoFocus
|
||||
|
|
@ -99,7 +102,7 @@ export function Component({image}: Props) {
|
|||
<TouchableOpacity
|
||||
testID="altTextImageSaveBtn"
|
||||
onPress={onPressSave}
|
||||
accessibilityLabel="Save alt text"
|
||||
accessibilityLabel={_(msg`Save alt text`)}
|
||||
accessibilityHint={`Saves alt text, which reads: ${altText}`}
|
||||
accessibilityRole="button">
|
||||
<LinearGradient
|
||||
|
|
@ -108,7 +111,7 @@ export function Component({image}: Props) {
|
|||
end={{x: 1, y: 1}}
|
||||
style={[styles.button]}>
|
||||
<Text type="button-lg" style={[s.white, s.bold]}>
|
||||
Save
|
||||
<Trans>Save</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -116,12 +119,12 @@ export function Component({image}: Props) {
|
|||
testID="altTextImageCancelBtn"
|
||||
onPress={onPressCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel add image alt text"
|
||||
accessibilityLabel={_(msg`Cancel add image alt text`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onPressCancel}>
|
||||
<View style={[styles.button]}>
|
||||
<Text type="button-lg" style={[pal.textLight]}>
|
||||
Cancel
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {isWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['50%']
|
||||
|
|
@ -22,6 +24,7 @@ export const snapPoints = ['50%']
|
|||
export const Component = observer(function Component({}: {}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const [date, setDate] = useState<Date>(
|
||||
store.preferences.birthDate || new Date(),
|
||||
|
|
@ -49,12 +52,12 @@ export const Component = observer(function Component({}: {}) {
|
|||
style={[pal.view, styles.container, isMobile && {paddingHorizontal: 18}]}>
|
||||
<View style={styles.titleSection}>
|
||||
<Text type="title-lg" style={[pal.text, styles.title]}>
|
||||
My Birthday
|
||||
<Trans>My Birthday</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
|
||||
This information is not shared with other users.
|
||||
<Trans>This information is not shared with other users.</Trans>
|
||||
</Text>
|
||||
|
||||
<View>
|
||||
|
|
@ -65,7 +68,7 @@ export const Component = observer(function Component({}: {}) {
|
|||
buttonType="default-light"
|
||||
buttonStyle={[pal.border, styles.dateInputButton]}
|
||||
buttonLabelType="lg"
|
||||
accessibilityLabel="Birthday"
|
||||
accessibilityLabel={_(msg`Birthday`)}
|
||||
accessibilityHint="Enter your birth date"
|
||||
accessibilityLabelledBy="birthDate"
|
||||
/>
|
||||
|
|
@ -86,9 +89,11 @@ export const Component = observer(function Component({}: {}) {
|
|||
onPress={onSave}
|
||||
style={styles.btn}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Save"
|
||||
accessibilityLabel={_(msg`Save`)}
|
||||
accessibilityHint="">
|
||||
<Text style={[s.white, s.bold, s.f18]}>Save</Text>
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
<Trans>Save</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {isWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
enum Stages {
|
||||
|
|
@ -25,6 +27,7 @@ export const snapPoints = ['90%']
|
|||
export const Component = observer(function Component({}: {}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const [stage, setStage] = useState<Stages>(Stages.InputEmail)
|
||||
const [email, setEmail] = useState<string>(
|
||||
store.session.currentSession?.email || '',
|
||||
|
|
@ -62,7 +65,9 @@ export const Component = observer(function Component({}: {}) {
|
|||
// you can remove this any time after Oct2023
|
||||
// -prf
|
||||
if (err === 'email must be confirmed (temporary)') {
|
||||
err = `Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.`
|
||||
err = _(
|
||||
msg`Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.`,
|
||||
)
|
||||
}
|
||||
setError(err)
|
||||
} finally {
|
||||
|
|
@ -103,26 +108,26 @@ export const Component = observer(function Component({}: {}) {
|
|||
style={[s.flex1, isMobile && {paddingHorizontal: 18}]}>
|
||||
<View style={styles.titleSection}>
|
||||
<Text type="title-lg" style={[pal.text, styles.title]}>
|
||||
{stage === Stages.InputEmail ? 'Change Your Email' : ''}
|
||||
{stage === Stages.ConfirmCode ? 'Security Step Required' : ''}
|
||||
{stage === Stages.Done ? 'Email Updated' : ''}
|
||||
{stage === Stages.InputEmail ? _(msg`Change Your Email`) : ''}
|
||||
{stage === Stages.ConfirmCode ? _(msg`Security Step Required`) : ''}
|
||||
{stage === Stages.Done ? _(msg`Email Updated`) : ''}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
|
||||
{stage === Stages.InputEmail ? (
|
||||
<>Enter your new email address below.</>
|
||||
<Trans>Enter your new email address below.</Trans>
|
||||
) : stage === Stages.ConfirmCode ? (
|
||||
<>
|
||||
<Trans>
|
||||
An email has been sent to your previous address,{' '}
|
||||
{store.session.currentSession?.email || ''}. It includes a
|
||||
confirmation code which you can enter below.
|
||||
</>
|
||||
</Trans>
|
||||
) : (
|
||||
<>
|
||||
<Trans>
|
||||
Your email has been updated but not verified. As a next step,
|
||||
please verify your new email.
|
||||
</>
|
||||
</Trans>
|
||||
)}
|
||||
</Text>
|
||||
|
||||
|
|
@ -135,7 +140,7 @@ export const Component = observer(function Component({}: {}) {
|
|||
value={email}
|
||||
onChangeText={setEmail}
|
||||
accessible={true}
|
||||
accessibilityLabel="Email"
|
||||
accessibilityLabel={_(msg`Email`)}
|
||||
accessibilityHint=""
|
||||
autoCapitalize="none"
|
||||
autoComplete="email"
|
||||
|
|
@ -151,7 +156,7 @@ export const Component = observer(function Component({}: {}) {
|
|||
value={confirmationCode}
|
||||
onChangeText={setConfirmationCode}
|
||||
accessible={true}
|
||||
accessibilityLabel="Confirmation code"
|
||||
accessibilityLabel={_(msg`Confirmation code`)}
|
||||
accessibilityHint=""
|
||||
autoCapitalize="none"
|
||||
autoComplete="off"
|
||||
|
|
@ -175,9 +180,9 @@ export const Component = observer(function Component({}: {}) {
|
|||
testID="requestChangeBtn"
|
||||
type="primary"
|
||||
onPress={onRequestChange}
|
||||
accessibilityLabel="Request Change"
|
||||
accessibilityLabel={_(msg`Request Change`)}
|
||||
accessibilityHint=""
|
||||
label="Request Change"
|
||||
label={_(msg`Request Change`)}
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
labelStyle={[s.f18]}
|
||||
/>
|
||||
|
|
@ -187,9 +192,9 @@ export const Component = observer(function Component({}: {}) {
|
|||
testID="confirmBtn"
|
||||
type="primary"
|
||||
onPress={onConfirm}
|
||||
accessibilityLabel="Confirm Change"
|
||||
accessibilityLabel={_(msg`Confirm Change`)}
|
||||
accessibilityHint=""
|
||||
label="Confirm Change"
|
||||
label={_(msg`Confirm Change`)}
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
labelStyle={[s.f18]}
|
||||
/>
|
||||
|
|
@ -199,9 +204,9 @@ export const Component = observer(function Component({}: {}) {
|
|||
testID="verifyBtn"
|
||||
type="primary"
|
||||
onPress={onVerify}
|
||||
accessibilityLabel="Verify New Email"
|
||||
accessibilityLabel={_(msg`Verify New Email`)}
|
||||
accessibilityHint=""
|
||||
label="Verify New Email"
|
||||
label={_(msg`Verify New Email`)}
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
labelStyle={[s.f18]}
|
||||
/>
|
||||
|
|
@ -210,9 +215,9 @@ export const Component = observer(function Component({}: {}) {
|
|||
testID="cancelBtn"
|
||||
type="default"
|
||||
onPress={() => closeModal()}
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityLabel={_(msg`Cancel`)}
|
||||
accessibilityHint=""
|
||||
label="Cancel"
|
||||
label={_(msg`Cancel`)}
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
labelStyle={[s.f18]}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import {useTheme} from 'lib/ThemeContext'
|
|||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['100%']
|
||||
|
|
@ -31,6 +33,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
|
|||
const [error, setError] = useState<string>('')
|
||||
const pal = usePalette('default')
|
||||
const {track} = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
|
||||
const [isProcessing, setProcessing] = useState<boolean>(false)
|
||||
|
|
@ -141,7 +144,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
|
|||
<TouchableOpacity
|
||||
onPress={onPressCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel change handle"
|
||||
accessibilityLabel={_(msg`Cancel change handle`)}
|
||||
accessibilityHint="Exits handle change process"
|
||||
onAccessibilityEscape={onPressCancel}>
|
||||
<Text type="lg" style={pal.textLight}>
|
||||
|
|
@ -153,7 +156,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
|
|||
type="2xl-bold"
|
||||
style={[styles.titleMiddle, pal.text]}
|
||||
numberOfLines={1}>
|
||||
Change Handle
|
||||
<Trans>Change Handle</Trans>
|
||||
</Text>
|
||||
<View style={styles.titleRight}>
|
||||
{isProcessing ? (
|
||||
|
|
@ -163,7 +166,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
|
|||
testID="retryConnectButton"
|
||||
onPress={onPressRetryConnect}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Retry change handle"
|
||||
accessibilityLabel={_(msg`Retry change handle`)}
|
||||
accessibilityHint={`Retries handle change to ${handle}`}>
|
||||
<Text type="xl-bold" style={[pal.link, s.pr5]}>
|
||||
Retry
|
||||
|
|
@ -173,10 +176,10 @@ export function Component({onChanged}: {onChanged: () => void}) {
|
|||
<TouchableOpacity
|
||||
onPress={onPressSave}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Save handle change"
|
||||
accessibilityLabel={_(msg`Save handle change`)}
|
||||
accessibilityHint={`Saves handle change to ${handle}`}>
|
||||
<Text type="2xl-medium" style={pal.link}>
|
||||
Save
|
||||
<Trans>Save</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
) : undefined}
|
||||
|
|
@ -234,6 +237,7 @@ function ProvidedHandleForm({
|
|||
}) {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
|
||||
// events
|
||||
// =
|
||||
|
|
@ -266,12 +270,12 @@ function ProvidedHandleForm({
|
|||
onChangeText={onChangeHandle}
|
||||
editable={!isProcessing}
|
||||
accessible={true}
|
||||
accessibilityLabel="Handle"
|
||||
accessibilityLabel={_(msg`Handle`)}
|
||||
accessibilityHint="Sets Bluesky username"
|
||||
/>
|
||||
</View>
|
||||
<Text type="md" style={[pal.textLight, s.pl10, s.pt10]}>
|
||||
Your full handle will be{' '}
|
||||
<Trans>Your full handle will be </Trans>
|
||||
<Text type="md-bold" style={pal.textLight}>
|
||||
@{createFullHandle(handle, userDomain)}
|
||||
</Text>
|
||||
|
|
@ -280,9 +284,9 @@ function ProvidedHandleForm({
|
|||
onPress={onToggleCustom}
|
||||
accessibilityRole="button"
|
||||
accessibilityHint="Hosting provider"
|
||||
accessibilityLabel="Opens modal for using custom domain">
|
||||
accessibilityLabel={_(msg`Opens modal for using custom domain`)}>
|
||||
<Text type="md-medium" style={[pal.link, s.pl10, s.pt5]}>
|
||||
I have my own domain
|
||||
<Trans>I have my own domain</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
|
|
@ -314,6 +318,7 @@ function CustomHandleForm({
|
|||
const palSecondary = usePalette('secondary')
|
||||
const palError = usePalette('error')
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
const [isVerifying, setIsVerifying] = React.useState(false)
|
||||
const [error, setError] = React.useState<string>('')
|
||||
const [isDNSForm, setDNSForm] = React.useState<boolean>(true)
|
||||
|
|
@ -367,7 +372,7 @@ function CustomHandleForm({
|
|||
return (
|
||||
<>
|
||||
<Text type="md" style={[pal.text, s.pb5, s.pl5]} nativeID="customDomain">
|
||||
Enter the domain you want to use
|
||||
<Trans>Enter the domain you want to use</Trans>
|
||||
</Text>
|
||||
<View style={[pal.btn, styles.textInputWrapper]}>
|
||||
<FontAwesomeIcon
|
||||
|
|
@ -385,7 +390,7 @@ function CustomHandleForm({
|
|||
onChangeText={onChangeHandle}
|
||||
editable={!isProcessing}
|
||||
accessibilityLabelledBy="customDomain"
|
||||
accessibilityLabel="Custom domain"
|
||||
accessibilityLabel={_(msg`Custom domain`)}
|
||||
accessibilityHint="Input your preferred hosting provider"
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -413,7 +418,7 @@ function CustomHandleForm({
|
|||
{isDNSForm ? (
|
||||
<>
|
||||
<Text type="md" style={[pal.text, s.pb5, s.pl5]}>
|
||||
Add the following DNS record to your domain:
|
||||
<Trans>Add the following DNS record to your domain:</Trans>
|
||||
</Text>
|
||||
<View style={[styles.dnsTable, pal.btn]}>
|
||||
<Text type="md-medium" style={[styles.dnsLabel, pal.text]}>
|
||||
|
|
@ -451,7 +456,7 @@ function CustomHandleForm({
|
|||
) : (
|
||||
<>
|
||||
<Text type="md" style={[pal.text, s.pb5, s.pl5]}>
|
||||
Upload a text file to:
|
||||
<Trans>Upload a text file to:</Trans>
|
||||
</Text>
|
||||
<View style={[styles.valueContainer, pal.btn]}>
|
||||
<View style={[styles.dnsValue]}>
|
||||
|
|
@ -483,7 +488,7 @@ function CustomHandleForm({
|
|||
{canSave === true && (
|
||||
<View style={[styles.message, palSecondary.view]}>
|
||||
<Text type="md-medium" style={palSecondary.text}>
|
||||
Domain verified!
|
||||
<Trans>Domain verified!</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
|
@ -511,7 +516,7 @@ function CustomHandleForm({
|
|||
<View style={styles.spacer} />
|
||||
<TouchableOpacity
|
||||
onPress={onToggleCustom}
|
||||
accessibilityLabel="Use default provider"
|
||||
accessibilityLabel={_(msg`Use default provider`)}
|
||||
accessibilityHint="Use bsky.social as hosting provider">
|
||||
<Text type="md-medium" style={[pal.link, s.pl10, s.pt5]}>
|
||||
Nevermind, create a handle for me
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
|
|||
import {cleanError} from 'lib/strings/errors'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {msg} from '@lingui/macro'
|
||||
import type {ConfirmModal} from '#/state/modals'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
|
|
@ -26,6 +28,7 @@ export function Component({
|
|||
cancelBtnText,
|
||||
}: ConfirmModal) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false)
|
||||
const [error, setError] = useState<string>('')
|
||||
|
|
@ -69,7 +72,7 @@ export function Component({
|
|||
onPress={onPress}
|
||||
style={[styles.btn, confirmBtnStyle]}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Confirm"
|
||||
accessibilityLabel={_(msg`Confirm`)}
|
||||
accessibilityHint="">
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
{confirmBtnText ?? 'Confirm'}
|
||||
|
|
@ -82,7 +85,7 @@ export function Component({
|
|||
onPress={onPressCancel}
|
||||
style={[styles.btnCancel, s.mt10]}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityLabel={_(msg`Cancel`)}
|
||||
accessibilityHint="">
|
||||
<Text type="button-lg" style={pal.textLight}>
|
||||
{cancelBtnText ?? 'Cancel'}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import {isIOS} from 'platform/detection'
|
|||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import * as Toast from '../util/Toast'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['90%']
|
||||
|
|
@ -25,6 +27,7 @@ export const Component = observer(
|
|||
const store = useStores()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -37,7 +40,9 @@ export const Component = observer(
|
|||
|
||||
return (
|
||||
<View testID="contentFilteringModal" style={[pal.view, styles.container]}>
|
||||
<Text style={[pal.text, styles.title]}>Content Filtering</Text>
|
||||
<Text style={[pal.text, styles.title]}>
|
||||
<Trans>Content Filtering</Trans>
|
||||
</Text>
|
||||
<ScrollView style={styles.scrollContainer}>
|
||||
<AdultContentEnabledPref />
|
||||
<ContentLabelPref
|
||||
|
|
@ -71,14 +76,16 @@ export const Component = observer(
|
|||
testID="sendReportBtn"
|
||||
onPress={onPressDone}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Done"
|
||||
accessibilityLabel={_(msg`Done`)}
|
||||
accessibilityHint="">
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text style={[s.white, s.bold, s.f18]}>Done</Text>
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
<Trans>Done</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ import {useTheme} from 'lib/ThemeContext'
|
|||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
const MAX_NAME = 64 // todo
|
||||
|
|
@ -47,6 +49,7 @@ export function Component({
|
|||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {track} = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
|
||||
const activePurpose = useMemo(() => {
|
||||
if (list?.data?.purpose) {
|
||||
|
|
@ -164,14 +167,18 @@ export function Component({
|
|||
]}
|
||||
testID="createOrEditListModal">
|
||||
<Text style={[styles.title, pal.text]}>
|
||||
{list ? 'Edit' : 'New'} {purposeLabel} List
|
||||
<Trans>
|
||||
{list ? 'Edit' : 'New'} {purposeLabel} List
|
||||
</Trans>
|
||||
</Text>
|
||||
{error !== '' && (
|
||||
<View style={styles.errorContainer}>
|
||||
<ErrorMessage message={error} />
|
||||
</View>
|
||||
)}
|
||||
<Text style={[styles.label, pal.text]}>List Avatar</Text>
|
||||
<Text style={[styles.label, pal.text]}>
|
||||
<Trans>List Avatar</Trans>
|
||||
</Text>
|
||||
<View style={[styles.avi, {borderColor: pal.colors.background}]}>
|
||||
<EditableUserAvatar
|
||||
type="list"
|
||||
|
|
@ -183,7 +190,7 @@ export function Component({
|
|||
<View style={styles.form}>
|
||||
<View>
|
||||
<Text style={[styles.label, pal.text]} nativeID="list-name">
|
||||
List Name
|
||||
<Trans>List Name</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
testID="editNameInput"
|
||||
|
|
@ -195,14 +202,14 @@ export function Component({
|
|||
value={name}
|
||||
onChangeText={v => setName(enforceLen(v, MAX_NAME))}
|
||||
accessible={true}
|
||||
accessibilityLabel="Name"
|
||||
accessibilityLabel={_(msg`Name`)}
|
||||
accessibilityHint=""
|
||||
accessibilityLabelledBy="list-name"
|
||||
/>
|
||||
</View>
|
||||
<View style={s.pb10}>
|
||||
<Text style={[styles.label, pal.text]} nativeID="list-description">
|
||||
Description
|
||||
<Trans>Description</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
testID="editDescriptionInput"
|
||||
|
|
@ -218,7 +225,7 @@ export function Component({
|
|||
value={description}
|
||||
onChangeText={v => setDescription(enforceLen(v, MAX_DESCRIPTION))}
|
||||
accessible={true}
|
||||
accessibilityLabel="Description"
|
||||
accessibilityLabel={_(msg`Description`)}
|
||||
accessibilityHint=""
|
||||
accessibilityLabelledBy="list-description"
|
||||
/>
|
||||
|
|
@ -233,14 +240,16 @@ export function Component({
|
|||
style={s.mt10}
|
||||
onPress={onPressSave}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Save"
|
||||
accessibilityLabel={_(msg`Save`)}
|
||||
accessibilityHint="">
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text style={[s.white, s.bold]}>Save</Text>
|
||||
<Text style={[s.white, s.bold]}>
|
||||
<Trans>Save</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
|
@ -249,11 +258,13 @@ export function Component({
|
|||
style={s.mt5}
|
||||
onPress={onPressCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityLabel={_(msg`Cancel`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onPressCancel}>
|
||||
<View style={[styles.btn]}>
|
||||
<Text style={[s.black, s.bold, pal.text]}>Cancel</Text>
|
||||
<Text style={[s.black, s.bold, pal.text]}>
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
|||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {resetToTab} from '../../../Navigation'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['60%']
|
||||
|
|
@ -25,6 +27,7 @@ export function Component({}: {}) {
|
|||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false)
|
||||
|
|
@ -71,7 +74,7 @@ export function Component({}: {}) {
|
|||
<View style={[styles.innerContainer, pal.view]}>
|
||||
<View style={[styles.titleContainer, pal.view]}>
|
||||
<Text type="title-xl" style={[s.textCenter, pal.text]}>
|
||||
Delete Account
|
||||
<Trans>Delete Account</Trans>
|
||||
</Text>
|
||||
<View style={[pal.view, s.flexRow]}>
|
||||
<Text type="title-xl" style={[pal.text, s.bold]}>
|
||||
|
|
@ -95,8 +98,10 @@ export function Component({}: {}) {
|
|||
{!isEmailSent ? (
|
||||
<>
|
||||
<Text type="lg" style={[styles.description, pal.text]}>
|
||||
For security reasons, we'll need to send a confirmation code to
|
||||
your email address.
|
||||
<Trans>
|
||||
For security reasons, we'll need to send a confirmation code to
|
||||
your email address.
|
||||
</Trans>
|
||||
</Text>
|
||||
{error ? (
|
||||
<View style={s.mt10}>
|
||||
|
|
@ -113,7 +118,7 @@ export function Component({}: {}) {
|
|||
style={styles.mt20}
|
||||
onPress={onPressSendEmail}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Send email"
|
||||
accessibilityLabel={_(msg`Send email`)}
|
||||
accessibilityHint="Sends email with confirmation code for account deletion">
|
||||
<LinearGradient
|
||||
colors={[
|
||||
|
|
@ -124,7 +129,7 @@ export function Component({}: {}) {
|
|||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text type="button-lg" style={[s.white, s.bold]}>
|
||||
Send Email
|
||||
<Trans>Send Email</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -132,11 +137,11 @@ export function Component({}: {}) {
|
|||
style={[styles.btn, s.mt10]}
|
||||
onPress={onCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel account deletion"
|
||||
accessibilityLabel={_(msg`Cancel account deletion`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onCancel}>
|
||||
<Text type="button-lg" style={pal.textLight}>
|
||||
Cancel
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
|
|
@ -149,8 +154,10 @@ export function Component({}: {}) {
|
|||
type="lg"
|
||||
style={styles.description}
|
||||
nativeID="confirmationCode">
|
||||
Check your inbox for an email with the confirmation code to enter
|
||||
below:
|
||||
<Trans>
|
||||
Check your inbox for an email with the confirmation code to
|
||||
enter below:
|
||||
</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
style={[styles.textInput, pal.borderDark, pal.text, styles.mb20]}
|
||||
|
|
@ -160,11 +167,11 @@ export function Component({}: {}) {
|
|||
value={confirmCode}
|
||||
onChangeText={setConfirmCode}
|
||||
accessibilityLabelledBy="confirmationCode"
|
||||
accessibilityLabel="Confirmation code"
|
||||
accessibilityLabel={_(msg`Confirmation code`)}
|
||||
accessibilityHint="Input confirmation code for account deletion"
|
||||
/>
|
||||
<Text type="lg" style={styles.description} nativeID="password">
|
||||
Please enter your password as well:
|
||||
<Trans>Please enter your password as well:</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
style={[styles.textInput, pal.borderDark, pal.text]}
|
||||
|
|
@ -175,7 +182,7 @@ export function Component({}: {}) {
|
|||
value={password}
|
||||
onChangeText={setPassword}
|
||||
accessibilityLabelledBy="password"
|
||||
accessibilityLabel="Password"
|
||||
accessibilityLabel={_(msg`Password`)}
|
||||
accessibilityHint="Input password for account deletion"
|
||||
/>
|
||||
{error ? (
|
||||
|
|
@ -193,21 +200,21 @@ export function Component({}: {}) {
|
|||
style={[styles.btn, styles.evilBtn, styles.mt20]}
|
||||
onPress={onPressConfirmDelete}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Confirm delete account"
|
||||
accessibilityLabel={_(msg`Confirm delete account`)}
|
||||
accessibilityHint="">
|
||||
<Text type="button-lg" style={[s.white, s.bold]}>
|
||||
Delete my account
|
||||
<Trans>Delete my account</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.btn, s.mt10]}
|
||||
onPress={onCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel account deletion"
|
||||
accessibilityLabel={_(msg`Cancel account deletion`)}
|
||||
accessibilityHint="Exits account deletion process"
|
||||
onAccessibilityEscape={onCancel}>
|
||||
<Text type="button-lg" style={pal.textLight}>
|
||||
Cancel
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import {Slider} from '@miblanchard/react-native-slider'
|
|||
import {MaterialIcons} from '@expo/vector-icons'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {getKeys} from 'lib/type-assertions'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['80%']
|
||||
|
|
@ -52,6 +54,7 @@ export const Component = observer(function EditImageImpl({
|
|||
}: Props) {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
const windowDimensions = useWindowDimensions()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {closeModal} = useModalControls()
|
||||
|
|
@ -200,7 +203,9 @@ export const Component = observer(function EditImageImpl({
|
|||
paddingHorizontal: isMobile ? 16 : undefined,
|
||||
},
|
||||
]}>
|
||||
<Text style={[styles.title, pal.text]}>Edit image</Text>
|
||||
<Text style={[styles.title, pal.text]}>
|
||||
<Trans>Edit image</Trans>
|
||||
</Text>
|
||||
<View style={[styles.gap18, s.flexRow]}>
|
||||
<View>
|
||||
<View
|
||||
|
|
@ -228,7 +233,7 @@ export const Component = observer(function EditImageImpl({
|
|||
<View>
|
||||
{!isMobile ? (
|
||||
<Text type="sm-bold" style={pal.text}>
|
||||
Ratios
|
||||
<Trans>Ratios</Trans>
|
||||
</Text>
|
||||
) : null}
|
||||
<View style={imgControlStyles}>
|
||||
|
|
@ -263,7 +268,7 @@ export const Component = observer(function EditImageImpl({
|
|||
</View>
|
||||
{!isMobile ? (
|
||||
<Text type="sm-bold" style={[pal.text, styles.subsection]}>
|
||||
Transformations
|
||||
<Trans>Transformations</Trans>
|
||||
</Text>
|
||||
) : null}
|
||||
<View style={imgControlStyles}>
|
||||
|
|
@ -291,7 +296,7 @@ export const Component = observer(function EditImageImpl({
|
|||
</View>
|
||||
<View style={[styles.gap18, styles.bottomSection, pal.border]}>
|
||||
<Text type="sm-bold" style={pal.text} nativeID="alt-text">
|
||||
Accessibility
|
||||
<Trans>Accessibility</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
testID="altTextImageInput"
|
||||
|
|
@ -307,7 +312,7 @@ export const Component = observer(function EditImageImpl({
|
|||
multiline
|
||||
value={altText}
|
||||
onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))}
|
||||
accessibilityLabel="Alt text"
|
||||
accessibilityLabel={_(msg`Alt text`)}
|
||||
accessibilityHint=""
|
||||
accessibilityLabelledBy="alt-text"
|
||||
/>
|
||||
|
|
@ -315,7 +320,7 @@ export const Component = observer(function EditImageImpl({
|
|||
<View style={styles.btns}>
|
||||
<Pressable onPress={onPressCancel} accessibilityRole="button">
|
||||
<Text type="xl" style={pal.link}>
|
||||
Cancel
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable onPress={onPressSave} accessibilityRole="button">
|
||||
|
|
@ -325,7 +330,7 @@ export const Component = observer(function EditImageImpl({
|
|||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text type="xl-medium" style={s.white}>
|
||||
Done
|
||||
<Trans>Done</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import {useAnalytics} from 'lib/analytics/analytics'
|
|||
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
||||
import Animated, {FadeOut} from 'react-native-reanimated'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
const AnimatedTouchableOpacity =
|
||||
|
|
@ -44,6 +46,7 @@ export function Component({
|
|||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {track} = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
|
||||
const [isProcessing, setProcessing] = useState<boolean>(false)
|
||||
|
|
@ -151,7 +154,9 @@ export function Component({
|
|||
return (
|
||||
<KeyboardAvoidingView style={s.flex1} behavior="height">
|
||||
<ScrollView style={[pal.view]} testID="editProfileModal">
|
||||
<Text style={[styles.title, pal.text]}>Edit my profile</Text>
|
||||
<Text style={[styles.title, pal.text]}>
|
||||
<Trans>Edit my profile</Trans>
|
||||
</Text>
|
||||
<View style={styles.photos}>
|
||||
<UserBanner
|
||||
banner={userBanner}
|
||||
|
|
@ -172,7 +177,9 @@ export function Component({
|
|||
)}
|
||||
<View style={styles.form}>
|
||||
<View>
|
||||
<Text style={[styles.label, pal.text]}>Display Name</Text>
|
||||
<Text style={[styles.label, pal.text]}>
|
||||
<Trans>Display Name</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
testID="editProfileDisplayNameInput"
|
||||
style={[styles.textInput, pal.border, pal.text]}
|
||||
|
|
@ -183,12 +190,14 @@ export function Component({
|
|||
setDisplayName(enforceLen(v, MAX_DISPLAY_NAME))
|
||||
}
|
||||
accessible={true}
|
||||
accessibilityLabel="Display name"
|
||||
accessibilityLabel={_(msg`Display name`)}
|
||||
accessibilityHint="Edit your display name"
|
||||
/>
|
||||
</View>
|
||||
<View style={s.pb10}>
|
||||
<Text style={[styles.label, pal.text]}>Description</Text>
|
||||
<Text style={[styles.label, pal.text]}>
|
||||
<Trans>Description</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
testID="editProfileDescriptionInput"
|
||||
style={[styles.textArea, pal.border, pal.text]}
|
||||
|
|
@ -199,7 +208,7 @@ export function Component({
|
|||
value={description}
|
||||
onChangeText={v => setDescription(enforceLen(v, MAX_DESCRIPTION))}
|
||||
accessible={true}
|
||||
accessibilityLabel="Description"
|
||||
accessibilityLabel={_(msg`Description`)}
|
||||
accessibilityHint="Edit your profile description"
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -213,14 +222,16 @@ export function Component({
|
|||
style={s.mt10}
|
||||
onPress={onPressSave}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Save"
|
||||
accessibilityLabel={_(msg`Save`)}
|
||||
accessibilityHint="Saves any changes to your profile">
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text style={[s.white, s.bold]}>Save Changes</Text>
|
||||
<Text style={[s.white, s.bold]}>
|
||||
<Trans>Save Changes</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
|
@ -231,11 +242,13 @@ export function Component({
|
|||
style={s.mt5}
|
||||
onPress={onPressCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel profile editing"
|
||||
accessibilityLabel={_(msg`Cancel profile editing`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onPressCancel}>
|
||||
<View style={[styles.btn]}>
|
||||
<Text style={[s.black, s.bold, pal.text]}>Cancel</Text>
|
||||
<Text style={[s.black, s.bold, pal.text]}>
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
</AnimatedTouchableOpacity>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {ScrollView} from './util'
|
|||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {useInvitesState, useInvitesAPI} from '#/state/invites'
|
||||
import {UserInfoText} from '../util/UserInfoText'
|
||||
|
|
@ -38,8 +39,10 @@ export function Component({}: {}) {
|
|||
<View style={[styles.container, pal.view]} testID="inviteCodesModal">
|
||||
<View style={[styles.empty, pal.viewLight]}>
|
||||
<Text type="lg" style={[pal.text, styles.emptyText]}>
|
||||
You don't have any invite codes yet! We'll send you some when you've
|
||||
been on Bluesky for a little longer.
|
||||
<Trans>
|
||||
You don't have any invite codes yet! We'll send you some when
|
||||
you've been on Bluesky for a little longer.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.flex1} />
|
||||
|
|
@ -63,10 +66,12 @@ export function Component({}: {}) {
|
|||
return (
|
||||
<View style={[styles.container, pal.view]} testID="inviteCodesModal">
|
||||
<Text type="title-xl" style={[styles.title, pal.text]}>
|
||||
Invite a Friend
|
||||
<Trans>Invite a Friend</Trans>
|
||||
</Text>
|
||||
<Text type="lg" style={[styles.description, pal.text]}>
|
||||
Each code works once. You'll receive more invite codes periodically.
|
||||
<Trans>
|
||||
Each code works once. You'll receive more invite codes periodically.
|
||||
</Trans>
|
||||
</Text>
|
||||
<ScrollView style={[styles.scrollContainer, pal.border]}>
|
||||
{store.me.invites.map((invite, i) => (
|
||||
|
|
@ -138,7 +143,9 @@ const InviteCode = observer(function InviteCodeImpl({
|
|||
</Text>
|
||||
<View style={styles.flex1} />
|
||||
{!used && invitesState.copiedInvites.includes(invite.code) && (
|
||||
<Text style={[pal.textLight, styles.codeCopied]}>Copied</Text>
|
||||
<Text style={[pal.textLight, styles.codeCopied]}>
|
||||
<Trans>Copied</Trans>
|
||||
</Text>
|
||||
)}
|
||||
{!used && (
|
||||
<FontAwesomeIcon
|
||||
|
|
@ -154,7 +161,9 @@ const InviteCode = observer(function InviteCodeImpl({
|
|||
gap: 8,
|
||||
paddingTop: 6,
|
||||
}}>
|
||||
<Text style={pal.text}>Used by:</Text>
|
||||
<Text style={pal.text}>
|
||||
<Trans>Used by:</Trans>
|
||||
</Text>
|
||||
{invite.uses.map(use => (
|
||||
<Link
|
||||
key={use.usedBy}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {isWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {isPossiblyAUrl, splitApexDomain} from 'lib/strings/url-helpers'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['50%']
|
||||
|
|
@ -24,6 +26,7 @@ export const Component = observer(function Component({
|
|||
const pal = usePalette('default')
|
||||
const {closeModal} = useModalControls()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {_} = useLingui()
|
||||
const potentiallyMisleading = isPossiblyAUrl(text)
|
||||
|
||||
const onPressVisit = () => {
|
||||
|
|
@ -45,26 +48,26 @@ export const Component = observer(function Component({
|
|||
size={18}
|
||||
/>
|
||||
<Text type="title-lg" style={[pal.text, styles.title]}>
|
||||
Potentially Misleading Link
|
||||
<Trans>Potentially Misleading Link</Trans>
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<Text type="title-lg" style={[pal.text, styles.title]}>
|
||||
Leaving Bluesky
|
||||
<Trans>Leaving Bluesky</Trans>
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={{gap: 10}}>
|
||||
<Text type="lg" style={pal.text}>
|
||||
This link is taking you to the following website:
|
||||
<Trans>This link is taking you to the following website:</Trans>
|
||||
</Text>
|
||||
|
||||
<LinkBox href={href} />
|
||||
|
||||
{potentiallyMisleading && (
|
||||
<Text type="lg" style={pal.text}>
|
||||
Make sure this is where you intend to go!
|
||||
<Trans>Make sure this is where you intend to go!</Trans>
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
|
@ -74,7 +77,7 @@ export const Component = observer(function Component({
|
|||
testID="confirmBtn"
|
||||
type="primary"
|
||||
onPress={onPressVisit}
|
||||
accessibilityLabel="Visit Site"
|
||||
accessibilityLabel={_(msg`Visit Site`)}
|
||||
accessibilityHint=""
|
||||
label="Visit Site"
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
|
|
@ -84,7 +87,7 @@ export const Component = observer(function Component({
|
|||
testID="cancelBtn"
|
||||
type="default"
|
||||
onPress={() => closeModal()}
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityLabel={_(msg`Cancel`)}
|
||||
accessibilityHint=""
|
||||
label="Cancel"
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import {cleanError} from 'lib/strings/errors'
|
|||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||
import {sanitizeHandle} from 'lib/strings/handles'
|
||||
import {HITSLOP_20} from '#/lib/constants'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['90%']
|
||||
|
|
@ -39,6 +41,7 @@ export const Component = observer(function Component({
|
|||
}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const [query, setQuery] = useState('')
|
||||
|
|
@ -85,7 +88,7 @@ export const Component = observer(function Component({
|
|||
value={query}
|
||||
onChangeText={onChangeQuery}
|
||||
accessible={true}
|
||||
accessibilityLabel="Search"
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
autoFocus
|
||||
autoCapitalize="none"
|
||||
|
|
@ -97,7 +100,7 @@ export const Component = observer(function Component({
|
|||
<Pressable
|
||||
onPress={onPressCancelSearch}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel search"
|
||||
accessibilityLabel={_(msg`Cancel search`)}
|
||||
accessibilityHint="Exits inputting search query"
|
||||
onAccessibilityEscape={onPressCancelSearch}
|
||||
hitSlop={HITSLOP_20}>
|
||||
|
|
@ -136,7 +139,7 @@ export const Component = observer(function Component({
|
|||
pal.textLight,
|
||||
{paddingHorizontal: 12, paddingVertical: 16},
|
||||
]}>
|
||||
No results found for {autocompleteView.prefix}
|
||||
<Trans>No results found for {autocompleteView.prefix}</Trans>
|
||||
</Text>
|
||||
)}
|
||||
</ScrollView>
|
||||
|
|
@ -149,7 +152,7 @@ export const Component = observer(function Component({
|
|||
testID="doneBtn"
|
||||
type="default"
|
||||
onPress={() => closeModal()}
|
||||
accessibilityLabel="Done"
|
||||
accessibilityLabel={_(msg`Done`)}
|
||||
accessibilityHint=""
|
||||
label="Done"
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import {Text} from '../util/text/Text'
|
|||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {RepostIcon} from 'lib/icons'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = [250]
|
||||
|
|
@ -21,6 +23,7 @@ export function Component({
|
|||
// TODO: Add author into component
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const onPress = async () => {
|
||||
closeModal()
|
||||
|
|
@ -38,7 +41,7 @@ export function Component({
|
|||
accessibilityHint={isReposted ? 'Remove repost' : 'Repost '}>
|
||||
<RepostIcon strokeWidth={2} size={24} style={s.blue3} />
|
||||
<Text type="title-lg" style={[styles.actionBtnLabel, pal.text]}>
|
||||
{!isReposted ? 'Repost' : 'Undo repost'}
|
||||
<Trans>{!isReposted ? 'Repost' : 'Undo repost'}</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
|
|
@ -46,11 +49,11 @@ export function Component({
|
|||
style={[styles.actionBtn]}
|
||||
onPress={onQuote}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Quote post"
|
||||
accessibilityLabel={_(msg`Quote post`)}
|
||||
accessibilityHint="">
|
||||
<FontAwesomeIcon icon="quote-left" size={24} style={s.blue3} />
|
||||
<Text type="title-lg" style={[styles.actionBtnLabel, pal.text]}>
|
||||
Quote Post
|
||||
<Trans>Quote Post</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
|
@ -58,7 +61,7 @@ export function Component({
|
|||
testID="cancelBtn"
|
||||
onPress={onPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel quote post"
|
||||
accessibilityLabel={_(msg`Cancel quote post`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onPress}>
|
||||
<LinearGradient
|
||||
|
|
@ -66,7 +69,9 @@ export function Component({
|
|||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text style={[s.white, s.bold, s.f18]}>Cancel</Text>
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import {isWeb} from 'platform/detection'
|
|||
import {Button} from '../util/forms/Button'
|
||||
import {SelectableBtn} from '../util/forms/SelectableBtn'
|
||||
import {ScrollView} from 'view/com/modals/util'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
const ADULT_CONTENT_LABELS = ['sexual', 'nudity', 'porn']
|
||||
|
|
@ -28,6 +30,7 @@ export const Component = observer(function Component({
|
|||
const {closeModal} = useModalControls()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const [selected, setSelected] = useState(labels)
|
||||
const {_} = useLingui()
|
||||
|
||||
const toggleAdultLabel = (label: string) => {
|
||||
const hadLabel = selected.includes(label)
|
||||
|
|
@ -51,7 +54,7 @@ export const Component = observer(function Component({
|
|||
<View testID="selfLabelModal" style={[pal.view, styles.container]}>
|
||||
<View style={styles.titleSection}>
|
||||
<Text type="title-lg" style={[pal.text, styles.title]}>
|
||||
Add a content warning
|
||||
<Trans>Add a content warning</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
|
|
@ -70,7 +73,7 @@ export const Component = observer(function Component({
|
|||
paddingBottom: 8,
|
||||
}}>
|
||||
<Text type="title" style={pal.text}>
|
||||
Adult Content
|
||||
<Trans>Adult Content</Trans>
|
||||
</Text>
|
||||
{hasAdultSelection ? (
|
||||
<Button
|
||||
|
|
@ -78,7 +81,7 @@ export const Component = observer(function Component({
|
|||
onPress={removeAdultLabel}
|
||||
style={{paddingTop: 0, paddingBottom: 0, paddingRight: 0}}>
|
||||
<Text type="md" style={pal.link}>
|
||||
Remove
|
||||
<Trans>Remove</Trans>
|
||||
</Text>
|
||||
</Button>
|
||||
) : null}
|
||||
|
|
@ -116,23 +119,25 @@ export const Component = observer(function Component({
|
|||
|
||||
<Text style={[pal.text, styles.adultExplainer]}>
|
||||
{selected.includes('sexual') ? (
|
||||
<>Pictures meant for adults.</>
|
||||
<Trans>Pictures meant for adults.</Trans>
|
||||
) : selected.includes('nudity') ? (
|
||||
<>Artistic or non-erotic nudity.</>
|
||||
<Trans>Artistic or non-erotic nudity.</Trans>
|
||||
) : selected.includes('porn') ? (
|
||||
<>Sexual activity or erotic nudity.</>
|
||||
<Trans>Sexual activity or erotic nudity.</Trans>
|
||||
) : (
|
||||
<>If none are selected, suitable for all ages.</>
|
||||
<Trans>If none are selected, suitable for all ages.</Trans>
|
||||
)}
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<View>
|
||||
<Text style={[pal.textLight]}>
|
||||
<Text type="md-bold" style={[pal.textLight]}>
|
||||
Not Applicable
|
||||
<Text type="md-bold" style={[pal.textLight, s.mr5]}>
|
||||
<Trans>Not Applicable.</Trans>
|
||||
</Text>
|
||||
. This warning is only available for posts with media attached.
|
||||
<Trans>
|
||||
This warning is only available for posts with media attached.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
|
@ -147,9 +152,11 @@ export const Component = observer(function Component({
|
|||
}}
|
||||
style={styles.btn}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Confirm"
|
||||
accessibilityLabel={_(msg`Confirm`)}
|
||||
accessibilityHint="">
|
||||
<Text style={[s.white, s.bold, s.f18]}>Done</Text>
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
<Trans>Done</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {LOCAL_DEV_SERVICE, STAGING_SERVICE, PROD_SERVICE} from 'state/index'
|
||||
import {LOGIN_INCLUDE_DEV_SERVERS} from 'lib/build-flags'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['80%']
|
||||
|
|
@ -19,6 +21,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
const theme = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const [customUrl, setCustomUrl] = useState<string>('')
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
|
||||
const doSelect = (url: string) => {
|
||||
|
|
@ -32,7 +35,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
return (
|
||||
<View style={[pal.view, s.flex1]} testID="serverInputModal">
|
||||
<Text type="2xl-bold" style={[pal.text, s.textCenter]}>
|
||||
Choose Service
|
||||
<Trans>Choose Service</Trans>
|
||||
</Text>
|
||||
<ScrollView style={styles.inner}>
|
||||
<View style={styles.group}>
|
||||
|
|
@ -43,7 +46,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
style={styles.btn}
|
||||
onPress={() => doSelect(LOCAL_DEV_SERVICE)}
|
||||
accessibilityRole="button">
|
||||
<Text style={styles.btnText}>Local dev server</Text>
|
||||
<Text style={styles.btnText}>
|
||||
<Trans>Local dev server</Trans>
|
||||
</Text>
|
||||
<FontAwesomeIcon
|
||||
icon="arrow-right"
|
||||
style={s.white as FontAwesomeIconStyle}
|
||||
|
|
@ -53,7 +58,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
style={styles.btn}
|
||||
onPress={() => doSelect(STAGING_SERVICE)}
|
||||
accessibilityRole="button">
|
||||
<Text style={styles.btnText}>Staging</Text>
|
||||
<Text style={styles.btnText}>
|
||||
<Trans>Staging</Trans>
|
||||
</Text>
|
||||
<FontAwesomeIcon
|
||||
icon="arrow-right"
|
||||
style={s.white as FontAwesomeIconStyle}
|
||||
|
|
@ -65,9 +72,11 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
style={styles.btn}
|
||||
onPress={() => doSelect(PROD_SERVICE)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Select Bluesky Social"
|
||||
accessibilityLabel={_(msg`Select Bluesky Social`)}
|
||||
accessibilityHint="Sets Bluesky Social as your service provider">
|
||||
<Text style={styles.btnText}>Bluesky.Social</Text>
|
||||
<Text style={styles.btnText}>
|
||||
<Trans>Bluesky.Social</Trans>
|
||||
</Text>
|
||||
<FontAwesomeIcon
|
||||
icon="arrow-right"
|
||||
style={s.white as FontAwesomeIconStyle}
|
||||
|
|
@ -75,7 +84,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.group}>
|
||||
<Text style={[pal.text, styles.label]}>Other service</Text>
|
||||
<Text style={[pal.text, styles.label]}>
|
||||
<Trans>Other service</Trans>
|
||||
</Text>
|
||||
<View style={s.flexRow}>
|
||||
<TextInput
|
||||
testID="customServerTextInput"
|
||||
|
|
@ -88,7 +99,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
|
|||
keyboardAppearance={theme.colorScheme}
|
||||
value={customUrl}
|
||||
onChangeText={setCustomUrl}
|
||||
accessibilityLabel="Custom domain"
|
||||
accessibilityLabel={_(msg`Custom domain`)}
|
||||
// TODO: Simplify this wording further to be understandable by everyone
|
||||
accessibilityHint="Use your domain as your Bluesky client service provider"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -17,12 +17,15 @@ import {Link} from '../util/Link'
|
|||
import {makeProfileLink} from 'lib/routes/links'
|
||||
import {BottomSheetScrollView} from '@gorhom/bottom-sheet'
|
||||
import {Haptics} from 'lib/haptics'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
export const snapPoints = ['40%', '90%']
|
||||
|
||||
export function Component({}: {}) {
|
||||
const pal = usePalette('default')
|
||||
const {track} = useAnalytics()
|
||||
const {_: _lingui} = useLingui()
|
||||
|
||||
const store = useStores()
|
||||
const [isSwitching, _, onPressSwitchAccount] = useAccountSwitcher()
|
||||
|
|
@ -41,7 +44,7 @@ export function Component({}: {}) {
|
|||
style={[styles.container, pal.view]}
|
||||
contentContainerStyle={[styles.innerContainer, pal.view]}>
|
||||
<Text type="title-xl" style={[styles.title, pal.text]}>
|
||||
Switch Account
|
||||
<Trans>Switch Account</Trans>
|
||||
</Text>
|
||||
{isSwitching ? (
|
||||
<View style={[pal.view, styles.linkCard]}>
|
||||
|
|
@ -65,10 +68,10 @@ export function Component({}: {}) {
|
|||
testID="signOutBtn"
|
||||
onPress={isSwitching ? undefined : onPressSignout}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Sign out"
|
||||
accessibilityLabel={_lingui(msg`Sign out`)}
|
||||
accessibilityHint={`Signs ${store.me.displayName} out of Bluesky`}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
Sign out
|
||||
<Trans>Sign out</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {isWeb, isAndroid} from 'platform/detection'
|
||||
import isEqual from 'lodash.isequal'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['fullscreen']
|
||||
|
|
@ -39,6 +41,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
|
|||
const store = useStores()
|
||||
const {closeModal} = useModalControls()
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const palPrimary = usePalette('primary')
|
||||
const palInverted = usePalette('inverted')
|
||||
const [originalSelections, setOriginalSelections] = React.useState<string[]>(
|
||||
|
|
@ -181,7 +184,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
|
|||
return (
|
||||
<View testID="userAddRemoveListsModal" style={s.hContentRegion}>
|
||||
<Text style={[styles.title, pal.text]}>
|
||||
Update {displayName} in Lists
|
||||
<Trans>Update {displayName} in Lists</Trans>
|
||||
</Text>
|
||||
<ListsList
|
||||
listsList={listsList}
|
||||
|
|
@ -195,7 +198,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
|
|||
type="default"
|
||||
onPress={onPressCancel}
|
||||
style={styles.footerBtn}
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityLabel={_(msg`Cancel`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onPressCancel}
|
||||
label="Cancel"
|
||||
|
|
@ -206,7 +209,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
|
|||
type="primary"
|
||||
onPress={onPressSave}
|
||||
style={styles.footerBtn}
|
||||
accessibilityLabel="Save changes"
|
||||
accessibilityLabel={_(msg`Save changes`)}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={onPressSave}
|
||||
label="Save Changes"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {isWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['90%']
|
||||
|
|
@ -37,6 +39,7 @@ export const Component = observer(function Component({
|
|||
}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const [stage, setStage] = useState<Stages>(
|
||||
showReminder ? Stages.Reminder : Stages.Email,
|
||||
)
|
||||
|
|
@ -98,21 +101,21 @@ export const Component = observer(function Component({
|
|||
|
||||
<Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
|
||||
{stage === Stages.Reminder ? (
|
||||
<>
|
||||
<Trans>
|
||||
Your email has not yet been verified. This is an important
|
||||
security step which we recommend.
|
||||
</>
|
||||
</Trans>
|
||||
) : stage === Stages.Email ? (
|
||||
<>
|
||||
<Trans>
|
||||
This is important in case you ever need to change your email or
|
||||
reset your password.
|
||||
</>
|
||||
</Trans>
|
||||
) : stage === Stages.ConfirmCode ? (
|
||||
<>
|
||||
<Trans>
|
||||
An email has been sent to{' '}
|
||||
{store.session.currentSession?.email || ''}. It includes a
|
||||
confirmation code which you can enter below.
|
||||
</>
|
||||
</Trans>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
|
@ -132,7 +135,7 @@ export const Component = observer(function Component({
|
|||
</View>
|
||||
<Pressable
|
||||
accessibilityRole="link"
|
||||
accessibilityLabel="Change my email"
|
||||
accessibilityLabel={_(msg`Change my email`)}
|
||||
accessibilityHint=""
|
||||
onPress={onEmailIncorrect}
|
||||
style={styles.changeEmailLink}>
|
||||
|
|
@ -150,7 +153,7 @@ export const Component = observer(function Component({
|
|||
value={confirmationCode}
|
||||
onChangeText={setConfirmationCode}
|
||||
accessible={true}
|
||||
accessibilityLabel="Confirmation code"
|
||||
accessibilityLabel={_(msg`Confirmation code`)}
|
||||
accessibilityHint=""
|
||||
autoCapitalize="none"
|
||||
autoComplete="off"
|
||||
|
|
@ -174,7 +177,7 @@ export const Component = observer(function Component({
|
|||
testID="getStartedBtn"
|
||||
type="primary"
|
||||
onPress={() => setStage(Stages.Email)}
|
||||
accessibilityLabel="Get Started"
|
||||
accessibilityLabel={_(msg`Get Started`)}
|
||||
accessibilityHint=""
|
||||
label="Get Started"
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
|
|
@ -187,7 +190,7 @@ export const Component = observer(function Component({
|
|||
testID="sendEmailBtn"
|
||||
type="primary"
|
||||
onPress={onSendEmail}
|
||||
accessibilityLabel="Send Confirmation Email"
|
||||
accessibilityLabel={_(msg`Send Confirmation Email`)}
|
||||
accessibilityHint=""
|
||||
label="Send Confirmation Email"
|
||||
labelContainerStyle={{
|
||||
|
|
@ -199,7 +202,7 @@ export const Component = observer(function Component({
|
|||
<Button
|
||||
testID="haveCodeBtn"
|
||||
type="default"
|
||||
accessibilityLabel="I have a code"
|
||||
accessibilityLabel={_(msg`I have a code`)}
|
||||
accessibilityHint=""
|
||||
label="I have a confirmation code"
|
||||
labelContainerStyle={{
|
||||
|
|
@ -216,7 +219,7 @@ export const Component = observer(function Component({
|
|||
testID="confirmBtn"
|
||||
type="primary"
|
||||
onPress={onConfirm}
|
||||
accessibilityLabel="Confirm"
|
||||
accessibilityLabel={_(msg`Confirm`)}
|
||||
accessibilityHint=""
|
||||
label="Confirm"
|
||||
labelContainerStyle={{justifyContent: 'center', padding: 4}}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {cleanError} from 'lib/strings/errors'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
export const snapPoints = ['80%']
|
||||
|
|
@ -24,6 +26,7 @@ export const snapPoints = ['80%']
|
|||
export function Component({}: {}) {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {closeModal} = useModalControls()
|
||||
const [email, setEmail] = React.useState<string>('')
|
||||
const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false)
|
||||
|
|
@ -61,12 +64,14 @@ export function Component({}: {}) {
|
|||
<View style={[styles.container, pal.view]}>
|
||||
<View style={[styles.innerContainer, pal.view]}>
|
||||
<Text type="title-xl" style={[styles.title, pal.text]}>
|
||||
Join the waitlist
|
||||
<Trans>Join the waitlist</Trans>
|
||||
</Text>
|
||||
<Text type="lg" style={[styles.description, pal.text]}>
|
||||
Bluesky uses invites to build a healthier community. If you don't know
|
||||
anybody with an invite, you can sign up for the waitlist and we'll
|
||||
send one soon.
|
||||
<Trans>
|
||||
Bluesky uses invites to build a healthier community. If you don't
|
||||
know anybody with an invite, you can sign up for the waitlist and
|
||||
we'll send one soon.
|
||||
</Trans>
|
||||
</Text>
|
||||
<TextInput
|
||||
style={[styles.textInput, pal.borderDark, pal.text, s.mb10, s.mt10]}
|
||||
|
|
@ -80,7 +85,7 @@ export function Component({}: {}) {
|
|||
onSubmitEditing={onPressSignup}
|
||||
enterKeyHint="done"
|
||||
accessible={true}
|
||||
accessibilityLabel="Email"
|
||||
accessibilityLabel={_(msg`Email`)}
|
||||
accessibilityHint="Input your email to get on the Bluesky waitlist"
|
||||
/>
|
||||
{error ? (
|
||||
|
|
@ -99,7 +104,9 @@ export function Component({}: {}) {
|
|||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
<Text style={[s.ml10, pal.text]}>
|
||||
Your email has been saved! We'll be in touch soon.
|
||||
<Trans>
|
||||
Your email has been saved! We'll be in touch soon.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
) : (
|
||||
|
|
@ -114,7 +121,7 @@ export function Component({}: {}) {
|
|||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text type="button-lg" style={[s.white, s.bold]}>
|
||||
Join Waitlist
|
||||
<Trans>Join Waitlist</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -122,11 +129,11 @@ export function Component({}: {}) {
|
|||
style={[styles.btn, s.mt10]}
|
||||
onPress={onCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel waitlist signup"
|
||||
accessibilityLabel={_(msg`Cancel waitlist signup`)}
|
||||
accessibilityHint={`Exits signing up for waitlist with ${email}`}
|
||||
onAccessibilityEscape={onCancel}>
|
||||
<Text type="button-lg" style={pal.textLight}>
|
||||
Cancel
|
||||
<Trans>Cancel</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import {s, gradients} from 'lib/styles'
|
|||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {SquareIcon, RectWideIcon, RectTallIcon} from 'lib/icons'
|
||||
import {Image as RNImage} from 'react-native-image-crop-picker'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
enum AspectRatio {
|
||||
|
|
@ -35,6 +37,7 @@ export function Component({
|
|||
}) {
|
||||
const {closeModal} = useModalControls()
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const [as, setAs] = React.useState<AspectRatio>(AspectRatio.Square)
|
||||
const [scale, setScale] = React.useState<number>(1)
|
||||
const editorRef = React.useRef<ImageEditor>(null)
|
||||
|
|
@ -96,7 +99,7 @@ export function Component({
|
|||
<TouchableOpacity
|
||||
onPress={doSetAs(AspectRatio.Wide)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Wide"
|
||||
accessibilityLabel={_(msg`Wide`)}
|
||||
accessibilityHint="Sets image aspect ratio to wide">
|
||||
<RectWideIcon
|
||||
size={24}
|
||||
|
|
@ -106,7 +109,7 @@ export function Component({
|
|||
<TouchableOpacity
|
||||
onPress={doSetAs(AspectRatio.Tall)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Tall"
|
||||
accessibilityLabel={_(msg`Tall`)}
|
||||
accessibilityHint="Sets image aspect ratio to tall">
|
||||
<RectTallIcon
|
||||
size={24}
|
||||
|
|
@ -116,7 +119,7 @@ export function Component({
|
|||
<TouchableOpacity
|
||||
onPress={doSetAs(AspectRatio.Square)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Square"
|
||||
accessibilityLabel={_(msg`Square`)}
|
||||
accessibilityHint="Sets image aspect ratio to square">
|
||||
<SquareIcon
|
||||
size={24}
|
||||
|
|
@ -128,7 +131,7 @@ export function Component({
|
|||
<TouchableOpacity
|
||||
onPress={onPressCancel}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel image crop"
|
||||
accessibilityLabel={_(msg`Cancel image crop`)}
|
||||
accessibilityHint="Exits image cropping process">
|
||||
<Text type="xl" style={pal.link}>
|
||||
Cancel
|
||||
|
|
@ -138,7 +141,7 @@ export function Component({
|
|||
<TouchableOpacity
|
||||
onPress={onPressDone}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Save image crop"
|
||||
accessibilityLabel={_(msg`Save image crop`)}
|
||||
accessibilityHint="Saves image crop settings">
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
|
|
@ -146,7 +149,7 @@ export function Component({
|
|||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text type="xl-medium" style={s.white}>
|
||||
Done
|
||||
<Trans>Done</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import LinearGradient from 'react-native-linear-gradient'
|
|||
import {s, colors, gradients} from 'lib/styles'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
export const ConfirmLanguagesButton = ({
|
||||
onPress,
|
||||
|
|
@ -13,6 +15,7 @@ export const ConfirmLanguagesButton = ({
|
|||
extraText?: string
|
||||
}) => {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
return (
|
||||
<View
|
||||
|
|
@ -28,14 +31,16 @@ export const ConfirmLanguagesButton = ({
|
|||
testID="confirmContentLanguagesBtn"
|
||||
onPress={onPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Confirm content language settings"
|
||||
accessibilityLabel={_(msg`Confirm content language settings`)}
|
||||
accessibilityHint="">
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text style={[s.white, s.bold, s.f18]}>Done{extraText}</Text>
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
<Trans>Done{extraText}</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {deviceLocales} from 'platform/detection'
|
|||
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
||||
import {LanguageToggle} from './LanguageToggle'
|
||||
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {
|
||||
useLanguagePrefs,
|
||||
|
|
@ -69,12 +70,16 @@ export function Component({}: {}) {
|
|||
maxHeight: '90vh',
|
||||
},
|
||||
]}>
|
||||
<Text style={[pal.text, styles.title]}>Content Languages</Text>
|
||||
<Text style={[pal.text, styles.title]}>
|
||||
<Trans>Content Languages</Trans>
|
||||
</Text>
|
||||
<Text style={[pal.text, styles.description]}>
|
||||
Which languages would you like to see in your algorithmic feeds?
|
||||
<Trans>
|
||||
Which languages would you like to see in your algorithmic feeds?
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text style={[pal.textLight, styles.description]}>
|
||||
Leave them all unchecked to see any language.
|
||||
<Trans>Leave them all unchecked to see any language.</Trans>
|
||||
</Text>
|
||||
<ScrollView style={styles.scrollContainer}>
|
||||
{languages.map(lang => (
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {deviceLocales} from 'platform/detection'
|
|||
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
||||
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {
|
||||
useLanguagePrefs,
|
||||
|
|
@ -71,9 +72,11 @@ export const Component = observer(function PostLanguagesSettingsImpl() {
|
|||
maxHeight: '90vh',
|
||||
},
|
||||
]}>
|
||||
<Text style={[pal.text, styles.title]}>Post Languages</Text>
|
||||
<Text style={[pal.text, styles.title]}>
|
||||
<Trans>Post Languages</Trans>
|
||||
</Text>
|
||||
<Text style={[pal.text, styles.description]}>
|
||||
Which languages are used in this post?
|
||||
<Trans>Which languages are used in this post?</Trans>
|
||||
</Text>
|
||||
<ScrollView style={styles.scrollContainer}>
|
||||
{languages.map(lang => {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {s} from 'lib/styles'
|
||||
import {SendReportButton} from './SendReportButton'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
export function InputIssueDetails({
|
||||
details,
|
||||
|
|
@ -23,6 +25,7 @@ export function InputIssueDetails({
|
|||
isProcessing: boolean
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
|
||||
return (
|
||||
|
|
@ -35,14 +38,16 @@ export function InputIssueDetails({
|
|||
style={[s.mb10, styles.backBtn]}
|
||||
onPress={goBack}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Add details"
|
||||
accessibilityLabel={_(msg`Add details`)}
|
||||
accessibilityHint="Add more details to your report">
|
||||
<FontAwesomeIcon size={18} icon="angle-left" style={[pal.link]} />
|
||||
<Text style={[pal.text, s.f18, pal.link]}> Back</Text>
|
||||
<Text style={[pal.text, s.f18, pal.link]}>
|
||||
<Trans> Back</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={[pal.btn, styles.detailsInputContainer]}>
|
||||
<TextInput
|
||||
accessibilityLabel="Text input field"
|
||||
accessibilityLabel={_(msg`Text input field`)}
|
||||
accessibilityHint="Enter a reason for reporting this post."
|
||||
placeholder="Enter a reason or any other details here."
|
||||
placeholderTextColor={pal.textLight.color}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import {SendReportButton} from './SendReportButton'
|
|||
import {InputIssueDetails} from './InputIssueDetails'
|
||||
import {ReportReasonOptions} from './ReasonOptions'
|
||||
import {CollectionId} from './types'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
|
||||
const DMCA_LINK = 'https://blueskyweb.xyz/support/copyright'
|
||||
|
|
@ -148,6 +150,7 @@ const SelectIssue = ({
|
|||
atUri: AtUri | null
|
||||
}) => {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const collectionName = getCollectionNameForReport(atUri)
|
||||
const onSelectIssue = (v: string) => setIssue(v)
|
||||
const goToDetails = () => {
|
||||
|
|
@ -160,9 +163,11 @@ const SelectIssue = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Text style={[pal.text, styles.title]}>Report {collectionName}</Text>
|
||||
<Text style={[pal.text, styles.title]}>
|
||||
<Trans>Report {collectionName}</Trans>
|
||||
</Text>
|
||||
<Text style={[pal.textLight, styles.description]}>
|
||||
What is the issue with this {collectionName}?
|
||||
<Trans>What is the issue with this {collectionName}?</Trans>
|
||||
</Text>
|
||||
<View style={{marginBottom: 10}}>
|
||||
<ReportReasonOptions
|
||||
|
|
@ -184,9 +189,11 @@ const SelectIssue = ({
|
|||
style={styles.addDetailsBtn}
|
||||
onPress={goToDetails}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Add details"
|
||||
accessibilityLabel={_(msg`Add details`)}
|
||||
accessibilityHint="Add more details to your report">
|
||||
<Text style={[s.f18, pal.link]}>Add details to report</Text>
|
||||
<Text style={[s.f18, pal.link]}>
|
||||
<Trans>Add details to report</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
) : undefined}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import {
|
|||
} from 'react-native'
|
||||
import {Text} from '../../util/text/Text'
|
||||
import {s, gradients, colors} from 'lib/styles'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
export function SendReportButton({
|
||||
onPress,
|
||||
|
|
@ -16,6 +18,7 @@ export function SendReportButton({
|
|||
onPress: () => void
|
||||
isProcessing: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
// loading state
|
||||
// =
|
||||
if (isProcessing) {
|
||||
|
|
@ -31,14 +34,16 @@ export function SendReportButton({
|
|||
style={s.mt10}
|
||||
onPress={onPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Report post"
|
||||
accessibilityLabel={_(msg`Report post`)}
|
||||
accessibilityHint={`Reports post with reason and details`}>
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
style={[styles.btn]}>
|
||||
<Text style={[s.white, s.bold, s.f18]}>Send Report</Text>
|
||||
<Text style={[s.white, s.bold, s.f18]}>
|
||||
<Trans>Send Report</Trans>
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue