Merge remote-tracking branch 'origin' into eric/nova

* origin: (45 commits)
  Fix splash config (#2452)
  convert prefix to lowercase in actor autocomplete query (#2431)
  support intl tenor links (#2438)
  Splash: reduce motion + dark mode (#2448)
  Bump android app version code
  Don't use mask for android at all (#2445)
  Update Korean localization (#2432)
  Use android mode, fix fallback (#2437)
  Update for Version 1.63 Português (BR) (#2435)
  New translations messages.po (Ukrainian) (#2422)
  Update Japanese localization (addition + language code correction) (#2423)
  1.63
  Additional embed sources and external-media consent controls (#2424)
  Reduce web requests (#2420)
  New user home feed fixes (#2421)
  E2E runner fixes (#2428)
  Recompile all locales (#2411) (#2416)
  Add Ukrainian localization (#2336)
  Update Portuguese for Português (#2414)
  Add Portuguese Localization (#2407)
  ...
This commit is contained in:
Eric Bailey
2024-01-08 17:33:31 -06:00
75 changed files with 12279 additions and 1235 deletions
+24 -3
View File
@@ -1,5 +1,6 @@
import {resolveConfig} from 'detox/internals'
import {execSync} from 'child_process'
import http from 'http'
const platform = device.getPlatform()
@@ -105,9 +106,29 @@ async function openAppForDebugBuild(platform: string, opts: any) {
}
export async function createServer(path = '') {
const res = await fetch(`http://localhost:1986/${path}`, {method: 'POST'})
const resBody = await res.text()
return resBody
return new Promise(function (resolve, reject) {
var req = http.request(
{
method: 'POST',
host: 'localhost',
port: 1986,
path: `/${path}`,
},
function (res) {
const body: Buffer[] = []
res.on('data', chunk => body.push(chunk))
res.on('end', function () {
try {
resolve(Buffer.concat(body).toString())
} catch (e) {
reject(e)
}
})
},
)
req.on('error', reject)
req.end()
})
}
const getDeepLinkUrl = (url: string) =>
+268 -26
View File
@@ -394,6 +394,7 @@ describe('parseEmbedPlayerFromUrl', () => {
'https://youtube.com/watch?v=videoId',
'https://youtube.com/watch?v=videoId&feature=share',
'https://youtube.com/shorts/videoId',
'https://m.youtube.com/watch?v=videoId',
'https://youtube.com/shorts/',
'https://youtube.com/',
@@ -401,113 +402,354 @@ describe('parseEmbedPlayerFromUrl', () => {
'https://twitch.tv/channelName',
'https://www.twitch.tv/channelName',
'https://m.twitch.tv/channelName',
'https://twitch.tv/channelName/clip/clipId',
'https://twitch.tv/videos/videoId',
'https://open.spotify.com/playlist/playlistId',
'https://open.spotify.com/playlist/playlistId?param=value',
'https://open.spotify.com/locale/playlist/playlistId',
'https://open.spotify.com/track/songId',
'https://open.spotify.com/track/songId?param=value',
'https://open.spotify.com/locale/track/songId',
'https://open.spotify.com/album/albumId',
'https://open.spotify.com/album/albumId?param=value',
'https://open.spotify.com/locale/album/albumId',
'https://soundcloud.com/user/track',
'https://soundcloud.com/user/sets/set',
'https://soundcloud.com/user/',
'https://music.apple.com/us/playlist/playlistName/playlistId',
'https://music.apple.com/us/album/albumName/albumId',
'https://music.apple.com/us/album/albumName/albumId?i=songId',
'https://vimeo.com/videoId',
'https://vimeo.com/videoId?autoplay=0',
'https://giphy.com/gifs/some-random-gif-name-gifId',
'https://giphy.com/gif/some-random-gif-name-gifId',
'https://giphy.com/gifs/',
'https://media.giphy.com/media/gifId/giphy.webp',
'https://media0.giphy.com/media/gifId/giphy.webp',
'https://media1.giphy.com/media/gifId/giphy.gif',
'https://media2.giphy.com/media/gifId/giphy.webp',
'https://media3.giphy.com/media/gifId/giphy.mp4',
'https://media4.giphy.com/media/gifId/giphy.webp',
'https://media5.giphy.com/media/gifId/giphy.mp4',
'https://media0.giphy.com/media/gifId/giphy.mp3',
'https://media1.google.com/media/gifId/giphy.webp',
'https://media.giphy.com/media/trackingId/gifId/giphy.webp',
'https://i.giphy.com/media/gifId/giphy.webp',
'https://i.giphy.com/media/gifId/giphy.webp',
'https://i.giphy.com/gifId.gif',
'https://i.giphy.com/gifId.gif',
'https://tenor.com/view/gifId',
'https://tenor.com/notView/gifId',
'https://tenor.com/view',
'https://tenor.com/view/gifId.gif',
'https://tenor.com/intl/view/gifId.gif',
]
const outputs = [
{
type: 'youtube_video',
videoId: 'videoId',
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
source: 'youtube',
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
{
type: 'youtube_video',
videoId: 'videoId',
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
source: 'youtube',
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
{
type: 'youtube_video',
videoId: 'videoId',
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
source: 'youtube',
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
{
type: 'youtube_video',
videoId: 'videoId',
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
source: 'youtube',
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
{
type: 'youtube_video',
videoId: 'videoId',
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
source: 'youtube',
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
{
type: 'youtube_short',
source: 'youtubeShorts',
hideDetails: true,
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
{
type: 'youtube_video',
videoId: 'videoId',
playerUri: 'https://www.youtube.com/embed/videoId?autoplay=1',
source: 'youtube',
playerUri:
'https://www.youtube.com/embed/videoId?autoplay=1&playsinline=1',
},
undefined,
undefined,
undefined,
{
type: 'twitch_live',
channelId: 'channelName',
type: 'twitch_video',
source: 'twitch',
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
},
{
type: 'twitch_live',
channelId: 'channelName',
type: 'twitch_video',
source: 'twitch',
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
},
{
type: 'twitch_video',
source: 'twitch',
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
},
{
type: 'twitch_video',
source: 'twitch',
playerUri: `https://clips.twitch.tv/embed?volume=0.5&autoplay=true&clip=clipId&parent=localhost`,
},
{
type: 'twitch_video',
source: 'twitch',
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&video=videoId&parent=localhost`,
},
{
type: 'spotify_playlist',
playlistId: 'playlistId',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
},
{
type: 'spotify_playlist',
playlistId: 'playlistId',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
},
{
type: 'spotify_playlist',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
},
{
type: 'spotify_song',
songId: 'songId',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/track/songId`,
},
{
type: 'spotify_song',
songId: 'songId',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/track/songId`,
},
{
type: 'spotify_song',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/track/songId`,
},
{
type: 'spotify_album',
albumId: 'albumId',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/album/albumId`,
},
{
type: 'spotify_album',
albumId: 'albumId',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/album/albumId`,
},
{
type: 'spotify_album',
source: 'spotify',
playerUri: `https://open.spotify.com/embed/album/albumId`,
},
{
type: 'soundcloud_track',
user: 'user',
track: 'track',
source: 'soundcloud',
playerUri: `https://w.soundcloud.com/player/?url=https://soundcloud.com/user/track&auto_play=true&visual=false&hide_related=true`,
},
{
type: 'soundcloud_set',
user: 'user',
set: 'set',
source: 'soundcloud',
playerUri: `https://w.soundcloud.com/player/?url=https://soundcloud.com/user/sets/set&auto_play=true&visual=false&hide_related=true`,
},
undefined,
{
type: 'apple_music_playlist',
source: 'appleMusic',
playerUri:
'https://embed.music.apple.com/us/playlist/playlistName/playlistId',
},
{
type: 'apple_music_album',
source: 'appleMusic',
playerUri: 'https://embed.music.apple.com/us/album/albumName/albumId',
},
{
type: 'apple_music_song',
source: 'appleMusic',
playerUri:
'https://embed.music.apple.com/us/album/albumName/albumId?i=songId',
},
{
type: 'vimeo_video',
source: 'vimeo',
playerUri: 'https://player.vimeo.com/video/videoId?autoplay=1',
},
{
type: 'vimeo_video',
source: 'vimeo',
playerUri: 'https://player.vimeo.com/video/videoId?autoplay=1',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
undefined,
undefined,
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
undefined,
undefined,
undefined,
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: 'https://giphy.com/gifs/gifId',
playerUri: 'https://i.giphy.com/media/gifId/giphy.webp',
},
{
type: 'tenor_gif',
source: 'tenor',
isGif: true,
hideDetails: true,
playerUri: 'https://tenor.com/view/gifId.gif',
},
undefined,
undefined,
{
type: 'tenor_gif',
source: 'tenor',
isGif: true,
hideDetails: true,
playerUri: 'https://tenor.com/view/gifId.gif',
},
{
type: 'tenor_gif',
source: 'tenor',
isGif: true,
hideDetails: true,
playerUri: 'https://tenor.com/intl/view/gifId.gif',
},
]
it('correctly grabs the correct id from uri', () => {
+22 -7
View File
@@ -1,5 +1,16 @@
const pkg = require('./package.json')
const SPLASH_CONFIG = {
backgroundColor: '#ffffff',
image: './assets/splash.png',
resizeMode: 'cover',
}
const DARK_SPLASH_CONFIG = {
backgroundColor: '#001429',
image: './assets/splash-dark.png',
resizeMode: 'cover',
}
module.exports = function () {
/**
* App version number. Should be incremented as part of a release cycle.
@@ -9,12 +20,12 @@ module.exports = function () {
/**
* iOS build number. Must be incremented for each TestFlight version.
*/
const IOS_BUILD_NUMBER = '2'
const IOS_BUILD_NUMBER = '1'
/**
* Android build number. Must be incremented for each release.
*/
const ANDROID_VERSION_CODE = 53
const ANDROID_VERSION_CODE = 55
/**
* Uses built-in Expo env vars
@@ -42,11 +53,7 @@ module.exports = function () {
orientation: 'portrait',
icon: './assets/icon.png',
userInterfaceStyle: 'automatic',
splash: {
image: './assets/splash.png',
resizeMode: 'cover',
backgroundColor: '#ffffff',
},
splash: SPLASH_CONFIG,
ios: {
buildNumber: IOS_BUILD_NUMBER,
supportsTablet: false,
@@ -66,6 +73,10 @@ module.exports = function () {
'Used for profile pictures, posts, and other kinds of content',
},
associatedDomains: ['applinks:bsky.app', 'applinks:staging.bsky.app'],
splash: {
...SPLASH_CONFIG,
dark: DARK_SPLASH_CONFIG,
},
},
androidStatusBar: {
barStyle: 'dark-content',
@@ -95,6 +106,10 @@ module.exports = function () {
category: ['BROWSABLE', 'DEFAULT'],
},
],
splash: {
...SPLASH_CONFIG,
dark: DARK_SPLASH_CONFIG,
},
},
web: {
favicon: './assets/favicon.png',
Binary file not shown.

After

Width:  |  Height:  |  Size: 991 KiB

+1
View File
@@ -193,6 +193,7 @@ func serve(cctx *cli.Context) error {
e.GET("/settings/home-feed", server.WebGeneric)
e.GET("/settings/saved-feeds", server.WebGeneric)
e.GET("/settings/threads", server.WebGeneric)
e.GET("/settings/external-embeds", server.WebGeneric)
e.GET("/sys/debug", server.WebGeneric)
e.GET("/sys/log", server.WebGeneric)
e.GET("/support", server.WebGeneric)
+1 -1
View File
@@ -1,6 +1,6 @@
/** @type {import('@lingui/conf').LinguiConfig} */
module.exports = {
locales: ['en', 'hi', 'ja', 'fr', 'de', 'es'],
locales: ['en', 'hi', 'ja', 'fr', 'de', 'es', 'ko', 'es', 'pt-BR', 'uk'],
catalogs: [
{
path: '<rootDir>/src/locale/locales/{locale}/messages',
+3 -5
View File
@@ -1,6 +1,6 @@
{
"name": "bsky.app",
"version": "1.62.0",
"version": "1.63.0",
"private": true,
"engines": {
"node": ">=18"
@@ -23,7 +23,7 @@
"test-coverage": "NODE_ENV=test jest --coverage",
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
"typecheck": "tsc --project ./tsconfig.check.json",
"e2e:mock-server": "./jest/dev-infra/with-test-redis-and-db.sh ts-node __e2e__/mock-server.ts",
"e2e:mock-server": "./jest/dev-infra/with-test-redis-and-db.sh ts-node --project tsconfig.e2e.json __e2e__/mock-server.ts",
"e2e:metro": "NODE_ENV=test RN_SRC_EXT=e2e.ts,e2e.tsx expo run:ios",
"e2e:build": "NODE_ENV=test detox build -c ios.sim.debug",
"e2e:run": "NODE_ENV=test detox test --configuration ios.sim.debug --take-screenshots all",
@@ -158,7 +158,6 @@
"react-native-root-siblings": "^4.1.1",
"react-native-safe-area-context": "4.7.4",
"react-native-screens": "~3.27.0",
"react-native-splash-screen": "^3.3.0",
"react-native-svg": "14.0.0",
"react-native-url-polyfill": "^1.3.0",
"react-native-uuid": "^2.0.1",
@@ -167,7 +166,6 @@
"react-native-web-linear-gradient": "^1.1.2",
"react-native-web-webview": "^1.0.2",
"react-native-webview": "^13.6.3",
"react-native-youtube-iframe": "^2.3.0",
"react-responsive": "^9.0.2",
"rn-fetch-blob": "^0.12.0",
"sentry-expo": "~7.0.1",
@@ -216,7 +214,7 @@
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-react-native-web": "^0.18.12",
"babel-preset-expo": "^10.0.0",
"detox": "^20.13.0",
"detox": "^20.14.8",
"eslint": "^8.19.0",
"eslint-plugin-detox": "^1.0.0",
"eslint-plugin-ft-flow": "^2.0.3",
+64
View File
@@ -0,0 +1,64 @@
diff --git a/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/contracts/ImageLibraryContract.kt b/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/contracts/ImageLibraryContract.kt
index ff15c91..41aaf12 100644
--- a/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/contracts/ImageLibraryContract.kt
+++ b/node_modules/expo-image-picker/android/src/main/java/expo/modules/imagepicker/contracts/ImageLibraryContract.kt
@@ -26,51 +26,26 @@ import java.io.Serializable
* @see [androidx.activity.result.contract.ActivityResultContracts.GetMultipleContents]
*/
internal class ImageLibraryContract(
- private val appContextProvider: AppContextProvider
+ private val appContextProvider: AppContextProvider,
) : AppContextActivityResultContract<ImageLibraryContractOptions, ImagePickerContractResult> {
private val contentResolver: ContentResolver
get() = appContextProvider.appContext.reactContext?.contentResolver
?: throw Exceptions.ReactContextLost()
override fun createIntent(context: Context, input: ImageLibraryContractOptions): Intent {
- val request = PickVisualMediaRequest.Builder()
- .setMediaType(
- when (input.options.mediaTypes) {
- MediaTypes.VIDEOS -> {
- PickVisualMedia.VideoOnly
- }
-
- MediaTypes.IMAGES -> {
- PickVisualMedia.ImageOnly
- }
-
- else -> {
- PickVisualMedia.ImageAndVideo
- }
- }
- )
- .build()
+ val intent = Intent(Intent.ACTION_GET_CONTENT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType("image/*")
if (input.options.allowsMultipleSelection) {
- val selectionLimit = input.options.selectionLimit
-
- if (selectionLimit == 1) {
- // If multiple selection is allowed but the limit is 1, we should ignore
- // the multiple selection flag and just treat it as a single selection.
- return PickVisualMedia().createIntent(context, request)
+ if(input.options.selectionLimit == 1) {
+ return intent
}
- if (selectionLimit > 1) {
- return PickMultipleVisualMedia(selectionLimit).createIntent(context, request)
- }
-
- // If the selection limit is 0, it is the same as unlimited selection.
- if (selectionLimit == UNLIMITED_SELECTION) {
- return PickMultipleVisualMedia().createIntent(context, request)
- }
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
- return PickVisualMedia().createIntent(context, request)
+ return intent
}
override fun parseResult(input: ImageLibraryContractOptions, resultCode: Int, intent: Intent?) =
@@ -0,0 +1,3 @@
added by https://github.com/bluesky-social/social-app/pull/2384#pullrequestreview-1800985521
hackfixes the image picker on android so that the user can select from their typical image sources
+9
View File
@@ -74,6 +74,7 @@ import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
import {SavedFeeds} from 'view/screens/SavedFeeds'
import {PreferencesHomeFeed} from 'view/screens/PreferencesHomeFeed'
import {PreferencesThreads} from 'view/screens/PreferencesThreads'
import {PreferencesExternalEmbeds} from '#/view/screens/PreferencesExternalEmbeds'
import {createNativeStackNavigatorWithAuth} from './view/shell/createNativeStackNavigatorWithAuth'
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
@@ -243,6 +244,14 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
getComponent={() => PreferencesThreads}
options={{title: title('Threads Preferences'), requireAuth: true}}
/>
<Stack.Screen
name="PreferencesExternalEmbeds"
getComponent={() => PreferencesExternalEmbeds}
options={{
title: title('External Media Preferences'),
requireAuth: true,
}}
/>
</>
)
}
+151 -63
View File
@@ -1,5 +1,11 @@
import React, {useCallback, useEffect} from 'react'
import {View, StyleSheet, Image as RNImage} from 'react-native'
import {
View,
StyleSheet,
Image as RNImage,
AccessibilityInfo,
useColorScheme,
} from 'react-native'
import * as SplashScreen from 'expo-splash-screen'
import {Image} from 'expo-image'
import Animated, {
@@ -14,9 +20,18 @@ import MaskedView from '@react-native-masked-view/masked-view'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import Svg, {Path, SvgProps} from 'react-native-svg'
import {isAndroid} from '#/platform/detection'
import {useColorMode} from 'state/shell'
import {colors} from '#/lib/styles'
// @ts-ignore
import splashImagePointer from '../assets/splash.png'
// @ts-ignore
import darkSplashImagePointer from '../assets/splash-dark.png'
const splashImageUri = RNImage.resolveAssetSource(splashImagePointer).uri
const darkSplashImageUri = RNImage.resolveAssetSource(
darkSplashImagePointer,
).uri
export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
const width = 1000
@@ -27,9 +42,9 @@ export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
// @ts-ignore it's fiiiiine
ref={ref}
viewBox="0 0 64 66"
style={{width, height}}>
style={[{width, height}, props.style]}>
<Path
fill="#fff"
fill={props.fill || '#fff'}
d="M13.873 3.77C21.21 9.243 29.103 20.342 32 26.3v15.732c0-.335-.13.043-.41.858-1.512 4.414-7.418 21.642-20.923 7.87-7.111-7.252-3.819-14.503 9.125-16.692-7.405 1.252-15.73-.817-18.014-8.93C1.12 22.804 0 8.431 0 6.488 0-3.237 8.579-.18 13.873 3.77ZM50.127 3.77C42.79 9.243 34.897 20.342 32 26.3v15.732c0-.335.13.043.41.858 1.512 4.414 7.418 21.642 20.923 7.87 7.111-7.252 3.819-14.503-9.125-16.692 7.405 1.252 15.73-.817 18.014-8.93C62.88 22.804 64 8.431 64 6.488 64-3.237 55.422-.18 50.127 3.77Z"
/>
</Svg>
@@ -50,9 +65,22 @@ export function Splash(props: React.PropsWithChildren<Props>) {
const outroAppOpacity = useSharedValue(0)
const [isAnimationComplete, setIsAnimationComplete] = React.useState(false)
const [isImageLoaded, setIsImageLoaded] = React.useState(false)
const isReady = props.isReady && isImageLoaded
const [isLayoutReady, setIsLayoutReady] = React.useState(false)
const [reduceMotion, setReduceMotion] = React.useState<boolean | undefined>(
false,
)
const isReady =
props.isReady &&
isImageLoaded &&
isLayoutReady &&
reduceMotion !== undefined
const logoAnimations = useAnimatedStyle(() => {
const colorMode = useColorMode()
const colorScheme = useColorScheme()
const themeName = colorMode === 'system' ? colorScheme : colorMode
const isDarkMode = themeName === 'dark'
const logoAnimation = useAnimatedStyle(() => {
return {
transform: [
{
@@ -62,7 +90,7 @@ export function Splash(props: React.PropsWithChildren<Props>) {
scale: interpolate(
outroLogo.value,
[0, 0.08, 1],
[1, 0.8, 400],
[1, 0.8, 500],
'clamp',
),
},
@@ -70,6 +98,27 @@ export function Splash(props: React.PropsWithChildren<Props>) {
opacity: interpolate(intro.value, [0, 1], [0, 1], 'clamp'),
}
})
const reducedLogoAnimation = useAnimatedStyle(() => {
return {
transform: [
{
scale: interpolate(intro.value, [0, 1], [0.8, 1], 'clamp'),
},
],
opacity: interpolate(intro.value, [0, 1], [0, 1], 'clamp'),
}
})
const logoWrapperAnimation = useAnimatedStyle(() => {
return {
opacity: interpolate(
outroAppOpacity.value,
[0, 0.1, 0.2, 1],
[1, 1, 0, 0],
'clamp',
),
}
})
const appAnimation = useAnimatedStyle(() => {
return {
@@ -80,7 +129,7 @@ export function Splash(props: React.PropsWithChildren<Props>) {
],
opacity: interpolate(
outroAppOpacity.value,
[0, 0.08, 0.15, 1],
[0, 0.1, 0.2, 1],
[0, 0, 1, 1],
'clamp',
),
@@ -88,82 +137,121 @@ export function Splash(props: React.PropsWithChildren<Props>) {
})
const onFinish = useCallback(() => setIsAnimationComplete(true), [])
const onLayout = useCallback(() => setIsLayoutReady(true), [])
const onLoadEnd = useCallback(() => setIsImageLoaded(true), [])
useEffect(() => {
if (isReady) {
// hide on mount
SplashScreen.hideAsync().catch(() => {})
intro.value = withTiming(
1,
{duration: 400, easing: Easing.out(Easing.cubic)},
async () => {
// set these values to check animation at specific point
// outroLogo.value = 0.1
// outroApp.value = 0.1
outroLogo.value = withTiming(
SplashScreen.hideAsync()
.then(() => {
intro.value = withTiming(
1,
{duration: 1200, easing: Easing.in(Easing.cubic)},
() => {
runOnJS(onFinish)()
{duration: 400, easing: Easing.out(Easing.cubic)},
async () => {
// set these values to check animation at specific point
// outroLogo.value = 0.1
// outroApp.value = 0.1
outroLogo.value = withTiming(
1,
{duration: 1200, easing: Easing.in(Easing.cubic)},
() => {
runOnJS(onFinish)()
},
)
outroApp.value = withTiming(1, {
duration: 1200,
easing: Easing.inOut(Easing.cubic),
})
outroAppOpacity.value = withTiming(1, {
duration: 1200,
easing: Easing.in(Easing.cubic),
})
},
)
outroApp.value = withTiming(1, {
duration: 1200,
easing: Easing.inOut(Easing.cubic),
})
outroAppOpacity.value = withTiming(1, {
duration: 1200,
easing: Easing.in(Easing.cubic),
})
},
)
})
.catch(() => {})
}
}, [onFinish, intro, outroLogo, outroApp, outroAppOpacity, isReady])
const onLoadEnd = useCallback(() => {
setIsImageLoaded(true)
}, [setIsImageLoaded])
useEffect(() => {
AccessibilityInfo.isReduceMotionEnabled().then(setReduceMotion)
}, [])
const logoAnimations =
reduceMotion === true ? reducedLogoAnimation : logoAnimation
return (
<View style={{flex: 1}}>
<View style={{flex: 1}} onLayout={onLayout}>
{!isAnimationComplete && (
<Image
accessibilityIgnoresInvertColors
onLoadEnd={onLoadEnd}
source={{uri: splashImageUri}}
source={{uri: isDarkMode ? darkSplashImageUri : splashImageUri}}
style={StyleSheet.absoluteFillObject}
/>
)}
<MaskedView
style={[StyleSheet.absoluteFillObject]}
maskElement={
<Animated.View
style={[
StyleSheet.absoluteFillObject,
{
// Transparent background because mask is based off alpha channel.
backgroundColor: 'transparent',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
transform: [{translateY: -(insets.top / 2)}, {scale: 0.1}], // scale from 1000px to 100px
},
]}>
<AnimatedLogo style={[logoAnimations]} />
</Animated.View>
}>
{!isAnimationComplete && (
<View
style={[StyleSheet.absoluteFillObject, {backgroundColor: 'white'}]}
/>
)}
{isReady &&
(isAndroid || reduceMotion === true ? (
// Use a simple fade on older versions of android (work around a bug)
<>
<Animated.View style={[{flex: 1}, appAnimation]}>
{props.children}
</Animated.View>
<Animated.View style={[{flex: 1}, appAnimation]}>
{props.children}
</Animated.View>
</MaskedView>
{!isAnimationComplete && (
<Animated.View
style={[
StyleSheet.absoluteFillObject,
logoWrapperAnimation,
{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
transform: [{translateY: -(insets.top / 2)}, {scale: 0.1}], // scale from 1000px to 100px
},
]}>
<AnimatedLogo
fill={isDarkMode ? colors.blue3 : '#fff'}
style={[{opacity: 0}, logoAnimations]}
/>
</Animated.View>
)}
</>
) : (
<MaskedView
style={[StyleSheet.absoluteFillObject]}
maskElement={
<Animated.View
style={[
{
// Transparent background because mask is based off alpha channel.
backgroundColor: 'transparent',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
transform: [{translateY: -(insets.top / 2)}, {scale: 0.1}], // scale from 1000px to 100px
},
]}>
<AnimatedLogo
fill={isDarkMode ? colors.blue3 : '#fff'}
style={[logoAnimations]}
/>
</Animated.View>
}>
{!isAnimationComplete && (
<View
style={[
StyleSheet.absoluteFillObject,
{backgroundColor: isDarkMode ? colors.blue3 : '#fff'},
]}
/>
)}
<Animated.View style={[{flex: 1}, appAnimation]}>
{props.children}
</Animated.View>
</MaskedView>
))}
</View>
)
}
+1
View File
@@ -147,6 +147,7 @@ interface ScreenPropertiesMap {
Settings: {}
AppPasswords: {}
Moderation: {}
PreferencesExternalEmbeds: {}
BlockedAccounts: {}
MutedAccounts: {}
SavedFeeds: {}
+1 -1
View File
@@ -98,7 +98,7 @@ export class MergeFeedAPI implements FeedAPI {
}
return {
cursor: posts.length ? String(this.itemCursor) : undefined,
cursor: String(this.itemCursor),
feed: posts,
}
}
+5 -4
View File
@@ -41,7 +41,7 @@ export function IS_LOCAL_DEV(url: string) {
}
export function IS_STAGING(url: string) {
return !IS_LOCAL_DEV(url) && !IS_PROD(url)
return url.startsWith('https://staging.bsky.dev')
}
export function IS_PROD(url: string) {
@@ -51,7 +51,8 @@ export function IS_PROD(url: string) {
// -prf
return (
url.startsWith('https://bsky.social') ||
url.startsWith('https://api.bsky.app')
url.startsWith('https://api.bsky.app') ||
/bsky\.network\/?$/.test(url)
)
}
@@ -116,8 +117,8 @@ export async function DEFAULT_FEEDS(
} else {
// production
return {
pinned: [],
saved: [],
pinned: [PROD_DEFAULT_FEED('whats-hot')],
saved: [PROD_DEFAULT_FEED('whats-hot')],
}
}
}
+8
View File
@@ -2,6 +2,7 @@ import {BskyAgent} from '@atproto/api'
import {isBskyAppUrl} from '../strings/url-helpers'
import {extractBskyMeta} from './bsky'
import {LINK_META_PROXY} from 'lib/constants'
import {getGiphyMetaUri} from 'lib/strings/embed-player'
export enum LikelyType {
HTML,
@@ -34,6 +35,13 @@ export async function getLinkMeta(
let urlp
try {
urlp = new URL(url)
// Get Giphy meta uri if this is any form of giphy link
const giphyMetaUri = getGiphyMetaUri(urlp)
if (giphyMetaUri) {
url = giphyMetaUri
urlp = new URL(url)
}
} catch (e) {
return {
error: 'Invalid URL',
+4 -6
View File
@@ -117,9 +117,6 @@ function createResizedImage(
return reject(new Error('Failed to resize image'))
}
canvas.width = width
canvas.height = height
let scale = 1
if (mode === 'cover') {
scale = img.width < img.height ? width / img.width : height / img.height
@@ -128,10 +125,11 @@ function createResizedImage(
}
let w = img.width * scale
let h = img.height * scale
let x = (width - w) / 2
let y = (height - h) / 2
ctx.drawImage(img, x, y, w, h)
canvas.width = w
canvas.height = h
ctx.drawImage(img, 0, 0, w, h)
resolve(canvas.toDataURL('image/jpeg', quality))
})
img.src = dataUri
+6 -1
View File
@@ -4,6 +4,7 @@ import {
MediaTypeOptions,
} from 'expo-image-picker'
import {getDataUriSize} from './util'
import * as Toast from 'view/com/util/Toast'
export async function openPicker(opts?: ImagePickerOptions) {
const response = await launchImageLibraryAsync({
@@ -13,7 +14,11 @@ export async function openPicker(opts?: ImagePickerOptions) {
...opts,
})
return (response.assets ?? []).map(image => ({
if (response.assets && response.assets.length > 4) {
Toast.show('You may only select up to 4 images')
}
return (response.assets ?? []).slice(0, 4).map(image => ({
mime: 'image/jpeg',
height: image.height,
width: image.width,
+1
View File
@@ -32,6 +32,7 @@ export type CommonNavigatorParams = {
SavedFeeds: undefined
PreferencesHomeFeed: undefined
PreferencesThreads: undefined
PreferencesExternalEmbeds: undefined
}
export type BottomTabNavigatorParams = CommonNavigatorParams & {
+297 -46
View File
@@ -1,17 +1,59 @@
import {Platform} from 'react-native'
import {Dimensions, Platform} from 'react-native'
const {height: SCREEN_HEIGHT} = Dimensions.get('window')
export type EmbedPlayerParams =
| {type: 'youtube_video'; videoId: string; playerUri: string}
| {type: 'twitch_live'; channelId: string; playerUri: string}
| {type: 'spotify_album'; albumId: string; playerUri: string}
| {
type: 'spotify_playlist'
playlistId: string
playerUri: string
}
| {type: 'spotify_song'; songId: string; playerUri: string}
| {type: 'soundcloud_track'; user: string; track: string; playerUri: string}
| {type: 'soundcloud_set'; user: string; set: string; playerUri: string}
export const embedPlayerSources = [
'youtube',
'youtubeShorts',
'twitch',
'spotify',
'soundcloud',
'appleMusic',
'vimeo',
'giphy',
'tenor',
] as const
export type EmbedPlayerSource = (typeof embedPlayerSources)[number]
export type EmbedPlayerType =
| 'youtube_video'
| 'youtube_short'
| 'twitch_video'
| 'spotify_album'
| 'spotify_playlist'
| 'spotify_song'
| 'soundcloud_track'
| 'soundcloud_set'
| 'apple_music_playlist'
| 'apple_music_album'
| 'apple_music_song'
| 'vimeo_video'
| 'giphy_gif'
| 'tenor_gif'
export const externalEmbedLabels: Record<EmbedPlayerSource, string> = {
youtube: 'YouTube',
youtubeShorts: 'YouTube Shorts',
vimeo: 'Vimeo',
twitch: 'Twitch',
giphy: 'GIPHY',
tenor: 'Tenor',
spotify: 'Spotify',
appleMusic: 'Apple Music',
soundcloud: 'SoundCloud',
}
export interface EmbedPlayerParams {
type: EmbedPlayerType
playerUri: string
isGif?: boolean
source: EmbedPlayerSource
metaUri?: string
hideDetails?: boolean
}
const giphyRegex = /media(?:[0-4]\.giphy\.com|\.giphy\.com)/i
const gifFilenameRegex = /^(\S+)\.(webp|gif|mp4)$/i
export function parseEmbedPlayerFromUrl(
url: string,
@@ -29,63 +71,88 @@ export function parseEmbedPlayerFromUrl(
if (videoId) {
return {
type: 'youtube_video',
videoId,
playerUri: `https://www.youtube.com/embed/${videoId}?autoplay=1`,
source: 'youtube',
playerUri: `https://www.youtube.com/embed/${videoId}?autoplay=1&playsinline=1`,
}
}
}
if (urlp.hostname === 'www.youtube.com' || urlp.hostname === 'youtube.com') {
if (
urlp.hostname === 'www.youtube.com' ||
urlp.hostname === 'youtube.com' ||
urlp.hostname === 'm.youtube.com'
) {
const [_, page, shortVideoId] = urlp.pathname.split('/')
const videoId =
page === 'shorts' ? shortVideoId : (urlp.searchParams.get('v') as string)
if (videoId) {
return {
type: 'youtube_video',
videoId,
playerUri: `https://www.youtube.com/embed/${videoId}?autoplay=1`,
type: page === 'shorts' ? 'youtube_short' : 'youtube_video',
source: page === 'shorts' ? 'youtubeShorts' : 'youtube',
hideDetails: page === 'shorts' ? true : undefined,
playerUri: `https://www.youtube.com/embed/${videoId}?autoplay=1&playsinline=1`,
}
}
}
// twitch
if (urlp.hostname === 'twitch.tv' || urlp.hostname === 'www.twitch.tv') {
if (
urlp.hostname === 'twitch.tv' ||
urlp.hostname === 'www.twitch.tv' ||
urlp.hostname === 'm.twitch.tv'
) {
const parent =
Platform.OS === 'web' ? window.location.hostname : 'localhost'
const parts = urlp.pathname.split('/')
if (parts.length === 2 && parts[1]) {
const [_, channelOrVideo, clipOrId, id] = urlp.pathname.split('/')
if (channelOrVideo === 'videos') {
return {
type: 'twitch_live',
channelId: parts[1],
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=${parts[1]}&parent=${parent}`,
type: 'twitch_video',
source: 'twitch',
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&video=${clipOrId}&parent=${parent}`,
}
} else if (clipOrId === 'clip') {
return {
type: 'twitch_video',
source: 'twitch',
playerUri: `https://clips.twitch.tv/embed?volume=0.5&autoplay=true&clip=${id}&parent=${parent}`,
}
} else if (channelOrVideo) {
return {
type: 'twitch_video',
source: 'twitch',
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=${channelOrVideo}&parent=${parent}`,
}
}
}
// spotify
if (urlp.hostname === 'open.spotify.com') {
const [_, type, id] = urlp.pathname.split('/')
if (type && id) {
if (type === 'playlist') {
const [_, typeOrLocale, idOrType, id] = urlp.pathname.split('/')
if (idOrType) {
if (typeOrLocale === 'playlist' || idOrType === 'playlist') {
return {
type: 'spotify_playlist',
playlistId: id,
playerUri: `https://open.spotify.com/embed/playlist/${id}`,
source: 'spotify',
playerUri: `https://open.spotify.com/embed/playlist/${
id ?? idOrType
}`,
}
}
if (type === 'album') {
if (typeOrLocale === 'album' || idOrType === 'album') {
return {
type: 'spotify_album',
albumId: id,
playerUri: `https://open.spotify.com/embed/album/${id}`,
source: 'spotify',
playerUri: `https://open.spotify.com/embed/album/${id ?? idOrType}`,
}
}
if (type === 'track') {
if (typeOrLocale === 'track' || idOrType === 'track') {
return {
type: 'spotify_song',
songId: id,
playerUri: `https://open.spotify.com/embed/track/${id}`,
source: 'spotify',
playerUri: `https://open.spotify.com/embed/track/${id ?? idOrType}`,
}
}
}
@@ -102,20 +169,173 @@ export function parseEmbedPlayerFromUrl(
if (trackOrSets === 'sets' && set) {
return {
type: 'soundcloud_set',
user,
set: set,
source: 'soundcloud',
playerUri: `https://w.soundcloud.com/player/?url=${url}&auto_play=true&visual=false&hide_related=true`,
}
}
return {
type: 'soundcloud_track',
user,
track: trackOrSets,
source: 'soundcloud',
playerUri: `https://w.soundcloud.com/player/?url=${url}&auto_play=true&visual=false&hide_related=true`,
}
}
}
if (
urlp.hostname === 'music.apple.com' ||
urlp.hostname === 'music.apple.com'
) {
// This should always have: locale, type (playlist or album), name, and id. We won't use spread since we want
// to check if the length is correct
const pathParams = urlp.pathname.split('/')
const type = pathParams[2]
const songId = urlp.searchParams.get('i')
if (pathParams.length === 5 && (type === 'playlist' || type === 'album')) {
// We want to append the songId to the end of the url if it exists
const embedUri = `https://embed.music.apple.com${urlp.pathname}${
urlp.search ? '?i=' + songId : ''
}`
if (type === 'playlist') {
return {
type: 'apple_music_playlist',
source: 'appleMusic',
playerUri: embedUri,
}
} else if (type === 'album') {
if (songId) {
return {
type: 'apple_music_song',
source: 'appleMusic',
playerUri: embedUri,
}
} else {
return {
type: 'apple_music_album',
source: 'appleMusic',
playerUri: embedUri,
}
}
}
}
}
if (urlp.hostname === 'vimeo.com' || urlp.hostname === 'www.vimeo.com') {
const [_, videoId] = urlp.pathname.split('/')
if (videoId) {
return {
type: 'vimeo_video',
source: 'vimeo',
playerUri: `https://player.vimeo.com/video/${videoId}?autoplay=1`,
}
}
}
if (urlp.hostname === 'giphy.com' || urlp.hostname === 'www.giphy.com') {
const [_, gifs, nameAndId] = urlp.pathname.split('/')
/*
* nameAndId is a string that consists of the name (dash separated) and the id of the gif (the last part of the name)
* We want to get the id of the gif, then direct to media.giphy.com/media/{id}/giphy.webp so we can
* use it in an <Image> component
*/
if (gifs === 'gifs' && nameAndId) {
const gifId = nameAndId.split('-').pop()
if (gifId) {
return {
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: `https://giphy.com/gifs/${gifId}`,
playerUri: `https://i.giphy.com/media/${gifId}/giphy.webp`,
}
}
}
}
// There are five possible hostnames that also can be giphy urls: media.giphy.com and media0-4.giphy.com
// These can include (presumably) a tracking id in the path name, so we have to check for that as well
if (giphyRegex.test(urlp.hostname)) {
// We can link directly to the gif, if its a proper link
const [_, media, trackingOrId, idOrFilename, filename] =
urlp.pathname.split('/')
if (media === 'media') {
if (idOrFilename && gifFilenameRegex.test(idOrFilename)) {
return {
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: `https://giphy.com/gifs/${trackingOrId}`,
playerUri: `https://i.giphy.com/media/${trackingOrId}/giphy.webp`,
}
} else if (filename && gifFilenameRegex.test(filename)) {
return {
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: `https://giphy.com/gifs/${idOrFilename}`,
playerUri: `https://i.giphy.com/media/${idOrFilename}/giphy.webp`,
}
}
}
}
// Finally, we should see if it is a link to i.giphy.com. These links don't necessarily end in .gif but can also
// be .webp
if (urlp.hostname === 'i.giphy.com' || urlp.hostname === 'www.i.giphy.com') {
const [_, mediaOrFilename, filename] = urlp.pathname.split('/')
if (mediaOrFilename === 'media' && filename) {
const gifId = filename.split('.')[0]
return {
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: `https://giphy.com/gifs/${gifId}`,
playerUri: `https://i.giphy.com/media/${gifId}/giphy.webp`,
}
} else if (mediaOrFilename) {
const gifId = mediaOrFilename.split('.')[0]
return {
type: 'giphy_gif',
source: 'giphy',
isGif: true,
hideDetails: true,
metaUri: `https://giphy.com/gifs/${gifId}`,
playerUri: `https://i.giphy.com/media/${
mediaOrFilename.split('.')[0]
}/giphy.webp`,
}
}
}
if (urlp.hostname === 'tenor.com' || urlp.hostname === 'www.tenor.com') {
const [_, pathOrIntl, pathOrFilename, intlFilename] =
urlp.pathname.split('/')
const isIntl = pathOrFilename === 'view'
const filename = isIntl ? intlFilename : pathOrFilename
if ((pathOrIntl === 'view' || pathOrFilename === 'view') && filename) {
const includesExt = filename.split('.').pop() === 'gif'
return {
type: 'tenor_gif',
source: 'tenor',
isGif: true,
hideDetails: true,
playerUri: `${url}${!includesExt ? '.gif' : ''}`,
}
}
}
}
export function getPlayerHeight({
@@ -131,22 +351,53 @@ export function getPlayerHeight({
switch (type) {
case 'youtube_video':
case 'twitch_live':
case 'twitch_video':
case 'vimeo_video':
return (width / 16) * 9
case 'youtube_short':
if (SCREEN_HEIGHT < 600) {
return ((width / 9) * 16) / 1.75
} else {
return ((width / 9) * 16) / 1.5
}
case 'spotify_album':
return 380
case 'apple_music_album':
case 'apple_music_playlist':
case 'spotify_playlist':
return 360
case 'soundcloud_set':
return 380
case 'spotify_song':
if (width <= 300) {
return 180
return 155
}
return 232
case 'soundcloud_track':
return 165
case 'soundcloud_set':
return 360
case 'apple_music_song':
return 150
default:
return width
}
}
export function getGifDims(
originalHeight: number,
originalWidth: number,
viewWidth: number,
) {
const scaledHeight = (originalHeight / originalWidth) * viewWidth
return {
height: scaledHeight > 250 ? 250 : scaledHeight,
width: (250 / scaledHeight) * viewWidth,
}
}
export function getGiphyMetaUri(url: URL) {
if (giphyRegex.test(url.hostname) || url.hostname === 'i.giphy.com') {
const params = parseEmbedPlayerFromUrl(url.toString())
if (params && params.type === 'giphy_gif') {
return params.metaUri
}
}
}
+1
View File
@@ -167,6 +167,7 @@ export const s = StyleSheet.create({
flexGrow1: {flexGrow: 1},
alignCenter: {alignItems: 'center'},
alignBaseline: {alignItems: 'baseline'},
justifyCenter: {justifyContent: 'center'},
// position
absolute: {position: 'absolute'},
+2
View File
@@ -25,6 +25,7 @@ export const defaultTheme: Theme = {
postCtrl: '#71768A',
brandText: '#0066FF',
emptyStateIcon: '#B6B6C9',
borderLinkHover: '#cac1c1',
},
primary: {
background: colors.blue3,
@@ -310,6 +311,7 @@ export const darkTheme: Theme = {
postCtrl: '#707489',
brandText: '#0085ff',
emptyStateIcon: colors.gray4,
borderLinkHover: colors.gray5,
},
primary: {
...defaultTheme.palette.primary,
+1
View File
@@ -5,6 +5,7 @@ import {AppLanguage} from '#/locale/languages'
test('sanitizeAppLanguageSetting', () => {
expect(sanitizeAppLanguageSetting('en')).toBe(AppLanguage.en)
expect(sanitizeAppLanguageSetting('pt-BR')).toBe(AppLanguage.pt_BR)
expect(sanitizeAppLanguageSetting('hi')).toBe(AppLanguage.hi)
expect(sanitizeAppLanguageSetting('foo')).toBe(AppLanguage.en)
expect(sanitizeAppLanguageSetting('en,foo')).toBe(AppLanguage.en)
+14 -8
View File
@@ -110,18 +110,24 @@ export function sanitizeAppLanguageSetting(appLanguage: string): AppLanguage {
switch (lang) {
case 'en':
return AppLanguage.en
case 'hi':
return AppLanguage.hi
case 'ja':
return AppLanguage.ja
case 'fr':
return AppLanguage.fr
// DISABLED until this translation is fixed -prf
// case 'de':
// return AppLanguage.de
// DISABLED until this translation is more thoroughly reviewed -prf
// case 'es':
// return AppLanguage.es
case 'es':
return AppLanguage.es
case 'fr':
return AppLanguage.fr
case 'hi':
return AppLanguage.hi
case 'ja':
return AppLanguage.ja
case 'ko':
return AppLanguage.ko
case 'pt-BR':
return AppLanguage.pt_BR
case 'uk':
return AppLanguage.uk
default:
continue
}
+30 -17
View File
@@ -3,13 +3,15 @@ import {i18n} from '@lingui/core'
import {useLanguagePrefs} from '#/state/preferences'
import {messages as messagesEn} from '#/locale/locales/en/messages'
import {messages as messagesHi} from '#/locale/locales/hi/messages'
import {messages as messagesJa} from '#/locale/locales/ja/messages'
import {messages as messagesFr} from '#/locale/locales/fr/messages'
// DISABLED until this translation is fixed -prf
// import {messages as messagesDe} from '#/locale/locales/de/messages'
// DISABLED until this translation is more thoroughly reviewed -prf
// import {messages as messagesEs} from '#/locale/locales/es/messages'
import {messages as messagesEs} from '#/locale/locales/es/messages'
import {messages as messagesFr} from '#/locale/locales/fr/messages'
import {messages as messagesHi} from '#/locale/locales/hi/messages'
import {messages as messagesJa} from '#/locale/locales/ja/messages'
import {messages as messagesKo} from '#/locale/locales/ko/messages'
import {messages as messagesPt_BR} from '#/locale/locales/pt-BR/messages'
import {messages as messagesUk} from '#/locale/locales/uk/messages'
import {sanitizeAppLanguageSetting} from '#/locale/helpers'
import {AppLanguage} from '#/locale/languages'
@@ -19,6 +21,19 @@ import {AppLanguage} from '#/locale/languages'
*/
export async function dynamicActivate(locale: AppLanguage) {
switch (locale) {
// DISABLED until this translation is fixed -prf
// case AppLanguage.de: {
// i18n.loadAndActivate({locale, messages: messagesDe})
// break
// }
case AppLanguage.es: {
i18n.loadAndActivate({locale, messages: messagesEs})
break
}
case AppLanguage.fr: {
i18n.loadAndActivate({locale, messages: messagesFr})
break
}
case AppLanguage.hi: {
i18n.loadAndActivate({locale, messages: messagesHi})
break
@@ -27,20 +42,18 @@ export async function dynamicActivate(locale: AppLanguage) {
i18n.loadAndActivate({locale, messages: messagesJa})
break
}
case AppLanguage.fr: {
i18n.loadAndActivate({locale, messages: messagesFr})
case AppLanguage.ko: {
i18n.loadAndActivate({locale, messages: messagesKo})
break
}
case AppLanguage.pt_BR: {
i18n.loadAndActivate({locale, messages: messagesPt_BR})
break
}
case AppLanguage.uk: {
i18n.loadAndActivate({locale, messages: messagesUk})
break
}
// DISABLED until this translation is fixed -prf
// case AppLanguage.de: {
// i18n.loadAndActivate({locale, messages: messagesDe})
// break
// }
// DISABLED until this translation is more thoroughly reviewed -prf
// case AppLanguage.es: {
// i18n.loadAndActivate({locale, messages: messagesEs})
// break
// }
default: {
i18n.loadAndActivate({locale, messages: messagesEn})
break
+23 -12
View File
@@ -12,6 +12,19 @@ export async function dynamicActivate(locale: AppLanguage) {
let mod: any
switch (locale) {
// DISABLED until this translation is fixed -prf
// case AppLanguage.de: {
// mod = await import(`./locales/de/messages`)
// break
// }
case AppLanguage.es: {
mod = await import(`./locales/es/messages`)
break
}
case AppLanguage.fr: {
mod = await import(`./locales/fr/messages`)
break
}
case AppLanguage.hi: {
mod = await import(`./locales/hi/messages`)
break
@@ -20,20 +33,18 @@ export async function dynamicActivate(locale: AppLanguage) {
mod = await import(`./locales/ja/messages`)
break
}
case AppLanguage.fr: {
mod = await import(`./locales/fr/messages`)
case AppLanguage.ko: {
mod = await import(`./locales/ko/messages`)
break
}
case AppLanguage.pt_BR: {
mod = await import(`./locales/pt-BR/messages`)
break
}
case AppLanguage.uk: {
mod = await import(`./locales/uk/messages`)
break
}
// DISABLED until this translation is fixed -prf
// case AppLanguage.de: {
// mod = await import(`./locales/de/messages`)
// break
// }
// DISABLED until this translation is more thoroughly reviewed -prf
// case AppLanguage.es: {
// mod = await import(`./locales/es/messages`)
// break
// }
default: {
mod = await import(`./locales/en/messages`)
break
+14 -10
View File
@@ -6,13 +6,15 @@ interface Language {
export enum AppLanguage {
en = 'en',
hi = 'hi',
ja = 'ja',
fr = 'fr',
// DISABLED until this translation is fixed -prf
// de = 'de',
// DISABLED until this translation is more thoroughly reviewed -prf
// es = 'es',
es = 'es',
fr = 'fr',
hi = 'hi',
ja = 'ja',
ko = 'ko',
pt_BR = 'pt-BR',
uk = 'uk',
}
interface AppLanguageConfig {
@@ -22,13 +24,15 @@ interface AppLanguageConfig {
export const APP_LANGUAGES: AppLanguageConfig[] = [
{code2: AppLanguage.en, name: 'English'},
{code2: AppLanguage.hi, name: 'हिंदी'},
{code2: AppLanguage.ja, name: '日本語'},
{code2: AppLanguage.fr, name: 'Français'},
// DISABLED until this translation is fixed -prf
// {code2: AppLanguage.de, name: 'Deutsch'},
// DISABLED until this translation is more thoroughly reviewed -prf
// {code2: AppLanguage.es, name: 'Español'},
{code2: AppLanguage.es, name: 'Español'},
{code2: AppLanguage.fr, name: 'Français'},
{code2: AppLanguage.hi, name: 'हिंदी'},
{code2: AppLanguage.ja, name: '日本語'},
{code2: AppLanguage.ko, name: '한국어'},
{code2: AppLanguage.pt_BR, name: 'Português (BR)'},
{code2: AppLanguage.uk, name: 'Українська'},
]
export const LANGUAGES: Language[] = [
+182 -92
View File
@@ -68,7 +68,7 @@ msgstr "Eine neue Version der App ist verfügbar. Bitte aktualisieren Sie die Ap
msgid "Accessibility"
msgstr "Zugänglichkeit"
#: src/view/com/auth/login/LoginForm.tsx:159
#: src/view/com/auth/login/LoginForm.tsx:163
#: src/view/screens/Settings.tsx:286
msgid "Account"
msgstr "Konto"
@@ -98,6 +98,7 @@ msgstr "Konto hinzufügen"
#: src/view/com/composer/photos/Gallery.tsx:119
#: src/view/com/composer/photos/Gallery.tsx:180
#: src/view/com/modals/AltImage.tsx:93
msgid "Add alt text"
msgstr "Alt Text hinzufügen"
@@ -110,11 +111,11 @@ msgstr "Einzelheiten hinzufügen"
msgid "Add details to report"
msgstr "Einzelheiten zum Bericht hinzufügen"
#: src/view/com/composer/Composer.tsx:442
#: src/view/com/composer/Composer.tsx:447
msgid "Add link card"
msgstr "Link Karte hinzufügen"
#: src/view/com/composer/Composer.tsx:445
#: src/view/com/composer/Composer.tsx:450
msgid "Add link card:"
msgstr "Link Karte hinzufügen:"
@@ -135,7 +136,7 @@ msgstr "Zu meinen Feeds hinzufügen"
msgid "Added to list"
msgstr "Den Listen hinzufügen"
#: src/view/screens/PreferencesHomeFeed.tsx:164
#: src/view/screens/PreferencesHomeFeed.tsx:170
msgid "Adjust the number of likes a reply must have to be shown in your feed."
msgstr "Passen Sie die Anzahl der Likes an, die eine Antwort haben muss, um in Ihrem Feed angezeigt zu werden."
@@ -143,7 +144,7 @@ msgstr "Passen Sie die Anzahl der Likes an, die eine Antwort haben muss, um in I
msgid "Adult Content"
msgstr "Inhalt für Erwachsene"
#: src/view/screens/Settings.tsx:569
#: src/view/screens/Settings.tsx:602
msgid "Advanced"
msgstr "Fortgeschrittene"
@@ -176,7 +177,7 @@ msgstr "und"
msgid "App Language"
msgstr "App Sprache"
#: src/view/screens/Settings.tsx:589
#: src/view/screens/Settings.tsx:622
msgid "App passwords"
msgstr "App-Passwörter"
@@ -212,7 +213,7 @@ msgstr "Aussehen"
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr "Sind Sie sicher, dass Sie das App-Passwort \"{name}\" löschen möchten?"
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Are you sure you'd like to discard this draft?"
msgstr "Sind Sie sicher, dass Sie diesen Entwurf verwerfen möchten?"
@@ -231,7 +232,7 @@ msgstr "Künstlerische oder nicht-erotische Nacktheit."
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:250
#: src/view/com/auth/login/LoginForm.tsx:254
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
#: src/view/com/modals/report/InputIssueDetails.tsx:46
#: src/view/com/post-thread/PostThread.tsx:388
@@ -327,7 +328,7 @@ msgstr "Bluesky wird dein Profil und deine Beiträge nicht für abgemeldete Benu
msgid "Bluesky.Social"
msgstr "Bluesky.Social"
#: src/view/screens/Settings.tsx:718
#: src/view/screens/Settings.tsx:751
msgid "Build version {0} {1}"
msgstr "Version bauen {0} {1}"
@@ -345,9 +346,8 @@ msgstr "Kamera"
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr "Darf nur Buchstaben, Zahlen, Leerzeichen, Bindestriche und Unterstriche enthalten. Muss mindestens 4 Zeichen lang sein, darf aber nicht länger als 32 Zeichen sein."
#: src/view/com/composer/Composer.tsx:289
#: src/view/com/composer/Composer.tsx:292
#: src/view/com/modals/AltImage.tsx:128
#: src/view/com/composer/Composer.tsx:294
#: src/view/com/composer/Composer.tsx:297
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
#: src/view/com/modals/Confirm.tsx:88
@@ -371,8 +371,8 @@ msgid "Cancel account deletion"
msgstr "Kontolöschung abbrechen"
#: src/view/com/modals/AltImage.tsx:123
msgid "Cancel add image alt text"
msgstr "Abbrechen Bild-Alt-Text hinzufügen"
#~ msgid "Cancel add image alt text"
#~ msgstr "Abbrechen Bild-Alt-Text hinzufügen"
#: src/view/com/modals/ChangeHandle.tsx:149
msgid "Cancel change handle"
@@ -403,8 +403,8 @@ msgstr "Anmeldung zur Warteliste abbrechen"
msgid "Change"
msgstr "Ändern"
#: src/view/screens/Settings.tsx:601
#: src/view/screens/Settings.tsx:610
#: src/view/screens/Settings.tsx:634
#: src/view/screens/Settings.tsx:643
msgid "Change handle"
msgstr "Änderungsgriff andern"
@@ -448,19 +448,19 @@ msgstr "Wählen Sie die Algorithmen, die Ihr Erlebnis mit benutzerdefinierten Fe
msgid "Choose your password"
msgstr "Wählen Sie Ihr Passwort"
#: src/view/screens/Settings.tsx:694
#: src/view/screens/Settings.tsx:727
msgid "Clear all legacy storage data"
msgstr "Alle alten Speicherdaten löschen"
#: src/view/screens/Settings.tsx:696
#: src/view/screens/Settings.tsx:729
msgid "Clear all legacy storage data (restart after this)"
msgstr "Alle alten Speicherdaten löschen (danach neu starten)"
#: src/view/screens/Settings.tsx:706
#: src/view/screens/Settings.tsx:739
msgid "Clear all storage data"
msgstr "Alle alten Speicherdaten löschen"
#: src/view/screens/Settings.tsx:708
#: src/view/screens/Settings.tsx:741
msgid "Clear all storage data (restart after this)"
msgstr "Alle alten Speicherdaten löschen (danach neu starten)"
@@ -501,8 +501,8 @@ msgstr "Antwort zusammenstellen"
#: src/view/com/modals/Confirm.tsx:75
#: src/view/com/modals/SelfLabel.tsx:154
#: src/view/com/modals/VerifyEmail.tsx:225
#: src/view/screens/PreferencesHomeFeed.tsx:299
#: src/view/screens/PreferencesThreads.tsx:153
#: src/view/screens/PreferencesHomeFeed.tsx:305
#: src/view/screens/PreferencesThreads.tsx:159
msgid "Confirm"
msgstr "Bestätigen"
@@ -526,7 +526,7 @@ msgid "Confirmation code"
msgstr "Bestätigungscode"
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:269
#: src/view/com/auth/login/LoginForm.tsx:273
msgid "Connecting..."
msgstr "Verbinden..."
@@ -616,11 +616,15 @@ msgstr "Erstellt {0}"
msgid "Custom domain"
msgstr "Benutzerdefinierter Bereich"
#: src/view/screens/Settings.tsx:615
#: src/view/screens/PreferencesExternalEmbeds.tsx:55
msgid "Customize media from external sites."
msgstr ""
#: src/view/screens/Settings.tsx:648
msgid "Danger Zone"
msgstr "Gefahrenzone"
#: src/view/screens/Settings.tsx:622
#: src/view/screens/Settings.tsx:655
msgid "Delete account"
msgstr "Konto löschen"
@@ -642,7 +646,7 @@ msgstr "Liste löschen"
msgid "Delete my account"
msgstr "Mein Konto löschen"
#: src/view/screens/Settings.tsx:632
#: src/view/screens/Settings.tsx:665
msgid "Delete my account…"
msgstr "Mein Konto löschen..."
@@ -669,19 +673,19 @@ msgstr "Beschreibung"
msgid "Dev Server"
msgstr "Entwicklungs-Server"
#: src/view/screens/Settings.tsx:637
#: src/view/screens/Settings.tsx:670
msgid "Developer Tools"
msgstr "Werkzeuge für Entwickler"
#: src/view/com/composer/Composer.tsx:210
#: src/view/com/composer/Composer.tsx:211
msgid "Did you want to say anything?"
msgstr ""
#: src/view/com/composer/Composer.tsx:143
#: src/view/com/composer/Composer.tsx:144
msgid "Discard"
msgstr "Verwerfen"
#: src/view/com/composer/Composer.tsx:137
#: src/view/com/composer/Composer.tsx:138
msgid "Discard draft"
msgstr "Verwerfen"
@@ -706,6 +710,7 @@ msgid "Domain verified!"
msgstr "Domain geprüft!"
#: src/view/com/auth/onboarding/RecommendedFollows.tsx:86
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/ContentFilteringSettings.tsx:88
#: src/view/com/modals/ContentFilteringSettings.tsx:96
#: src/view/com/modals/crop-image/CropImage.web.tsx:152
@@ -715,8 +720,8 @@ msgstr "Domain geprüft!"
#: src/view/com/modals/Threadgate.tsx:129
#: src/view/com/modals/Threadgate.tsx:132
#: src/view/com/modals/UserAddRemoveLists.tsx:79
#: src/view/screens/PreferencesHomeFeed.tsx:302
#: src/view/screens/PreferencesThreads.tsx:156
#: src/view/screens/PreferencesHomeFeed.tsx:308
#: src/view/screens/PreferencesThreads.tsx:162
msgid "Done"
msgstr "Erledigt"
@@ -777,7 +782,15 @@ msgstr "Email aktualiziert"
msgid "Email:"
msgstr "E-Mail:"
#: src/view/screens/PreferencesHomeFeed.tsx:138
#: src/view/com/modals/EmbedConsent.tsx:113
msgid "Enable {0} only"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:97
msgid "Enable External Media"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:144
msgid "Enable this setting to only see replies between people you follow."
msgstr "Aktivieren Sie diese Einstellung, um nur Antworten zwischen Personen zu sehen, denen Sie folgen."
@@ -821,6 +834,20 @@ msgstr "Alle"
msgid "Expand alt text"
msgstr "Alt-Text erweitern"
#: src/view/com/modals/EmbedConsent.tsx:64
msgid "External Media"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:75
#: src/view/screens/PreferencesExternalEmbeds.tsx:66
msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button."
msgstr ""
#: src/view/screens/PreferencesExternalEmbeds.tsx:52
#: src/view/screens/Settings.tsx:595
msgid "External Media Preferences"
msgstr ""
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:109
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:141
msgid "Failed to load recommended feeds"
@@ -868,7 +895,7 @@ msgstr "Benutzer mit der Suchfunktion auf der rechten Seite finden"
msgid "Finding similar accounts..."
msgstr "Suche nach ähnlichen Konten..."
#: src/view/screens/PreferencesHomeFeed.tsx:102
#: src/view/screens/PreferencesHomeFeed.tsx:108
msgid "Fine-tune the content you see on your home screen."
msgstr "Optimieren Sie die Inhalte, die Sie auf Ihrem Startbildschirm sehen."
@@ -888,7 +915,7 @@ msgstr "Folgen Sie einigen Nutzern, um loszulegen. Wir können Ihnen weitere Nut
msgid "Followed users"
msgstr "Verfolgte Benutzer"
#: src/view/screens/PreferencesHomeFeed.tsx:145
#: src/view/screens/PreferencesHomeFeed.tsx:151
msgid "Followed users only"
msgstr "Nur verfolgte Benutzer"
@@ -917,11 +944,11 @@ msgstr "Aus Sicherheitsgründen müssen wir Ihnen einen Bestätigungscode an Ihr
msgid "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."
msgstr "Aus Sicherheitsgründen können Sie es nicht mehr einsehen. Wenn Sie dieses Passwort verlieren, müssen Sie ein neues generieren."
#: src/view/com/auth/login/LoginForm.tsx:232
#: src/view/com/auth/login/LoginForm.tsx:236
msgid "Forgot"
msgstr "Vergessen"
#: src/view/com/auth/login/LoginForm.tsx:229
#: src/view/com/auth/login/LoginForm.tsx:233
msgid "Forgot password"
msgstr "Passwort vergessen"
@@ -953,7 +980,7 @@ msgid "Go Back"
msgstr "Zurückgehen"
#: src/view/com/auth/login/ForgotPasswordForm.tsx:181
#: src/view/com/auth/login/LoginForm.tsx:279
#: src/view/com/auth/login/LoginForm.tsx:283
#: src/view/com/auth/login/SetNewPasswordForm.tsx:163
msgid "Go to next"
msgstr "Weiter zum nächsten"
@@ -1016,7 +1043,7 @@ msgid "Home"
msgstr "Startseite"
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/PreferencesHomeFeed.tsx:101
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
msgstr "Startseite Feed-Einstellungen"
@@ -1051,7 +1078,7 @@ msgstr "Bild-Alt-Text"
msgid "Image options"
msgstr "Bild-Optionen"
#: src/view/com/auth/login/LoginForm.tsx:113
#: src/view/com/auth/login/LoginForm.tsx:115
msgid "Invalid username or password"
msgstr "Ungültiger Benutzername oder Passwort"
@@ -1256,6 +1283,10 @@ msgstr "Mehr Feeds "
msgid "More options"
msgstr "Mehr Optionen"
#: src/view/screens/PreferencesThreads.tsx:82
msgid "Most-liked replies first"
msgstr ""
#: src/view/com/profile/ProfileHeader.tsx:370
msgid "Mute Account"
msgstr "Stummes Konto"
@@ -1313,6 +1344,11 @@ msgstr "Meine gespeicherte Feeds "
msgid "Name"
msgstr "Namen"
#: src/view/com/modals/EmbedConsent.tsx:107
#: src/view/com/modals/EmbedConsent.tsx:123
msgid "Never load embeds from {0}"
msgstr ""
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:72
msgid "Never lose access to your followers and data."
msgstr "Verlieren Sie nie den Zugriff auf Ihre Follower und Daten."
@@ -1336,10 +1372,14 @@ msgstr "Neuer Posten "
msgid "New Post"
msgstr "Neuer Posten "
#: src/view/screens/PreferencesThreads.tsx:79
msgid "Newest replies first"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:282
#: src/view/com/auth/login/LoginForm.tsx:286
#: src/view/com/auth/login/SetNewPasswordForm.tsx:156
#: src/view/com/auth/login/SetNewPasswordForm.tsx:166
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:79
@@ -1350,10 +1390,12 @@ msgstr "Nächster"
msgid "Next image"
msgstr "Nächstes Bild "
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:191
#: src/view/screens/PreferencesHomeFeed.tsx:226
#: src/view/screens/PreferencesHomeFeed.tsx:263
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:197
#: src/view/screens/PreferencesHomeFeed.tsx:232
#: src/view/screens/PreferencesHomeFeed.tsx:269
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "No"
msgstr "Nein"
@@ -1378,6 +1420,10 @@ msgstr "Keine Ergebnisse gefunden für \"{query}\""
msgid "No results found for {query}"
msgstr "Keine Ergebnisse gefunden für {query}"
#: src/view/com/modals/EmbedConsent.tsx:129
msgid "No thanks"
msgstr ""
#: src/view/com/modals/Threadgate.tsx:82
msgid "Nobody"
msgstr "Niemand"
@@ -1407,7 +1453,11 @@ msgstr "Ach nein!"
msgid "Okay"
msgstr "Okay"
#: src/view/com/composer/Composer.tsx:358
#: src/view/screens/PreferencesThreads.tsx:78
msgid "Oldest replies first"
msgstr ""
#: src/view/com/composer/Composer.tsx:363
msgid "One or more images is missing alt text."
msgstr "Bei einem oder mehreren Bildern fehlt der Alt-Text."
@@ -1415,6 +1465,11 @@ msgstr "Bei einem oder mehreren Bildern fehlt der Alt-Text."
msgid "Only {0} can reply."
msgstr "Nur {0} kann antworten."
#: src/view/com/composer/Composer.tsx:468
#: src/view/com/composer/Composer.tsx:469
msgid "Open emoji picker"
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr "Offene Navigation"
@@ -1423,6 +1478,10 @@ msgstr "Offene Navigation"
msgid "Opens configurable language settings"
msgstr "Öffnet die konfigurierbaren Spracheinstellungen"
#: src/view/screens/Settings.tsx:587
msgid "Opens external embeds settings"
msgstr ""
#: src/view/shell/desktop/RightNav.tsx:156
#: src/view/shell/Drawer.tsx:641
msgid "Opens list of invite codes"
@@ -1440,7 +1499,7 @@ msgstr "Öffnet die Moderationseinstellungen"
msgid "Opens screen with all saved feeds"
msgstr "Öffnet den Bildschirm mit allen gespeicherten Feeds"
#: src/view/screens/Settings.tsx:581
#: src/view/screens/Settings.tsx:614
msgid "Opens the app password settings page"
msgstr "Öffnet die Einstellungsseite für das App-Passwort"
@@ -1448,11 +1507,11 @@ msgstr "Öffnet die Einstellungsseite für das App-Passwort"
msgid "Opens the home feed preferences"
msgstr "Öffnet die Homefeed-Einstellungen"
#: src/view/screens/Settings.tsx:664
#: src/view/screens/Settings.tsx:697
msgid "Opens the storybook page"
msgstr "Öffnet die Märchenbuchseite"
#: src/view/screens/Settings.tsx:644
#: src/view/screens/Settings.tsx:677
msgid "Opens the system log page"
msgstr "Öffnet die Systemprotokollseite"
@@ -1483,7 +1542,7 @@ msgstr "Seite nicht gefunden"
#: src/view/com/auth/create/Step2.tsx:122
#: src/view/com/auth/create/Step2.tsx:132
#: src/view/com/auth/login/LoginForm.tsx:217
#: src/view/com/auth/login/LoginForm.tsx:221
#: src/view/com/auth/login/SetNewPasswordForm.tsx:130
#: src/view/com/modals/DeleteAccount.tsx:191
msgid "Password"
@@ -1505,6 +1564,19 @@ msgstr "Bilder, die für Erwachsene gedacht sind."
msgid "Pinned Feeds"
msgstr "Angepinnte Feeds"
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:111
msgid "Play {0}"
msgstr ""
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:54
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:55
msgid "Play Video"
msgstr ""
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:110
msgid "Plays the GIF"
msgstr ""
#: src/view/com/auth/create/state.ts:116
msgid "Please choose your handle."
msgstr "Bitte wählen Sie Ihren Handgriff."
@@ -1539,11 +1611,11 @@ msgstr ""
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr "Bitte teilen Sie uns mit, warum diese Entscheidung Ihrer Meinung nach falsch war."
#: src/view/com/composer/Composer.tsx:214
#: src/view/com/composer/Composer.tsx:215
msgid "Please wait for your link card to finish loading"
msgstr ""
#: src/view/com/composer/Composer.tsx:341
#: src/view/com/composer/Composer.tsx:346
#: src/view/com/post-thread/PostThread.tsx:225
#: src/view/screens/PostThread.tsx:80
msgid "Post"
@@ -1581,16 +1653,17 @@ msgstr "Vorheriges Bild"
msgid "Primary Language"
msgstr "Primäre Sprache"
#: src/view/screens/PreferencesThreads.tsx:91
#: src/view/screens/PreferencesThreads.tsx:97
msgid "Prioritize Your Follows"
msgstr "Priorisieren Sie Ihre Anhängerschaft"
#: src/view/screens/Settings.tsx:570
#: src/view/shell/desktop/RightNav.tsx:84
msgid "Privacy"
msgstr "Privatsphäre"
#: src/view/screens/PrivacyPolicy.tsx:29
#: src/view/screens/Settings.tsx:750
#: src/view/screens/Settings.tsx:783
#: src/view/shell/Drawer.tsx:262
msgid "Privacy Policy"
msgstr "Datenschutzbestimmungen"
@@ -1607,7 +1680,7 @@ msgstr "Verarbeitung..."
msgid "Profile"
msgstr "Profile"
#: src/view/screens/Settings.tsx:808
#: src/view/screens/Settings.tsx:841
msgid "Protect your account by verifying your email."
msgstr "Schützen Sie Ihr Konto, indem Sie Ihre E-Mail verifizieren."
@@ -1628,6 +1701,10 @@ msgstr "Angebotsposten"
msgid "Quote Post"
msgstr "Angebotsposten"
#: src/view/screens/PreferencesThreads.tsx:86
msgid "Random (aka \"Poster's Roulette\")"
msgstr ""
#: src/view/com/modals/EditImage.tsx:236
msgid "Ratios"
msgstr "Verhältnisse"
@@ -1695,7 +1772,7 @@ msgstr "Antworten"
msgid "Replies to this thread are disabled"
msgstr "Antworten auf diesen Thread sind deaktiviert"
#: src/view/screens/PreferencesHomeFeed.tsx:135
#: src/view/screens/PreferencesHomeFeed.tsx:141
msgid "Reply Filters"
msgstr "Antwort-Filter"
@@ -1738,6 +1815,10 @@ msgstr "Nachgetragen von"
msgid "Request Change"
msgstr "Änderung beantragen"
#: src/view/screens/Settings.tsx:422
msgid "Require alt text before posting"
msgstr ""
#: src/view/com/auth/create/Step2.tsx:68
msgid "Required for this provider"
msgstr "Für diesen Anbieter erforderlich"
@@ -1746,7 +1827,7 @@ msgstr "Für diesen Anbieter erforderlich"
msgid "Reset code"
msgstr "Code zurücksetzen"
#: src/view/screens/Settings.tsx:686
#: src/view/screens/Settings.tsx:719
msgid "Reset onboarding state"
msgstr "Onboarding-Status zurücksetzen"
@@ -1754,28 +1835,27 @@ msgstr "Onboarding-Status zurücksetzen"
msgid "Reset password"
msgstr "Passwort zurücksetzen"
#: src/view/screens/Settings.tsx:676
#: src/view/screens/Settings.tsx:709
msgid "Reset preferences state"
msgstr "Einstellungen zurücksetzen"
#: src/view/screens/Settings.tsx:684
#: src/view/screens/Settings.tsx:717
msgid "Resets the onboarding state"
msgstr "Onboarding-Status zurücksetzen"
#: src/view/screens/Settings.tsx:674
#: src/view/screens/Settings.tsx:707
msgid "Resets the preferences state"
msgstr "Setzt den Zustand der Einstellungen zurück"
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/login/LoginForm.tsx:259
#: src/view/com/auth/login/LoginForm.tsx:262
#: src/view/com/auth/login/LoginForm.tsx:263
#: src/view/com/auth/login/LoginForm.tsx:266
#: src/view/com/util/error/ErrorMessage.tsx:55
#: src/view/com/util/error/ErrorScreen.tsx:65
msgid "Retry"
msgstr "Wiederholung"
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/BirthDateSettings.tsx:94
#: src/view/com/modals/BirthDateSettings.tsx:97
#: src/view/com/modals/ChangeHandle.tsx:173
@@ -1839,7 +1919,7 @@ msgstr "Wählen Sie Bluesky Social"
msgid "Select from an existing account"
msgstr "Aus einem bestehenden Konto auswählen"
#: src/view/com/auth/login/LoginForm.tsx:143
#: src/view/com/auth/login/LoginForm.tsx:147
msgid "Select service"
msgstr "Dienst auswählen"
@@ -1880,23 +1960,23 @@ msgstr "Bericht senden"
msgid "Set new password"
msgstr "Neues Passwort festlegen"
#: src/view/screens/PreferencesHomeFeed.tsx:216
#: src/view/screens/PreferencesHomeFeed.tsx:222
msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
msgstr "Setzen Sie diese Einstellung auf \"Nein\", um alle zitierten Beiträge aus Ihrem Feed auszublenden. Neu eingestellte Beiträge sind weiterhin sichtbar."
#: src/view/screens/PreferencesHomeFeed.tsx:113
#: src/view/screens/PreferencesHomeFeed.tsx:119
msgid "Set this setting to \"No\" to hide all replies from your feed."
msgstr "Setzen Sie diese Einstellung auf \"Nein\", um alle Antworten aus Ihrem Feed auszublenden."
#: src/view/screens/PreferencesHomeFeed.tsx:182
#: src/view/screens/PreferencesHomeFeed.tsx:188
msgid "Set this setting to \"No\" to hide all reposts from your feed."
msgstr "Setzen Sie diese Einstellung auf \"Nein\", um alle wieder geposteten Beiträge aus Ihrem Feed auszublenden."
#: src/view/screens/PreferencesThreads.tsx:116
#: src/view/screens/PreferencesThreads.tsx:122
msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
msgstr "Setzen Sie diese Einstellung auf \"Ja\", um Antworten in einer Thread-Ansicht anzuzeigen. Dies ist eine experimentelle Funktion."
#: src/view/screens/PreferencesHomeFeed.tsx:252
#: src/view/screens/PreferencesHomeFeed.tsx:258
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
msgstr "Setzen Sie diese Einstellung auf \"Ja\", um Beispiele für Ihre gespeicherten Feeds in Ihrem folgenden Feed anzuzeigen. Dies ist eine experimentelle Funktion."
@@ -1930,23 +2010,27 @@ msgstr "Zeigen"
msgid "Show anyway"
msgstr "Trotzdem anzeigen"
#: src/view/screens/PreferencesHomeFeed.tsx:249
#: src/view/com/modals/EmbedConsent.tsx:87
msgid "Show embeds from {0}"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:255
msgid "Show Posts from My Feeds"
msgstr "Beiträge von My Feeds anzeigen"
#: src/view/screens/PreferencesHomeFeed.tsx:213
#: src/view/screens/PreferencesHomeFeed.tsx:219
msgid "Show Quote Posts"
msgstr "Angebotsposten zeigen"
#: src/view/screens/PreferencesHomeFeed.tsx:110
#: src/view/screens/PreferencesHomeFeed.tsx:116
msgid "Show Replies"
msgstr "Antworten zeigen"
#: src/view/screens/PreferencesThreads.tsx:94
#: src/view/screens/PreferencesThreads.tsx:100
msgid "Show replies by people you follow before all other replies."
msgstr "Antworten von Personen, denen Sie folgen, vor allen anderen Antworten anzeigen."
#: src/view/screens/PreferencesHomeFeed.tsx:179
#: src/view/screens/PreferencesHomeFeed.tsx:185
msgid "Show Reposts"
msgstr "Wiederholungen anzeigen"
@@ -1983,7 +2067,7 @@ msgstr "Eintragen als {0}"
msgid "Sign in as..."
msgstr "Eintragen als..."
#: src/view/com/auth/login/LoginForm.tsx:130
#: src/view/com/auth/login/LoginForm.tsx:134
msgid "Sign into"
msgstr "Anmelden"
@@ -2037,11 +2121,11 @@ msgstr "Platz"
msgid "Staging"
msgstr "Aufführung"
#: src/view/screens/Settings.tsx:730
#: src/view/screens/Settings.tsx:763
msgid "Status page"
msgstr "Status-Seite"
#: src/view/screens/Settings.tsx:666
#: src/view/screens/Settings.tsx:699
msgid "Storybook"
msgstr "Märchenbuch"
@@ -2070,7 +2154,7 @@ msgstr "Unterstützung"
msgid "Switch Account"
msgstr "Konto wechseln"
#: src/view/screens/Settings.tsx:646
#: src/view/screens/Settings.tsx:679
msgid "System log"
msgstr "System-Protokoll"
@@ -2082,7 +2166,7 @@ msgstr "Groß"
msgid "Terms"
msgstr "Bedingungen"
#: src/view/screens/Settings.tsx:744
#: src/view/screens/Settings.tsx:777
#: src/view/screens/TermsOfService.tsx:29
#: src/view/shell/Drawer.tsx:256
msgid "Terms of Service"
@@ -2137,6 +2221,10 @@ msgstr "Diese {screenDescription} wurde markiert:"
msgid "This account has requested that users sign in to view their profile."
msgstr "Dieses Konto hat die Benutzer aufgefordert, sich anzumelden, um ihr Profil zu sehen."
#: src/view/com/modals/EmbedConsent.tsx:68
msgid "This content is hosted by {0}. Do you want to enable external media?"
msgstr ""
#: src/view/com/posts/FeedErrorMessage.tsx:107
msgid "This content is not viewable without a Bluesky account."
msgstr "Dieser Inhalt kann ohne Bluesky-Konto nicht angezeigt werden."
@@ -2178,7 +2266,7 @@ msgstr ""
msgid "Thread Preferences"
msgstr "Einstellungen zum Thema"
#: src/view/screens/PreferencesThreads.tsx:113
#: src/view/screens/PreferencesThreads.tsx:119
msgid "Threaded Mode"
msgstr "Gewindemodus"
@@ -2210,7 +2298,7 @@ msgstr "Stummschaltliste aufheben"
#: src/view/com/auth/create/CreateAccount.tsx:65
#: src/view/com/auth/login/Login.tsx:76
#: src/view/com/auth/login/LoginForm.tsx:117
#: src/view/com/auth/login/LoginForm.tsx:120
msgid "Unable to contact your service. Please check your Internet connection."
msgstr "Sie können Ihren Dienst nicht kontaktieren. Bitte überprüfen Sie Ihre Internetverbindung."
@@ -2228,7 +2316,7 @@ msgstr "Konto freischalten"
msgid "Undo repost"
msgstr "Umbuchung rückgängig machen"
#: src/view/com/auth/create/state.ts:210
#: src/view/com/auth/create/state.ts:216
msgid "Unfortunately, you do not meet the requirements to create an account."
msgstr "Leider erfüllen Sie nicht die Voraussetzungen, um ein Konto zu erstellen."
@@ -2284,8 +2372,8 @@ msgstr "Benutzerhandgriff"
msgid "User Lists"
msgstr "Benutzer Liste"
#: src/view/com/auth/login/LoginForm.tsx:170
#: src/view/com/auth/login/LoginForm.tsx:188
#: src/view/com/auth/login/LoginForm.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:192
msgid "Username or email address"
msgstr "Benutzername oder E-Mail Adresse"
@@ -2301,15 +2389,15 @@ msgstr "Benutzer gefolgt von <0/>"
msgid "Users in \"{0}\""
msgstr "Benutzer in \"{0}\""
#: src/view/screens/Settings.tsx:769
#: src/view/screens/Settings.tsx:802
msgid "Verify email"
msgstr "E-Mail überprüfen"
#: src/view/screens/Settings.tsx:794
#: src/view/screens/Settings.tsx:827
msgid "Verify my email"
msgstr "E-Mail überprüfen"
#: src/view/screens/Settings.tsx:803
#: src/view/screens/Settings.tsx:836
msgid "Verify My Email"
msgstr "E-Mail überprüfen"
@@ -2375,7 +2463,7 @@ msgstr "Wer kann antworten."
msgid "Wide"
msgstr "Breit"
#: src/view/com/composer/Composer.tsx:413
#: src/view/com/composer/Composer.tsx:418
msgid "Write post"
msgstr "Posten schreiben"
@@ -2383,10 +2471,12 @@ msgstr "Posten schreiben"
msgid "Write your reply"
msgstr "Schreiben Sie Ihre Antwort"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:192
#: src/view/screens/PreferencesHomeFeed.tsx:227
#: src/view/screens/PreferencesHomeFeed.tsx:262
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:198
#: src/view/screens/PreferencesHomeFeed.tsx:233
#: src/view/screens/PreferencesHomeFeed.tsx:268
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "Yes"
msgstr "Ja"
+181 -95
View File
@@ -88,7 +88,7 @@ msgstr ""
msgid "Accessibility"
msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:159
#: src/view/com/auth/login/LoginForm.tsx:163
#: src/view/screens/Settings.tsx:286
msgid "Account"
msgstr ""
@@ -118,6 +118,7 @@ msgstr ""
#: src/view/com/composer/photos/Gallery.tsx:119
#: src/view/com/composer/photos/Gallery.tsx:180
#: src/view/com/modals/AltImage.tsx:93
msgid "Add alt text"
msgstr ""
@@ -130,11 +131,11 @@ msgstr ""
msgid "Add details to report"
msgstr ""
#: src/view/com/composer/Composer.tsx:442
#: src/view/com/composer/Composer.tsx:447
msgid "Add link card"
msgstr ""
#: src/view/com/composer/Composer.tsx:445
#: src/view/com/composer/Composer.tsx:450
msgid "Add link card:"
msgstr ""
@@ -155,7 +156,7 @@ msgstr ""
msgid "Added to list"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:164
#: src/view/screens/PreferencesHomeFeed.tsx:170
msgid "Adjust the number of likes a reply must have to be shown in your feed."
msgstr ""
@@ -163,7 +164,7 @@ msgstr ""
msgid "Adult Content"
msgstr ""
#: src/view/screens/Settings.tsx:569
#: src/view/screens/Settings.tsx:602
msgid "Advanced"
msgstr ""
@@ -196,7 +197,7 @@ msgstr ""
msgid "App Language"
msgstr ""
#: src/view/screens/Settings.tsx:589
#: src/view/screens/Settings.tsx:622
msgid "App passwords"
msgstr ""
@@ -236,7 +237,7 @@ msgstr ""
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr ""
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Are you sure you'd like to discard this draft?"
msgstr ""
@@ -259,7 +260,7 @@ msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:250
#: src/view/com/auth/login/LoginForm.tsx:254
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
#: src/view/com/modals/report/InputIssueDetails.tsx:46
#: src/view/com/post-thread/PostThread.tsx:388
@@ -355,7 +356,7 @@ msgstr ""
msgid "Bluesky.Social"
msgstr ""
#: src/view/screens/Settings.tsx:718
#: src/view/screens/Settings.tsx:751
msgid "Build version {0} {1}"
msgstr ""
@@ -373,9 +374,8 @@ msgstr ""
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr ""
#: src/view/com/composer/Composer.tsx:289
#: src/view/com/composer/Composer.tsx:292
#: src/view/com/modals/AltImage.tsx:128
#: src/view/com/composer/Composer.tsx:294
#: src/view/com/composer/Composer.tsx:297
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
#: src/view/com/modals/Confirm.tsx:88
@@ -399,8 +399,8 @@ msgid "Cancel account deletion"
msgstr ""
#: src/view/com/modals/AltImage.tsx:123
msgid "Cancel add image alt text"
msgstr ""
#~ msgid "Cancel add image alt text"
#~ msgstr ""
#: src/view/com/modals/ChangeHandle.tsx:149
msgid "Cancel change handle"
@@ -431,8 +431,8 @@ msgstr ""
msgid "Change"
msgstr ""
#: src/view/screens/Settings.tsx:601
#: src/view/screens/Settings.tsx:610
#: src/view/screens/Settings.tsx:634
#: src/view/screens/Settings.tsx:643
msgid "Change handle"
msgstr ""
@@ -480,19 +480,19 @@ msgstr ""
msgid "Choose your password"
msgstr ""
#: src/view/screens/Settings.tsx:694
#: src/view/screens/Settings.tsx:727
msgid "Clear all legacy storage data"
msgstr ""
#: src/view/screens/Settings.tsx:696
#: src/view/screens/Settings.tsx:729
msgid "Clear all legacy storage data (restart after this)"
msgstr ""
#: src/view/screens/Settings.tsx:706
#: src/view/screens/Settings.tsx:739
msgid "Clear all storage data"
msgstr ""
#: src/view/screens/Settings.tsx:708
#: src/view/screens/Settings.tsx:741
msgid "Clear all storage data (restart after this)"
msgstr ""
@@ -533,8 +533,8 @@ msgstr ""
#: src/view/com/modals/Confirm.tsx:75
#: src/view/com/modals/SelfLabel.tsx:154
#: src/view/com/modals/VerifyEmail.tsx:225
#: src/view/screens/PreferencesHomeFeed.tsx:299
#: src/view/screens/PreferencesThreads.tsx:153
#: src/view/screens/PreferencesHomeFeed.tsx:305
#: src/view/screens/PreferencesThreads.tsx:159
msgid "Confirm"
msgstr ""
@@ -558,7 +558,7 @@ msgid "Confirmation code"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:269
#: src/view/com/auth/login/LoginForm.tsx:273
msgid "Connecting..."
msgstr ""
@@ -648,7 +648,11 @@ msgstr ""
msgid "Custom domain"
msgstr ""
#: src/view/screens/Settings.tsx:615
#: src/view/screens/PreferencesExternalEmbeds.tsx:55
msgid "Customize media from external sites."
msgstr ""
#: src/view/screens/Settings.tsx:648
msgid "Danger Zone"
msgstr ""
@@ -656,7 +660,7 @@ msgstr ""
#~ msgid "Dark"
#~ msgstr ""
#: src/view/screens/Settings.tsx:622
#: src/view/screens/Settings.tsx:655
msgid "Delete account"
msgstr ""
@@ -678,7 +682,7 @@ msgstr ""
msgid "Delete my account"
msgstr ""
#: src/view/screens/Settings.tsx:632
#: src/view/screens/Settings.tsx:665
msgid "Delete my account…"
msgstr ""
@@ -705,19 +709,19 @@ msgstr ""
msgid "Dev Server"
msgstr ""
#: src/view/screens/Settings.tsx:637
#: src/view/screens/Settings.tsx:670
msgid "Developer Tools"
msgstr ""
#: src/view/com/composer/Composer.tsx:210
#: src/view/com/composer/Composer.tsx:211
msgid "Did you want to say anything?"
msgstr ""
#: src/view/com/composer/Composer.tsx:143
#: src/view/com/composer/Composer.tsx:144
msgid "Discard"
msgstr ""
#: src/view/com/composer/Composer.tsx:137
#: src/view/com/composer/Composer.tsx:138
msgid "Discard draft"
msgstr ""
@@ -742,6 +746,7 @@ msgid "Domain verified!"
msgstr ""
#: src/view/com/auth/onboarding/RecommendedFollows.tsx:86
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/ContentFilteringSettings.tsx:88
#: src/view/com/modals/ContentFilteringSettings.tsx:96
#: src/view/com/modals/crop-image/CropImage.web.tsx:152
@@ -751,8 +756,8 @@ msgstr ""
#: src/view/com/modals/Threadgate.tsx:129
#: src/view/com/modals/Threadgate.tsx:132
#: src/view/com/modals/UserAddRemoveLists.tsx:79
#: src/view/screens/PreferencesHomeFeed.tsx:302
#: src/view/screens/PreferencesThreads.tsx:156
#: src/view/screens/PreferencesHomeFeed.tsx:308
#: src/view/screens/PreferencesThreads.tsx:162
msgid "Done"
msgstr ""
@@ -813,7 +818,15 @@ msgstr ""
msgid "Email:"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:138
#: src/view/com/modals/EmbedConsent.tsx:113
msgid "Enable {0} only"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:97
msgid "Enable External Media"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:144
msgid "Enable this setting to only see replies between people you follow."
msgstr ""
@@ -857,6 +870,20 @@ msgstr ""
msgid "Expand alt text"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:64
msgid "External Media"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:75
#: src/view/screens/PreferencesExternalEmbeds.tsx:66
msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button."
msgstr ""
#: src/view/screens/PreferencesExternalEmbeds.tsx:52
#: src/view/screens/Settings.tsx:595
msgid "External Media Preferences"
msgstr ""
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:109
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:141
msgid "Failed to load recommended feeds"
@@ -904,7 +931,7 @@ msgstr ""
msgid "Finding similar accounts..."
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:102
#: src/view/screens/PreferencesHomeFeed.tsx:108
msgid "Fine-tune the content you see on your home screen."
msgstr ""
@@ -928,7 +955,7 @@ msgstr ""
msgid "Followed users"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:145
#: src/view/screens/PreferencesHomeFeed.tsx:151
msgid "Followed users only"
msgstr ""
@@ -957,11 +984,11 @@ msgstr ""
msgid "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."
msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:232
#: src/view/com/auth/login/LoginForm.tsx:236
msgid "Forgot"
msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:229
#: src/view/com/auth/login/LoginForm.tsx:233
msgid "Forgot password"
msgstr ""
@@ -993,7 +1020,7 @@ msgid "Go Back"
msgstr ""
#: src/view/com/auth/login/ForgotPasswordForm.tsx:181
#: src/view/com/auth/login/LoginForm.tsx:279
#: src/view/com/auth/login/LoginForm.tsx:283
#: src/view/com/auth/login/SetNewPasswordForm.tsx:163
msgid "Go to next"
msgstr ""
@@ -1064,7 +1091,7 @@ msgid "Home"
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/PreferencesHomeFeed.tsx:101
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
msgstr ""
@@ -1104,7 +1131,7 @@ msgstr ""
#~ msgid "In Your Network"
#~ msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:113
#: src/view/com/auth/login/LoginForm.tsx:115
msgid "Invalid username or password"
msgstr ""
@@ -1329,6 +1356,10 @@ msgstr ""
#~ msgid "More post options"
#~ msgstr ""
#: src/view/screens/PreferencesThreads.tsx:82
msgid "Most-liked replies first"
msgstr ""
#: src/view/com/profile/ProfileHeader.tsx:370
msgid "Mute Account"
msgstr ""
@@ -1390,6 +1421,11 @@ msgstr ""
msgid "Name"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:107
#: src/view/com/modals/EmbedConsent.tsx:123
msgid "Never load embeds from {0}"
msgstr ""
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:72
msgid "Never lose access to your followers and data."
msgstr ""
@@ -1413,10 +1449,14 @@ msgstr ""
msgid "New Post"
msgstr ""
#: src/view/screens/PreferencesThreads.tsx:79
msgid "Newest replies first"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:282
#: src/view/com/auth/login/LoginForm.tsx:286
#: src/view/com/auth/login/SetNewPasswordForm.tsx:156
#: src/view/com/auth/login/SetNewPasswordForm.tsx:166
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:79
@@ -1427,10 +1467,12 @@ msgstr ""
msgid "Next image"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:191
#: src/view/screens/PreferencesHomeFeed.tsx:226
#: src/view/screens/PreferencesHomeFeed.tsx:263
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:197
#: src/view/screens/PreferencesHomeFeed.tsx:232
#: src/view/screens/PreferencesHomeFeed.tsx:269
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "No"
msgstr ""
@@ -1460,6 +1502,10 @@ msgstr ""
msgid "No results found for {query}"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:129
msgid "No thanks"
msgstr ""
#: src/view/com/modals/Threadgate.tsx:82
msgid "Nobody"
msgstr ""
@@ -1501,7 +1547,11 @@ msgstr ""
msgid "Okay"
msgstr ""
#: src/view/com/composer/Composer.tsx:358
#: src/view/screens/PreferencesThreads.tsx:78
msgid "Oldest replies first"
msgstr ""
#: src/view/com/composer/Composer.tsx:363
msgid "One or more images is missing alt text."
msgstr ""
@@ -1509,6 +1559,11 @@ msgstr ""
msgid "Only {0} can reply."
msgstr ""
#: src/view/com/composer/Composer.tsx:468
#: src/view/com/composer/Composer.tsx:469
msgid "Open emoji picker"
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr ""
@@ -1517,6 +1572,10 @@ msgstr ""
msgid "Opens configurable language settings"
msgstr ""
#: src/view/screens/Settings.tsx:587
msgid "Opens external embeds settings"
msgstr ""
#: src/view/shell/desktop/RightNav.tsx:156
#: src/view/shell/Drawer.tsx:641
msgid "Opens list of invite codes"
@@ -1534,7 +1593,7 @@ msgstr ""
msgid "Opens screen with all saved feeds"
msgstr ""
#: src/view/screens/Settings.tsx:581
#: src/view/screens/Settings.tsx:614
msgid "Opens the app password settings page"
msgstr ""
@@ -1542,11 +1601,11 @@ msgstr ""
msgid "Opens the home feed preferences"
msgstr ""
#: src/view/screens/Settings.tsx:664
#: src/view/screens/Settings.tsx:697
msgid "Opens the storybook page"
msgstr ""
#: src/view/screens/Settings.tsx:644
#: src/view/screens/Settings.tsx:677
msgid "Opens the system log page"
msgstr ""
@@ -1577,7 +1636,7 @@ msgstr ""
#: src/view/com/auth/create/Step2.tsx:122
#: src/view/com/auth/create/Step2.tsx:132
#: src/view/com/auth/login/LoginForm.tsx:217
#: src/view/com/auth/login/LoginForm.tsx:221
#: src/view/com/auth/login/SetNewPasswordForm.tsx:130
#: src/view/com/modals/DeleteAccount.tsx:191
msgid "Password"
@@ -1599,6 +1658,19 @@ msgstr ""
msgid "Pinned Feeds"
msgstr ""
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:111
msgid "Play {0}"
msgstr ""
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:54
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:55
msgid "Play Video"
msgstr ""
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:110
msgid "Plays the GIF"
msgstr ""
#: src/view/com/auth/create/state.ts:116
msgid "Please choose your handle."
msgstr ""
@@ -1633,11 +1705,11 @@ msgstr ""
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:214
#: src/view/com/composer/Composer.tsx:215
msgid "Please wait for your link card to finish loading"
msgstr ""
#: src/view/com/composer/Composer.tsx:341
#: src/view/com/composer/Composer.tsx:346
#: src/view/com/post-thread/PostThread.tsx:225
#: src/view/screens/PostThread.tsx:80
msgid "Post"
@@ -1675,16 +1747,17 @@ msgstr ""
msgid "Primary Language"
msgstr ""
#: src/view/screens/PreferencesThreads.tsx:91
#: src/view/screens/PreferencesThreads.tsx:97
msgid "Prioritize Your Follows"
msgstr ""
#: src/view/screens/Settings.tsx:570
#: src/view/shell/desktop/RightNav.tsx:84
msgid "Privacy"
msgstr ""
#: src/view/screens/PrivacyPolicy.tsx:29
#: src/view/screens/Settings.tsx:750
#: src/view/screens/Settings.tsx:783
#: src/view/shell/Drawer.tsx:262
msgid "Privacy Policy"
msgstr ""
@@ -1701,7 +1774,7 @@ msgstr ""
msgid "Profile"
msgstr ""
#: src/view/screens/Settings.tsx:808
#: src/view/screens/Settings.tsx:841
msgid "Protect your account by verifying your email."
msgstr ""
@@ -1722,6 +1795,10 @@ msgstr ""
msgid "Quote Post"
msgstr ""
#: src/view/screens/PreferencesThreads.tsx:86
msgid "Random (aka \"Poster's Roulette\")"
msgstr ""
#: src/view/com/modals/EditImage.tsx:236
msgid "Ratios"
msgstr ""
@@ -1794,7 +1871,7 @@ msgstr ""
msgid "Replies to this thread are disabled"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:135
#: src/view/screens/PreferencesHomeFeed.tsx:141
msgid "Reply Filters"
msgstr ""
@@ -1841,9 +1918,9 @@ msgstr ""
#~ msgid "Request to limit the visibility of my account"
#~ msgstr ""
#: src/view/screens/Settings.tsx:382
#~ msgid "Require alt text before posting"
#~ msgstr ""
#: src/view/screens/Settings.tsx:422
msgid "Require alt text before posting"
msgstr ""
#: src/view/com/auth/create/Step2.tsx:68
msgid "Required for this provider"
@@ -1853,7 +1930,7 @@ msgstr ""
msgid "Reset code"
msgstr ""
#: src/view/screens/Settings.tsx:686
#: src/view/screens/Settings.tsx:719
msgid "Reset onboarding state"
msgstr ""
@@ -1861,22 +1938,22 @@ msgstr ""
msgid "Reset password"
msgstr ""
#: src/view/screens/Settings.tsx:676
#: src/view/screens/Settings.tsx:709
msgid "Reset preferences state"
msgstr ""
#: src/view/screens/Settings.tsx:684
#: src/view/screens/Settings.tsx:717
msgid "Resets the onboarding state"
msgstr ""
#: src/view/screens/Settings.tsx:674
#: src/view/screens/Settings.tsx:707
msgid "Resets the preferences state"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/login/LoginForm.tsx:259
#: src/view/com/auth/login/LoginForm.tsx:262
#: src/view/com/auth/login/LoginForm.tsx:263
#: src/view/com/auth/login/LoginForm.tsx:266
#: src/view/com/util/error/ErrorMessage.tsx:55
#: src/view/com/util/error/ErrorScreen.tsx:65
msgid "Retry"
@@ -1886,7 +1963,6 @@ msgstr ""
#~ msgid "Retry change handle"
#~ msgstr ""
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/BirthDateSettings.tsx:94
#: src/view/com/modals/BirthDateSettings.tsx:97
#: src/view/com/modals/ChangeHandle.tsx:173
@@ -1958,7 +2034,7 @@ msgstr ""
msgid "Select from an existing account"
msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:143
#: src/view/com/auth/login/LoginForm.tsx:147
msgid "Select service"
msgstr ""
@@ -1999,23 +2075,23 @@ msgstr ""
msgid "Set new password"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:216
#: src/view/screens/PreferencesHomeFeed.tsx:222
msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:113
#: src/view/screens/PreferencesHomeFeed.tsx:119
msgid "Set this setting to \"No\" to hide all replies from your feed."
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:182
#: src/view/screens/PreferencesHomeFeed.tsx:188
msgid "Set this setting to \"No\" to hide all reposts from your feed."
msgstr ""
#: src/view/screens/PreferencesThreads.tsx:116
#: src/view/screens/PreferencesThreads.tsx:122
msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:252
#: src/view/screens/PreferencesHomeFeed.tsx:258
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
msgstr ""
@@ -2053,23 +2129,27 @@ msgstr ""
msgid "Show anyway"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:249
#: src/view/com/modals/EmbedConsent.tsx:87
msgid "Show embeds from {0}"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:255
msgid "Show Posts from My Feeds"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:213
#: src/view/screens/PreferencesHomeFeed.tsx:219
msgid "Show Quote Posts"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:110
#: src/view/screens/PreferencesHomeFeed.tsx:116
msgid "Show Replies"
msgstr ""
#: src/view/screens/PreferencesThreads.tsx:94
#: src/view/screens/PreferencesThreads.tsx:100
msgid "Show replies by people you follow before all other replies."
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:179
#: src/view/screens/PreferencesHomeFeed.tsx:185
msgid "Show Reposts"
msgstr ""
@@ -2106,7 +2186,7 @@ msgstr ""
msgid "Sign in as..."
msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:130
#: src/view/com/auth/login/LoginForm.tsx:134
msgid "Sign into"
msgstr ""
@@ -2160,11 +2240,11 @@ msgstr ""
msgid "Staging"
msgstr ""
#: src/view/screens/Settings.tsx:730
#: src/view/screens/Settings.tsx:763
msgid "Status page"
msgstr ""
#: src/view/screens/Settings.tsx:666
#: src/view/screens/Settings.tsx:699
msgid "Storybook"
msgstr ""
@@ -2197,7 +2277,7 @@ msgstr ""
#~ msgid "System"
#~ msgstr ""
#: src/view/screens/Settings.tsx:646
#: src/view/screens/Settings.tsx:679
msgid "System log"
msgstr ""
@@ -2209,7 +2289,7 @@ msgstr ""
msgid "Terms"
msgstr ""
#: src/view/screens/Settings.tsx:744
#: src/view/screens/Settings.tsx:777
#: src/view/screens/TermsOfService.tsx:29
#: src/view/shell/Drawer.tsx:256
msgid "Terms of Service"
@@ -2264,6 +2344,10 @@ msgstr ""
msgid "This account has requested that users sign in to view their profile."
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:68
msgid "This content is hosted by {0}. Do you want to enable external media?"
msgstr ""
#: src/view/com/posts/FeedErrorMessage.tsx:107
msgid "This content is not viewable without a Bluesky account."
msgstr ""
@@ -2305,7 +2389,7 @@ msgstr ""
msgid "Thread Preferences"
msgstr ""
#: src/view/screens/PreferencesThreads.tsx:113
#: src/view/screens/PreferencesThreads.tsx:119
msgid "Threaded Mode"
msgstr ""
@@ -2337,7 +2421,7 @@ msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:65
#: src/view/com/auth/login/Login.tsx:76
#: src/view/com/auth/login/LoginForm.tsx:117
#: src/view/com/auth/login/LoginForm.tsx:120
msgid "Unable to contact your service. Please check your Internet connection."
msgstr ""
@@ -2355,7 +2439,7 @@ msgstr ""
msgid "Undo repost"
msgstr ""
#: src/view/com/auth/create/state.ts:210
#: src/view/com/auth/create/state.ts:216
msgid "Unfortunately, you do not meet the requirements to create an account."
msgstr ""
@@ -2411,8 +2495,8 @@ msgstr ""
msgid "User Lists"
msgstr ""
#: src/view/com/auth/login/LoginForm.tsx:170
#: src/view/com/auth/login/LoginForm.tsx:188
#: src/view/com/auth/login/LoginForm.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:192
msgid "Username or email address"
msgstr ""
@@ -2432,15 +2516,15 @@ msgstr ""
msgid "Users in \"{0}\""
msgstr ""
#: src/view/screens/Settings.tsx:769
#: src/view/screens/Settings.tsx:802
msgid "Verify email"
msgstr ""
#: src/view/screens/Settings.tsx:794
#: src/view/screens/Settings.tsx:827
msgid "Verify my email"
msgstr ""
#: src/view/screens/Settings.tsx:803
#: src/view/screens/Settings.tsx:836
msgid "Verify My Email"
msgstr ""
@@ -2514,7 +2598,7 @@ msgstr ""
msgid "Wide"
msgstr ""
#: src/view/com/composer/Composer.tsx:413
#: src/view/com/composer/Composer.tsx:418
msgid "Write post"
msgstr ""
@@ -2522,10 +2606,12 @@ msgstr ""
msgid "Write your reply"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:192
#: src/view/screens/PreferencesHomeFeed.tsx:227
#: src/view/screens/PreferencesHomeFeed.tsx:262
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:198
#: src/view/screens/PreferencesHomeFeed.tsx:233
#: src/view/screens/PreferencesHomeFeed.tsx:268
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "Yes"
msgstr ""
+197 -128
View File
@@ -15,7 +15,7 @@ msgstr ""
#: src/view/shell/desktop/RightNav.tsx:168
msgid "{0, plural, one {# invite code available} other {# invite codes available}}"
msgstr ""
msgstr "{0, plural, one {# invite code available} other {# invite codes available}}"
#: src/view/com/modals/Repost.tsx:44
msgid "{0}"
@@ -27,7 +27,7 @@ msgstr "Lista {purposeLabel} {0}"
#: src/view/shell/desktop/RightNav.tsx:151
msgid "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
msgstr ""
msgstr "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
#: src/view/screens/Settings.tsx:407
#: src/view/shell/Drawer.tsx:659
@@ -57,7 +57,7 @@ msgstr "<0>Sigue a algunos</0><1>usuarios</1><2>recomendados</2>"
#: src/view/com/util/moderation/LabelInfo.tsx:45
msgid "A content warning has been applied to this {0}."
msgstr ""
msgstr "Se ha aplicado una advertencia de contenido a este {0}."
#: src/lib/hooks/useOTAUpdate.ts:16
msgid "A new version of the app is available. Please update to continue using the app."
@@ -68,7 +68,7 @@ msgstr "Ya está disponible una nueva versión de la aplicación. Actualízala p
msgid "Accessibility"
msgstr "Accesibilidad"
#: src/view/com/auth/login/LoginForm.tsx:159
#: src/view/com/auth/login/LoginForm.tsx:163
#: src/view/screens/Settings.tsx:286
msgid "Account"
msgstr "Cuenta"
@@ -98,6 +98,7 @@ msgstr "Agregar una cuenta"
#: src/view/com/composer/photos/Gallery.tsx:119
#: src/view/com/composer/photos/Gallery.tsx:180
#: src/view/com/modals/AltImage.tsx:93
msgid "Add alt text"
msgstr "Agregar texto alt"
@@ -110,11 +111,11 @@ msgstr "Agregar detalles"
msgid "Add details to report"
msgstr "Agregar detalles al informe"
#: src/view/com/composer/Composer.tsx:442
#: src/view/com/composer/Composer.tsx:447
msgid "Add link card"
msgstr "Agregar una tarjeta de enlace"
#: src/view/com/composer/Composer.tsx:445
#: src/view/com/composer/Composer.tsx:450
msgid "Add link card:"
msgstr "Agregar una tarjeta de enlace:"
@@ -135,7 +136,7 @@ msgstr "Agregar a mis noticias"
msgid "Added to list"
msgstr "Agregar a una lista"
#: src/view/screens/PreferencesHomeFeed.tsx:164
#: src/view/screens/PreferencesHomeFeed.tsx:170
msgid "Adjust the number of likes a reply must have to be shown in your feed."
msgstr "Ajusta el número de Me gusta que debe tener una respuesta para que se muestre en tus noticias."
@@ -143,7 +144,7 @@ msgstr "Ajusta el número de Me gusta que debe tener una respuesta para que se m
msgid "Adult Content"
msgstr "Contenido para adultos"
#: src/view/screens/Settings.tsx:569
#: src/view/screens/Settings.tsx:602
msgid "Advanced"
msgstr "Avanzado"
@@ -176,7 +177,7 @@ msgstr "y"
msgid "App Language"
msgstr "Lenguaje de app"
#: src/view/screens/Settings.tsx:589
#: src/view/screens/Settings.tsx:622
msgid "App passwords"
msgstr "Contraseñas de la app"
@@ -186,15 +187,11 @@ msgstr "Contraseñas de la app"
#: src/view/com/util/forms/PostDropdownBtn.tsx:236
msgid "Appeal content warning"
msgstr ""
msgstr "Aviso sobre el contenido del recurso"
#: src/view/com/modals/AppealLabel.tsx:65
msgid "Appeal Content Warning"
msgstr ""
#: src/view/com/modals/AppealLabel.tsx:65
#~ msgid "Appeal Decision"
#~ msgstr "Decisión de apelación"
msgstr "Aviso sobre el Contenido del Recurso"
#: src/view/com/util/moderation/LabelInfo.tsx:52
msgid "Appeal this decision"
@@ -212,7 +209,7 @@ msgstr "Aspecto exterior"
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr "¿Estás seguro de que quieres eliminar la contraseña de la app \"{name}\"?"
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Are you sure you'd like to discard this draft?"
msgstr "¿Estás seguro de que quieres descartar este borrador?"
@@ -222,7 +219,7 @@ msgstr "¿Estás seguro?"
#: src/view/com/util/forms/PostDropdownBtn.tsx:219
msgid "Are you sure? This cannot be undone."
msgstr "¿Estás seguro? Esto no puede deshacerse,"
msgstr "¿Estás seguro? Esto no puede deshacerse."
#: src/view/com/modals/SelfLabel.tsx:123
msgid "Artistic or non-erotic nudity."
@@ -231,7 +228,7 @@ msgstr "Desnudez artística o no erótica."
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:250
#: src/view/com/auth/login/LoginForm.tsx:254
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
#: src/view/com/modals/report/InputIssueDetails.tsx:46
#: src/view/com/post-thread/PostThread.tsx:388
@@ -289,7 +286,7 @@ msgstr "Las cuentas bloqueadas no pueden responder en tus hilos, mencionarte ni
#: src/view/com/post-thread/PostThread.tsx:250
msgid "Blocked post."
msgstr "Publicación bloqueada"
msgstr "Publicación bloqueada."
#: src/view/screens/ProfileList.tsx:310
msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
@@ -327,7 +324,7 @@ msgstr "Bluesky no mostrará tu perfil ni tus publicaciones a los usuarios que h
msgid "Bluesky.Social"
msgstr "Bluesky.Social"
#: src/view/screens/Settings.tsx:718
#: src/view/screens/Settings.tsx:751
msgid "Build version {0} {1}"
msgstr "Versión {0} {1}"
@@ -345,9 +342,8 @@ msgstr "Cámara"
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr "Sólo puede contener letras, números, espacios, guiones y guiones bajos. Debe tener al menos 4 caracteres, pero no más de 32."
#: src/view/com/composer/Composer.tsx:289
#: src/view/com/composer/Composer.tsx:292
#: src/view/com/modals/AltImage.tsx:128
#: src/view/com/composer/Composer.tsx:294
#: src/view/com/composer/Composer.tsx:297
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
#: src/view/com/modals/Confirm.tsx:88
@@ -371,8 +367,8 @@ msgid "Cancel account deletion"
msgstr "Cancelar la eliminación de la cuenta"
#: src/view/com/modals/AltImage.tsx:123
msgid "Cancel add image alt text"
msgstr "Cancelar añadir texto alternativo a la imagen"
#~ msgid "Cancel add image alt text"
#~ msgstr "Cancelar añadir texto alternativo a la imagen"
#: src/view/com/modals/ChangeHandle.tsx:149
msgid "Cancel change handle"
@@ -403,8 +399,8 @@ msgstr "Cancelar la inscripción en la lista de espera"
msgid "Change"
msgstr "Cambiar"
#: src/view/screens/Settings.tsx:601
#: src/view/screens/Settings.tsx:610
#: src/view/screens/Settings.tsx:634
#: src/view/screens/Settings.tsx:643
msgid "Change handle"
msgstr "Cambiar el identificador"
@@ -448,19 +444,19 @@ msgstr "Elige los algoritmos que potencian tu experiencia con publicaciones pers
msgid "Choose your password"
msgstr "Elige tu contraseña"
#: src/view/screens/Settings.tsx:694
#: src/view/screens/Settings.tsx:727
msgid "Clear all legacy storage data"
msgstr "Borrar todos los datos de almacenamiento heredados"
#: src/view/screens/Settings.tsx:696
#: src/view/screens/Settings.tsx:729
msgid "Clear all legacy storage data (restart after this)"
msgstr "Borrar todos los datos de almacenamiento heredados (reiniciar después de esto)"
#: src/view/screens/Settings.tsx:706
#: src/view/screens/Settings.tsx:739
msgid "Clear all storage data"
msgstr "Borrar todos los datos de almacenamiento"
#: src/view/screens/Settings.tsx:708
#: src/view/screens/Settings.tsx:741
msgid "Clear all storage data (restart after this)"
msgstr "Borrar todos los datos de almacenamiento (reiniciar después de esto)"
@@ -501,8 +497,8 @@ msgstr "Redactar la respuesta"
#: src/view/com/modals/Confirm.tsx:75
#: src/view/com/modals/SelfLabel.tsx:154
#: src/view/com/modals/VerifyEmail.tsx:225
#: src/view/screens/PreferencesHomeFeed.tsx:299
#: src/view/screens/PreferencesThreads.tsx:153
#: src/view/screens/PreferencesHomeFeed.tsx:305
#: src/view/screens/PreferencesThreads.tsx:159
msgid "Confirm"
msgstr "Confirmar"
@@ -526,7 +522,7 @@ msgid "Confirmation code"
msgstr "Código de confirmación"
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:269
#: src/view/com/auth/login/LoginForm.tsx:273
msgid "Connecting..."
msgstr "Conectando..."
@@ -616,11 +612,15 @@ msgstr "Creado {0}"
msgid "Custom domain"
msgstr "Dominio personalizado"
#: src/view/screens/Settings.tsx:615
#: src/view/screens/PreferencesExternalEmbeds.tsx:55
msgid "Customize media from external sites."
msgstr ""
#: src/view/screens/Settings.tsx:648
msgid "Danger Zone"
msgstr "Zona de peligro"
#: src/view/screens/Settings.tsx:622
#: src/view/screens/Settings.tsx:655
msgid "Delete account"
msgstr "Borrar la cuenta"
@@ -642,7 +642,7 @@ msgstr "Borrar la lista"
msgid "Delete my account"
msgstr "Borrar mi cuenta"
#: src/view/screens/Settings.tsx:632
#: src/view/screens/Settings.tsx:665
msgid "Delete my account…"
msgstr "Borrar mi cuenta..."
@@ -669,19 +669,19 @@ msgstr "Descripción"
msgid "Dev Server"
msgstr "Servidor de desarrollo"
#: src/view/screens/Settings.tsx:637
#: src/view/screens/Settings.tsx:670
msgid "Developer Tools"
msgstr "Herramientas de desarrollador"
#: src/view/com/composer/Composer.tsx:210
#: src/view/com/composer/Composer.tsx:211
msgid "Did you want to say anything?"
msgstr ""
msgstr "¿Quieres decir algo?"
#: src/view/com/composer/Composer.tsx:143
#: src/view/com/composer/Composer.tsx:144
msgid "Discard"
msgstr "Descartar"
#: src/view/com/composer/Composer.tsx:137
#: src/view/com/composer/Composer.tsx:138
msgid "Discard draft"
msgstr "Descartar el borrador"
@@ -706,6 +706,7 @@ msgid "Domain verified!"
msgstr "¡Dominio verificado!"
#: src/view/com/auth/onboarding/RecommendedFollows.tsx:86
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/ContentFilteringSettings.tsx:88
#: src/view/com/modals/ContentFilteringSettings.tsx:96
#: src/view/com/modals/crop-image/CropImage.web.tsx:152
@@ -715,8 +716,8 @@ msgstr "¡Dominio verificado!"
#: src/view/com/modals/Threadgate.tsx:129
#: src/view/com/modals/Threadgate.tsx:132
#: src/view/com/modals/UserAddRemoveLists.tsx:79
#: src/view/screens/PreferencesHomeFeed.tsx:302
#: src/view/screens/PreferencesThreads.tsx:156
#: src/view/screens/PreferencesHomeFeed.tsx:308
#: src/view/screens/PreferencesThreads.tsx:162
msgid "Done"
msgstr "Listo"
@@ -777,7 +778,15 @@ msgstr "Correo electrónico actualizado"
msgid "Email:"
msgstr "Correo electrónico:"
#: src/view/screens/PreferencesHomeFeed.tsx:138
#: src/view/com/modals/EmbedConsent.tsx:113
msgid "Enable {0} only"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:97
msgid "Enable External Media"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:144
msgid "Enable this setting to only see replies between people you follow."
msgstr "Activa esta opción para ver sólo las respuestas de las personas a las que sigues."
@@ -821,6 +830,20 @@ msgstr "Todos"
msgid "Expand alt text"
msgstr "Expandir el texto alt"
#: src/view/com/modals/EmbedConsent.tsx:64
msgid "External Media"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:75
#: src/view/screens/PreferencesExternalEmbeds.tsx:66
msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button."
msgstr ""
#: src/view/screens/PreferencesExternalEmbeds.tsx:52
#: src/view/screens/Settings.tsx:595
msgid "External Media Preferences"
msgstr ""
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:109
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:141
msgid "Failed to load recommended feeds"
@@ -868,7 +891,7 @@ msgstr "Encuentra usuarios con la herramienta de búsqueda de la derecha"
msgid "Finding similar accounts..."
msgstr "Encontrar cuentas similares..."
#: src/view/screens/PreferencesHomeFeed.tsx:102
#: src/view/screens/PreferencesHomeFeed.tsx:108
msgid "Fine-tune the content you see on your home screen."
msgstr "Ajusta el contenido que ves en tu pantalla de inicio."
@@ -888,7 +911,7 @@ msgstr "Sigue a algunos usuarios para empezar. Podemos recomendarte más usuario
msgid "Followed users"
msgstr "Usuarios seguidos"
#: src/view/screens/PreferencesHomeFeed.tsx:145
#: src/view/screens/PreferencesHomeFeed.tsx:151
msgid "Followed users only"
msgstr "Solo usuarios seguidos"
@@ -917,11 +940,11 @@ msgstr "Por razones de seguridad, tendremos que enviarte un código de confirmac
msgid "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."
msgstr "Por razones de seguridad, no podrás volver a verla. Si pierdes esta contraseña, tendrás que generar una nueva."
#: src/view/com/auth/login/LoginForm.tsx:232
#: src/view/com/auth/login/LoginForm.tsx:236
msgid "Forgot"
msgstr "Lo olvidé"
#: src/view/com/auth/login/LoginForm.tsx:229
#: src/view/com/auth/login/LoginForm.tsx:233
msgid "Forgot password"
msgstr "Olvidé mi contraseña"
@@ -953,7 +976,7 @@ msgid "Go Back"
msgstr "Regresar"
#: src/view/com/auth/login/ForgotPasswordForm.tsx:181
#: src/view/com/auth/login/LoginForm.tsx:279
#: src/view/com/auth/login/LoginForm.tsx:283
#: src/view/com/auth/login/SetNewPasswordForm.tsx:163
msgid "Go to next"
msgstr "Ir al siguiente"
@@ -978,11 +1001,11 @@ msgstr "Ocultar"
#: src/view/com/util/forms/PostDropdownBtn.tsx:173
msgid "Hide post"
msgstr ""
msgstr "Ocultar publicación"
#: src/view/com/util/forms/PostDropdownBtn.tsx:177
msgid "Hide this post?"
msgstr ""
msgstr "¿Ocultar esta publicación?"
#: src/view/com/notifications/FeedItem.tsx:316
msgid "Hide user list"
@@ -1016,7 +1039,7 @@ msgid "Home"
msgstr "Página inicial"
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/PreferencesHomeFeed.tsx:101
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
msgstr "Preferencias de noticias de la página inicial"
@@ -1051,7 +1074,7 @@ msgstr "Texto alt de la imagen"
msgid "Image options"
msgstr "Opciones de la imagen"
#: src/view/com/auth/login/LoginForm.tsx:113
#: src/view/com/auth/login/LoginForm.tsx:115
msgid "Invalid username or password"
msgstr "Nombre de usuario o contraseña no válidos"
@@ -1202,10 +1225,6 @@ msgstr "Visibilidad de desconexión"
msgid "Login to account that is not listed"
msgstr "Acceder a una cuenta que no está en la lista"
#: src/view/screens/ProfileFeed.tsx:472
#~ msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
#~ msgstr "Parece que este canal de noticias sólo está disponible para usuarios con una cuenta Bluesky. Por favor, ¡regístrate o inicia sesión para ver este canal!"
#: src/view/com/modals/LinkWarning.tsx:63
msgid "Make sure this is where you intend to go!"
msgstr "¡Asegúrate de que es aquí a donde pretendes ir!"
@@ -1256,6 +1275,10 @@ msgstr "Más canales de noticias"
msgid "More options"
msgstr "Más opciones"
#: src/view/screens/PreferencesThreads.tsx:82
msgid "Most-liked replies first"
msgstr ""
#: src/view/com/profile/ProfileHeader.tsx:370
msgid "Mute Account"
msgstr "Silenciar la cuenta"
@@ -1313,6 +1336,11 @@ msgstr "Mis canales de noticias guardados"
msgid "Name"
msgstr "Nombre"
#: src/view/com/modals/EmbedConsent.tsx:107
#: src/view/com/modals/EmbedConsent.tsx:123
msgid "Never load embeds from {0}"
msgstr ""
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:72
msgid "Never lose access to your followers and data."
msgstr "No pierdas nunca el acceso a tus seguidores y datos."
@@ -1336,10 +1364,14 @@ msgstr "Publicación nueva"
msgid "New Post"
msgstr "Publicación nueva"
#: src/view/screens/PreferencesThreads.tsx:79
msgid "Newest replies first"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:282
#: src/view/com/auth/login/LoginForm.tsx:286
#: src/view/com/auth/login/SetNewPasswordForm.tsx:156
#: src/view/com/auth/login/SetNewPasswordForm.tsx:166
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:79
@@ -1350,10 +1382,12 @@ msgstr "Siguiente"
msgid "Next image"
msgstr "Imagen nueva"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:191
#: src/view/screens/PreferencesHomeFeed.tsx:226
#: src/view/screens/PreferencesHomeFeed.tsx:263
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:197
#: src/view/screens/PreferencesHomeFeed.tsx:232
#: src/view/screens/PreferencesHomeFeed.tsx:269
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "No"
msgstr "No"
@@ -1378,6 +1412,10 @@ msgstr "No se han encontrado resultados para \"{query}\""
msgid "No results found for {query}"
msgstr "No se han encontrado resultados para {query}"
#: src/view/com/modals/EmbedConsent.tsx:129
msgid "No thanks"
msgstr ""
#: src/view/com/modals/Threadgate.tsx:82
msgid "Nobody"
msgstr "Nadie"
@@ -1407,7 +1445,11 @@ msgstr "¡Qué problema!"
msgid "Okay"
msgstr "Está bien"
#: src/view/com/composer/Composer.tsx:358
#: src/view/screens/PreferencesThreads.tsx:78
msgid "Oldest replies first"
msgstr ""
#: src/view/com/composer/Composer.tsx:363
msgid "One or more images is missing alt text."
msgstr "Falta el texto alternativo en una o varias imágenes."
@@ -1415,6 +1457,11 @@ msgstr "Falta el texto alternativo en una o varias imágenes."
msgid "Only {0} can reply."
msgstr "Solo {0} puede responder."
#: src/view/com/composer/Composer.tsx:468
#: src/view/com/composer/Composer.tsx:469
msgid "Open emoji picker"
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr "Abrir navegación"
@@ -1423,6 +1470,10 @@ msgstr "Abrir navegación"
msgid "Opens configurable language settings"
msgstr "Abrir la configuración del idioma que se puede ajustar"
#: src/view/screens/Settings.tsx:587
msgid "Opens external embeds settings"
msgstr ""
#: src/view/shell/desktop/RightNav.tsx:156
#: src/view/shell/Drawer.tsx:641
msgid "Opens list of invite codes"
@@ -1440,7 +1491,7 @@ msgstr "Abre la configuración de moderación"
msgid "Opens screen with all saved feeds"
msgstr "Abre la pantalla con todas las noticias guardadas"
#: src/view/screens/Settings.tsx:581
#: src/view/screens/Settings.tsx:614
msgid "Opens the app password settings page"
msgstr "Abre la página de configuración de la contraseña de la app"
@@ -1448,11 +1499,11 @@ msgstr "Abre la página de configuración de la contraseña de la app"
msgid "Opens the home feed preferences"
msgstr "Abre las preferencias de noticias de la página inicial"
#: src/view/screens/Settings.tsx:664
#: src/view/screens/Settings.tsx:697
msgid "Opens the storybook page"
msgstr "Abre la página del libro de cuentos"
#: src/view/screens/Settings.tsx:644
#: src/view/screens/Settings.tsx:677
msgid "Opens the system log page"
msgstr "Abre la página de la bitácora del sistema"
@@ -1483,7 +1534,7 @@ msgstr "Página no encontrada"
#: src/view/com/auth/create/Step2.tsx:122
#: src/view/com/auth/create/Step2.tsx:132
#: src/view/com/auth/login/LoginForm.tsx:217
#: src/view/com/auth/login/LoginForm.tsx:221
#: src/view/com/auth/login/SetNewPasswordForm.tsx:130
#: src/view/com/modals/DeleteAccount.tsx:191
msgid "Password"
@@ -1505,6 +1556,19 @@ msgstr "Imágenes destinadas a adultos."
msgid "Pinned Feeds"
msgstr "Canales de noticias anclados"
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:111
msgid "Play {0}"
msgstr ""
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:54
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:55
msgid "Play Video"
msgstr ""
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:110
msgid "Plays the GIF"
msgstr ""
#: src/view/com/auth/create/state.ts:116
msgid "Please choose your handle."
msgstr "Por favor, elige tu identificador."
@@ -1532,18 +1596,13 @@ msgstr "Introduce tu contraseña, también:"
#: src/view/com/modals/AppealLabel.tsx:72
#: src/view/com/modals/AppealLabel.tsx:75
msgid "Please tell us why you think this content warning was incorrectly applied!"
msgstr ""
msgstr "Por favor, dinos por qué crees que esta advertencia de contenido se ha aplicado incorrectamente!"
#: src/view/com/modals/AppealLabel.tsx:72
#: src/view/com/modals/AppealLabel.tsx:75
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr "Por favor, dinos por qué crees que esta decisión fue incorrecta."
#: src/view/com/composer/Composer.tsx:214
#: src/view/com/composer/Composer.tsx:215
msgid "Please wait for your link card to finish loading"
msgstr ""
msgstr "Por favor, espera a que tu tarjeta de enlace termine de cargarse"
#: src/view/com/composer/Composer.tsx:341
#: src/view/com/composer/Composer.tsx:346
#: src/view/com/post-thread/PostThread.tsx:225
#: src/view/screens/PostThread.tsx:80
msgid "Post"
@@ -1581,16 +1640,17 @@ msgstr "Imagen previa"
msgid "Primary Language"
msgstr "Lenguajes primarios"
#: src/view/screens/PreferencesThreads.tsx:91
#: src/view/screens/PreferencesThreads.tsx:97
msgid "Prioritize Your Follows"
msgstr "Priorizar los usuarios a los que sigue"
#: src/view/screens/Settings.tsx:570
#: src/view/shell/desktop/RightNav.tsx:84
msgid "Privacy"
msgstr "Privacidad"
#: src/view/screens/PrivacyPolicy.tsx:29
#: src/view/screens/Settings.tsx:750
#: src/view/screens/Settings.tsx:783
#: src/view/shell/Drawer.tsx:262
msgid "Privacy Policy"
msgstr "Política de privacidad"
@@ -1607,7 +1667,7 @@ msgstr "Procesando..."
msgid "Profile"
msgstr "Perfil"
#: src/view/screens/Settings.tsx:808
#: src/view/screens/Settings.tsx:841
msgid "Protect your account by verifying your email."
msgstr "Protege tu cuenta verificando tu correo electrónico."
@@ -1628,6 +1688,10 @@ msgstr "Citar una publicación"
msgid "Quote Post"
msgstr "Citar una publicación"
#: src/view/screens/PreferencesThreads.tsx:86
msgid "Random (aka \"Poster's Roulette\")"
msgstr ""
#: src/view/com/modals/EditImage.tsx:236
msgid "Ratios"
msgstr "Proporciones"
@@ -1695,7 +1759,7 @@ msgstr "Respuestas"
msgid "Replies to this thread are disabled"
msgstr "Las respuestas a este hilo están desactivadas"
#: src/view/screens/PreferencesHomeFeed.tsx:135
#: src/view/screens/PreferencesHomeFeed.tsx:141
msgid "Reply Filters"
msgstr "Filtros de respuestas"
@@ -1738,6 +1802,10 @@ msgstr "Vuelto a publicar por"
msgid "Request Change"
msgstr "Solicitar un cambio"
#: src/view/screens/Settings.tsx:422
msgid "Require alt text before posting"
msgstr ""
#: src/view/com/auth/create/Step2.tsx:68
msgid "Required for this provider"
msgstr "Requerido para este proveedor"
@@ -1746,7 +1814,7 @@ msgstr "Requerido para este proveedor"
msgid "Reset code"
msgstr "Restablecer el código"
#: src/view/screens/Settings.tsx:686
#: src/view/screens/Settings.tsx:719
msgid "Reset onboarding state"
msgstr "Restablecer el estado de incorporación"
@@ -1754,28 +1822,27 @@ msgstr "Restablecer el estado de incorporación"
msgid "Reset password"
msgstr "Restablecer la contraseña"
#: src/view/screens/Settings.tsx:676
#: src/view/screens/Settings.tsx:709
msgid "Reset preferences state"
msgstr "Restablecer el estado de preferencias"
#: src/view/screens/Settings.tsx:684
#: src/view/screens/Settings.tsx:717
msgid "Resets the onboarding state"
msgstr "Restablece el estado de incorporación"
#: src/view/screens/Settings.tsx:674
#: src/view/screens/Settings.tsx:707
msgid "Resets the preferences state"
msgstr "Restablecer el estado de preferencias"
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/login/LoginForm.tsx:259
#: src/view/com/auth/login/LoginForm.tsx:262
#: src/view/com/auth/login/LoginForm.tsx:263
#: src/view/com/auth/login/LoginForm.tsx:266
#: src/view/com/util/error/ErrorMessage.tsx:55
#: src/view/com/util/error/ErrorScreen.tsx:65
msgid "Retry"
msgstr "Volver a intentar"
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/BirthDateSettings.tsx:94
#: src/view/com/modals/BirthDateSettings.tsx:97
#: src/view/com/modals/ChangeHandle.tsx:173
@@ -1821,7 +1888,7 @@ msgstr "Buscar"
#: src/view/com/auth/LoggedOut.tsx:104
#: src/view/com/auth/LoggedOut.tsx:105
msgid "Search for users"
msgstr ""
msgstr "Buscar usuarios"
#: src/view/com/modals/ChangeEmail.tsx:110
msgid "Security Step Required"
@@ -1839,7 +1906,7 @@ msgstr "Seleccionar Bluesky Social"
msgid "Select from an existing account"
msgstr "Selecciona de una cuenta existente"
#: src/view/com/auth/login/LoginForm.tsx:143
#: src/view/com/auth/login/LoginForm.tsx:147
msgid "Select service"
msgstr "Selecciona el servicio"
@@ -1880,23 +1947,23 @@ msgstr "Enviar el informe"
msgid "Set new password"
msgstr "Establecer la contraseña nueva"
#: src/view/screens/PreferencesHomeFeed.tsx:216
#: src/view/screens/PreferencesHomeFeed.tsx:222
msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
msgstr "Establece este ajuste en \"No\" para ocultar todas las publicaciones de citas de tus noticias. Las repeticiones seguirán siendo visibles."
#: src/view/screens/PreferencesHomeFeed.tsx:113
#: src/view/screens/PreferencesHomeFeed.tsx:119
msgid "Set this setting to \"No\" to hide all replies from your feed."
msgstr "Establece este ajuste en \"No\" para ocultar todas las respuestas de tus noticias."
#: src/view/screens/PreferencesHomeFeed.tsx:182
#: src/view/screens/PreferencesHomeFeed.tsx:188
msgid "Set this setting to \"No\" to hide all reposts from your feed."
msgstr "Establece este ajuste en \"No\" para ocultar todas las veces que se han vuelto a publicar desde tus noticias."
#: src/view/screens/PreferencesThreads.tsx:116
#: src/view/screens/PreferencesThreads.tsx:122
msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
msgstr "Establece este ajuste en \"Sí\" para mostrar las respuestas en una vista de hilos. Se trata de una función experimental."
#: src/view/screens/PreferencesHomeFeed.tsx:252
#: src/view/screens/PreferencesHomeFeed.tsx:258
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
msgstr "Establece este ajuste en \"Sí\" para mostrar muestras de tus noticias guardadas en tu siguiente canal de noticias. Se trata de una función experimental."
@@ -1930,23 +1997,27 @@ msgstr "Mostrar"
msgid "Show anyway"
msgstr "Mostrar de todas maneras"
#: src/view/screens/PreferencesHomeFeed.tsx:249
#: src/view/com/modals/EmbedConsent.tsx:87
msgid "Show embeds from {0}"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:255
msgid "Show Posts from My Feeds"
msgstr "Mostrar publicaciones de mis noticias"
#: src/view/screens/PreferencesHomeFeed.tsx:213
#: src/view/screens/PreferencesHomeFeed.tsx:219
msgid "Show Quote Posts"
msgstr "Mostrar publicaciones de citas"
#: src/view/screens/PreferencesHomeFeed.tsx:110
#: src/view/screens/PreferencesHomeFeed.tsx:116
msgid "Show Replies"
msgstr "Mostrar respuestas"
#: src/view/screens/PreferencesThreads.tsx:94
#: src/view/screens/PreferencesThreads.tsx:100
msgid "Show replies by people you follow before all other replies."
msgstr "Mostrar las respuestas de las personas a quienes sigues antes que el resto de respuestas."
#: src/view/screens/PreferencesHomeFeed.tsx:179
#: src/view/screens/PreferencesHomeFeed.tsx:185
msgid "Show Reposts"
msgstr "Mostrar publicaciones que se han publicado nuevamente"
@@ -1983,7 +2054,7 @@ msgstr "Iniciar sesión como {0}"
msgid "Sign in as..."
msgstr "Iniciar sesión como ..."
#: src/view/com/auth/login/LoginForm.tsx:130
#: src/view/com/auth/login/LoginForm.tsx:134
msgid "Sign into"
msgstr "Iniciar sesión en"
@@ -2037,11 +2108,11 @@ msgstr "Cuadrado"
msgid "Staging"
msgstr "Puesta en escena"
#: src/view/screens/Settings.tsx:730
#: src/view/screens/Settings.tsx:763
msgid "Status page"
msgstr "Página de estado"
#: src/view/screens/Settings.tsx:666
#: src/view/screens/Settings.tsx:699
msgid "Storybook"
msgstr "Libro de cuentos"
@@ -2070,7 +2141,7 @@ msgstr "Soporte"
msgid "Switch Account"
msgstr "Cambiar a otra cuenta"
#: src/view/screens/Settings.tsx:646
#: src/view/screens/Settings.tsx:679
msgid "System log"
msgstr "Bitácora del sistema"
@@ -2082,7 +2153,7 @@ msgstr "Alto"
msgid "Terms"
msgstr "Condiciones"
#: src/view/screens/Settings.tsx:744
#: src/view/screens/Settings.tsx:777
#: src/view/screens/TermsOfService.tsx:29
#: src/view/shell/Drawer.tsx:256
msgid "Terms of Service"
@@ -2125,10 +2196,6 @@ msgstr "Las condiciones de servicio se han trasladado a"
msgid "There was an unexpected issue in the application. Please let us know if this happened to you!"
msgstr "Se ha producido un problema inesperado en la aplicación. Por favor, ¡avísanos si te ha ocurrido esto!"
#: src/view/com/util/moderation/LabelInfo.tsx:45
#~ msgid "This {0} has been labeled."
#~ msgstr "Este {0} ha sido etiquetado."
#: src/view/com/util/moderation/ScreenHider.tsx:88
msgid "This {screenDescription} has been flagged:"
msgstr "Esta {screenDescription} ha sido marcada:"
@@ -2137,6 +2204,10 @@ msgstr "Esta {screenDescription} ha sido marcada:"
msgid "This account has requested that users sign in to view their profile."
msgstr "Esta cuenta ha solicitado que los usuarios inicien sesión para ver su perfil."
#: src/view/com/modals/EmbedConsent.tsx:68
msgid "This content is hosted by {0}. Do you want to enable external media?"
msgstr ""
#: src/view/com/posts/FeedErrorMessage.tsx:107
msgid "This content is not viewable without a Bluesky account."
msgstr "Este contenido no se puede ver sin una cuenta Bluesky."
@@ -2171,14 +2242,14 @@ msgstr "Esta advertencia sólo está disponible para las publicaciones con medio
#: src/view/com/util/forms/PostDropdownBtn.tsx:178
msgid "This will hide this post from your feeds."
msgstr ""
msgstr "Esto ocultará esta entrada de tus contenidos."
#: src/view/screens/PreferencesThreads.tsx:53
#: src/view/screens/Settings.tsx:503
msgid "Thread Preferences"
msgstr "Preferencias de hilos"
#: src/view/screens/PreferencesThreads.tsx:113
#: src/view/screens/PreferencesThreads.tsx:119
msgid "Threaded Mode"
msgstr "Modo con hilos"
@@ -2210,7 +2281,7 @@ msgstr "Desactivar la opción de silenciar la lista"
#: src/view/com/auth/create/CreateAccount.tsx:65
#: src/view/com/auth/login/Login.tsx:76
#: src/view/com/auth/login/LoginForm.tsx:117
#: src/view/com/auth/login/LoginForm.tsx:120
msgid "Unable to contact your service. Please check your Internet connection."
msgstr "No se puede contactar con tu servicio. Comprueba tu conexión a Internet."
@@ -2228,7 +2299,7 @@ msgstr "Desbloquear una cuenta"
msgid "Undo repost"
msgstr "Deshacer esta publicación"
#: src/view/com/auth/create/state.ts:210
#: src/view/com/auth/create/state.ts:216
msgid "Unfortunately, you do not meet the requirements to create an account."
msgstr "Lamentablemente, no cumples los requisitos para crear una cuenta."
@@ -2284,8 +2355,8 @@ msgstr "Identificador del usuario"
msgid "User Lists"
msgstr "Listas de usuarios"
#: src/view/com/auth/login/LoginForm.tsx:170
#: src/view/com/auth/login/LoginForm.tsx:188
#: src/view/com/auth/login/LoginForm.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:192
msgid "Username or email address"
msgstr "Nombre de usuario o dirección de correo electrónico"
@@ -2301,15 +2372,15 @@ msgstr "usuarios seguidos por <0/>"
msgid "Users in \"{0}\""
msgstr "Usuarios en «{0}»"
#: src/view/screens/Settings.tsx:769
#: src/view/screens/Settings.tsx:802
msgid "Verify email"
msgstr "Verificar el correo electrónico"
#: src/view/screens/Settings.tsx:794
#: src/view/screens/Settings.tsx:827
msgid "Verify my email"
msgstr "Verificar mi correo electrónico"
#: src/view/screens/Settings.tsx:803
#: src/view/screens/Settings.tsx:836
msgid "Verify My Email"
msgstr "Verificar mi correo electrónico"
@@ -2350,13 +2421,9 @@ msgstr "Bienvenido a <0>Bluesky</0>"
msgid "What is the issue with this {collectionName}?"
msgstr "¿Cuál es el problema con esta {collectionName}?"
#: src/view/com/auth/SplashScreen.tsx:34
#~ msgid "What's next?"
#~ msgstr "¿Qué sigue?"
#: src/view/com/auth/SplashScreen.tsx:34
msgid "What's up?"
msgstr ""
msgstr "¿Qué hay de nuevo?"
#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:78
msgid "Which languages are used in this post?"
@@ -2375,7 +2442,7 @@ msgstr "Quién puede responder"
msgid "Wide"
msgstr "Ancho"
#: src/view/com/composer/Composer.tsx:413
#: src/view/com/composer/Composer.tsx:418
msgid "Write post"
msgstr "Redactar una publicación"
@@ -2383,10 +2450,12 @@ msgstr "Redactar una publicación"
msgid "Write your reply"
msgstr "Redactar tu respuesta"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:192
#: src/view/screens/PreferencesHomeFeed.tsx:227
#: src/view/screens/PreferencesHomeFeed.tsx:262
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:198
#: src/view/screens/PreferencesHomeFeed.tsx:233
#: src/view/screens/PreferencesHomeFeed.tsx:268
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "Yes"
msgstr "Sí"
File diff suppressed because it is too large Load Diff
+181 -95
View File
@@ -88,7 +88,7 @@ msgstr "ऐप का एक नया संस्करण उपलब्ध
msgid "Accessibility"
msgstr "प्रवेर्शयोग्यता"
#: src/view/com/auth/login/LoginForm.tsx:159
#: src/view/com/auth/login/LoginForm.tsx:163
#: src/view/screens/Settings.tsx:286
msgid "Account"
msgstr "अकाउंट"
@@ -118,6 +118,7 @@ msgstr "अकाउंट जोड़ें"
#: src/view/com/composer/photos/Gallery.tsx:119
#: src/view/com/composer/photos/Gallery.tsx:180
#: src/view/com/modals/AltImage.tsx:93
msgid "Add alt text"
msgstr "इस फ़ोटो में विवरण जोड़ें"
@@ -130,11 +131,11 @@ msgstr "विवरण जोड़ें"
msgid "Add details to report"
msgstr "रिपोर्ट करने के लिए विवरण जोड़ें"
#: src/view/com/composer/Composer.tsx:442
#: src/view/com/composer/Composer.tsx:447
msgid "Add link card"
msgstr "लिंक कार्ड जोड़ें"
#: src/view/com/composer/Composer.tsx:445
#: src/view/com/composer/Composer.tsx:450
msgid "Add link card:"
msgstr "लिंक कार्ड जोड़ें:"
@@ -155,7 +156,7 @@ msgstr "इस फ़ीड को सहेजें"
msgid "Added to list"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:164
#: src/view/screens/PreferencesHomeFeed.tsx:170
msgid "Adjust the number of likes a reply must have to be shown in your feed."
msgstr "पसंद की संख्या को समायोजित करें उत्तर को आपके फ़ीड में दिखाया जाना चाहिए।।"
@@ -163,7 +164,7 @@ msgstr "पसंद की संख्या को समायोजित
msgid "Adult Content"
msgstr "वयस्क सामग्री"
#: src/view/screens/Settings.tsx:569
#: src/view/screens/Settings.tsx:602
msgid "Advanced"
msgstr "विकसित"
@@ -196,7 +197,7 @@ msgstr "और"
msgid "App Language"
msgstr "ऐप भाषा"
#: src/view/screens/Settings.tsx:589
#: src/view/screens/Settings.tsx:622
msgid "App passwords"
msgstr "ऐप पासवर्ड"
@@ -236,7 +237,7 @@ msgstr "दिखावट"
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr "क्या आप वाकई ऐप पासवर्ड \"{name}\" हटाना चाहते हैं?"
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Are you sure you'd like to discard this draft?"
msgstr "क्या आप वाकई इस ड्राफ्ट को हटाना करना चाहेंगे?"
@@ -259,7 +260,7 @@ msgstr "कलात्मक या गैर-कामुक नग्नत
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:250
#: src/view/com/auth/login/LoginForm.tsx:254
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
#: src/view/com/modals/report/InputIssueDetails.tsx:46
#: src/view/com/post-thread/PostThread.tsx:388
@@ -355,7 +356,7 @@ msgstr ""
msgid "Bluesky.Social"
msgstr "Bluesky.Social"
#: src/view/screens/Settings.tsx:718
#: src/view/screens/Settings.tsx:751
msgid "Build version {0} {1}"
msgstr "Build version {0} {1}"
@@ -373,9 +374,8 @@ msgstr "कैमरा"
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr "केवल अक्षर, संख्या, रिक्त स्थान, डैश और अंडरस्कोर हो सकते हैं। कम से कम 4 अक्षर लंबा होना चाहिए, लेकिन 32 अक्षरों से अधिक लंबा नहीं होना चाहिए।।"
#: src/view/com/composer/Composer.tsx:289
#: src/view/com/composer/Composer.tsx:292
#: src/view/com/modals/AltImage.tsx:128
#: src/view/com/composer/Composer.tsx:294
#: src/view/com/composer/Composer.tsx:297
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
#: src/view/com/modals/Confirm.tsx:88
@@ -399,8 +399,8 @@ msgid "Cancel account deletion"
msgstr "अकाउंट बंद मत करो"
#: src/view/com/modals/AltImage.tsx:123
msgid "Cancel add image alt text"
msgstr "ऑल्ट टेक्स्ट मत जोड़ें"
#~ msgid "Cancel add image alt text"
#~ msgstr "ऑल्ट टेक्स्ट मत जोड़ें"
#: src/view/com/modals/ChangeHandle.tsx:149
msgid "Cancel change handle"
@@ -431,8 +431,8 @@ msgstr "प्रतीक्षा सूची पंजीकरण मत
msgid "Change"
msgstr "परिवर्तन"
#: src/view/screens/Settings.tsx:601
#: src/view/screens/Settings.tsx:610
#: src/view/screens/Settings.tsx:634
#: src/view/screens/Settings.tsx:643
msgid "Change handle"
msgstr "हैंडल बदलें"
@@ -476,19 +476,19 @@ msgstr "उन एल्गोरिदम का चयन करें जो
msgid "Choose your password"
msgstr "अपना पासवर्ड चुनें"
#: src/view/screens/Settings.tsx:694
#: src/view/screens/Settings.tsx:727
msgid "Clear all legacy storage data"
msgstr ""
#: src/view/screens/Settings.tsx:696
#: src/view/screens/Settings.tsx:729
msgid "Clear all legacy storage data (restart after this)"
msgstr ""
#: src/view/screens/Settings.tsx:706
#: src/view/screens/Settings.tsx:739
msgid "Clear all storage data"
msgstr ""
#: src/view/screens/Settings.tsx:708
#: src/view/screens/Settings.tsx:741
msgid "Clear all storage data (restart after this)"
msgstr ""
@@ -529,8 +529,8 @@ msgstr "जवाब लिखो"
#: src/view/com/modals/Confirm.tsx:75
#: src/view/com/modals/SelfLabel.tsx:154
#: src/view/com/modals/VerifyEmail.tsx:225
#: src/view/screens/PreferencesHomeFeed.tsx:299
#: src/view/screens/PreferencesThreads.tsx:153
#: src/view/screens/PreferencesHomeFeed.tsx:305
#: src/view/screens/PreferencesThreads.tsx:159
msgid "Confirm"
msgstr "हो गया"
@@ -554,7 +554,7 @@ msgid "Confirmation code"
msgstr "OTP कोड"
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:269
#: src/view/com/auth/login/LoginForm.tsx:273
msgid "Connecting..."
msgstr "कनेक्टिंग ..।"
@@ -644,7 +644,11 @@ msgstr "बनाया गया {0}"
msgid "Custom domain"
msgstr "कस्टम डोमेन"
#: src/view/screens/Settings.tsx:615
#: src/view/screens/PreferencesExternalEmbeds.tsx:55
msgid "Customize media from external sites."
msgstr ""
#: src/view/screens/Settings.tsx:648
msgid "Danger Zone"
msgstr "खतरा क्षेत्र"
@@ -652,7 +656,7 @@ msgstr "खतरा क्षेत्र"
#~ msgid "Dark"
#~ msgstr "डार्क मोड"
#: src/view/screens/Settings.tsx:622
#: src/view/screens/Settings.tsx:655
msgid "Delete account"
msgstr "खाता हटाएं"
@@ -674,7 +678,7 @@ msgstr "सूची हटाएँ"
msgid "Delete my account"
msgstr "मेरा खाता हटाएं"
#: src/view/screens/Settings.tsx:632
#: src/view/screens/Settings.tsx:665
msgid "Delete my account…"
msgstr "मेरा खाता हटाएं…"
@@ -701,19 +705,19 @@ msgstr "विवरण"
msgid "Dev Server"
msgstr "देव सर्वर"
#: src/view/screens/Settings.tsx:637
#: src/view/screens/Settings.tsx:670
msgid "Developer Tools"
msgstr "डेवलपर उपकरण"
#: src/view/com/composer/Composer.tsx:210
#: src/view/com/composer/Composer.tsx:211
msgid "Did you want to say anything?"
msgstr ""
#: src/view/com/composer/Composer.tsx:143
#: src/view/com/composer/Composer.tsx:144
msgid "Discard"
msgstr ""
#: src/view/com/composer/Composer.tsx:137
#: src/view/com/composer/Composer.tsx:138
msgid "Discard draft"
msgstr "ड्राफ्ट हटाएं"
@@ -738,6 +742,7 @@ msgid "Domain verified!"
msgstr "डोमेन सत्यापित!"
#: src/view/com/auth/onboarding/RecommendedFollows.tsx:86
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/ContentFilteringSettings.tsx:88
#: src/view/com/modals/ContentFilteringSettings.tsx:96
#: src/view/com/modals/crop-image/CropImage.web.tsx:152
@@ -747,8 +752,8 @@ msgstr "डोमेन सत्यापित!"
#: src/view/com/modals/Threadgate.tsx:129
#: src/view/com/modals/Threadgate.tsx:132
#: src/view/com/modals/UserAddRemoveLists.tsx:79
#: src/view/screens/PreferencesHomeFeed.tsx:302
#: src/view/screens/PreferencesThreads.tsx:156
#: src/view/screens/PreferencesHomeFeed.tsx:308
#: src/view/screens/PreferencesThreads.tsx:162
msgid "Done"
msgstr "खत्म"
@@ -809,7 +814,15 @@ msgstr "ईमेल अपडेट किया गया"
msgid "Email:"
msgstr "ईमेल:"
#: src/view/screens/PreferencesHomeFeed.tsx:138
#: src/view/com/modals/EmbedConsent.tsx:113
msgid "Enable {0} only"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:97
msgid "Enable External Media"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:144
msgid "Enable this setting to only see replies between people you follow."
msgstr "इस सेटिंग को केवल उन लोगों के बीच जवाब देखने में सक्षम करें जिन्हें आप फॉलो करते हैं।।"
@@ -853,6 +866,20 @@ msgstr ""
msgid "Expand alt text"
msgstr "ऑल्ट टेक्स्ट"
#: src/view/com/modals/EmbedConsent.tsx:64
msgid "External Media"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:75
#: src/view/screens/PreferencesExternalEmbeds.tsx:66
msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button."
msgstr ""
#: src/view/screens/PreferencesExternalEmbeds.tsx:52
#: src/view/screens/Settings.tsx:595
msgid "External Media Preferences"
msgstr ""
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:109
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:141
msgid "Failed to load recommended feeds"
@@ -900,7 +927,7 @@ msgstr ""
msgid "Finding similar accounts..."
msgstr "मिलते-जुलते खाते ढूँढना"
#: src/view/screens/PreferencesHomeFeed.tsx:102
#: src/view/screens/PreferencesHomeFeed.tsx:108
msgid "Fine-tune the content you see on your home screen."
msgstr "अपने मुख्य फ़ीड की स्क्रीन पर दिखाई देने वाली सामग्री को ठीक करें।।"
@@ -920,7 +947,7 @@ msgstr "आरंभ करने के लिए कुछ उपयोगक
msgid "Followed users"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:145
#: src/view/screens/PreferencesHomeFeed.tsx:151
msgid "Followed users only"
msgstr "केवल वे यूजर को फ़ॉलो किया गया"
@@ -949,11 +976,11 @@ msgstr "सुरक्षा कारणों के लिए, हमें
msgid "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."
msgstr "सुरक्षा कारणों के लिए, आप इसे फिर से देखने में सक्षम नहीं होंगे। यदि आप इस पासवर्ड को खो देते हैं, तो आपको एक नया उत्पन्न करना होगा।।"
#: src/view/com/auth/login/LoginForm.tsx:232
#: src/view/com/auth/login/LoginForm.tsx:236
msgid "Forgot"
msgstr "भूल"
#: src/view/com/auth/login/LoginForm.tsx:229
#: src/view/com/auth/login/LoginForm.tsx:233
msgid "Forgot password"
msgstr "पासवर्ड भूल गए"
@@ -985,7 +1012,7 @@ msgid "Go Back"
msgstr "वापस जाओ"
#: src/view/com/auth/login/ForgotPasswordForm.tsx:181
#: src/view/com/auth/login/LoginForm.tsx:279
#: src/view/com/auth/login/LoginForm.tsx:283
#: src/view/com/auth/login/SetNewPasswordForm.tsx:163
msgid "Go to next"
msgstr "अगला"
@@ -1056,7 +1083,7 @@ msgid "Home"
msgstr "होम फीड"
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/PreferencesHomeFeed.tsx:101
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
msgstr "होम फ़ीड प्राथमिकताएं"
@@ -1096,7 +1123,7 @@ msgstr "छवि विकल्प"
#~ msgid "In Your Network"
#~ msgstr "आपके नेटवर्क में"
#: src/view/com/auth/login/LoginForm.tsx:113
#: src/view/com/auth/login/LoginForm.tsx:115
msgid "Invalid username or password"
msgstr "अवैध उपयोगकर्ता नाम या पासवर्ड"
@@ -1321,6 +1348,10 @@ msgstr "अधिक विकल्प"
#~ msgid "More post options"
#~ msgstr "पोस्ट विकल्प"
#: src/view/screens/PreferencesThreads.tsx:82
msgid "Most-liked replies first"
msgstr ""
#: src/view/com/profile/ProfileHeader.tsx:370
msgid "Mute Account"
msgstr "खाता म्यूट करें"
@@ -1382,6 +1413,11 @@ msgstr "मेरी फ़ीड"
msgid "Name"
msgstr "नाम"
#: src/view/com/modals/EmbedConsent.tsx:107
#: src/view/com/modals/EmbedConsent.tsx:123
msgid "Never load embeds from {0}"
msgstr ""
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:72
msgid "Never lose access to your followers and data."
msgstr "अपने फ़ॉलोअर्स और डेटा तक पहुंच कभी न खोएं।"
@@ -1405,10 +1441,14 @@ msgstr "नई पोस्ट"
msgid "New Post"
msgstr "नई पोस्ट"
#: src/view/screens/PreferencesThreads.tsx:79
msgid "Newest replies first"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:282
#: src/view/com/auth/login/LoginForm.tsx:286
#: src/view/com/auth/login/SetNewPasswordForm.tsx:156
#: src/view/com/auth/login/SetNewPasswordForm.tsx:166
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:79
@@ -1419,10 +1459,12 @@ msgstr "अगला"
msgid "Next image"
msgstr "अगली फोटो"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:191
#: src/view/screens/PreferencesHomeFeed.tsx:226
#: src/view/screens/PreferencesHomeFeed.tsx:263
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:197
#: src/view/screens/PreferencesHomeFeed.tsx:232
#: src/view/screens/PreferencesHomeFeed.tsx:269
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "No"
msgstr "नहीं"
@@ -1452,6 +1494,10 @@ msgstr "\"{query}\" के लिए कोई परिणाम नहीं
msgid "No results found for {query}"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:129
msgid "No thanks"
msgstr ""
#: src/view/com/modals/Threadgate.tsx:82
msgid "Nobody"
msgstr ""
@@ -1493,7 +1539,11 @@ msgstr "अरे नहीं!"
msgid "Okay"
msgstr "ठीक है"
#: src/view/com/composer/Composer.tsx:358
#: src/view/screens/PreferencesThreads.tsx:78
msgid "Oldest replies first"
msgstr ""
#: src/view/com/composer/Composer.tsx:363
msgid "One or more images is missing alt text."
msgstr "एक या अधिक छवियाँ alt पाठ याद आती हैं।।"
@@ -1501,6 +1551,11 @@ msgstr "एक या अधिक छवियाँ alt पाठ याद
msgid "Only {0} can reply."
msgstr ""
#: src/view/com/composer/Composer.tsx:468
#: src/view/com/composer/Composer.tsx:469
msgid "Open emoji picker"
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr "ओपन नेविगेशन"
@@ -1509,6 +1564,10 @@ msgstr "ओपन नेविगेशन"
msgid "Opens configurable language settings"
msgstr "भाषा सेटिंग्स खोलें"
#: src/view/screens/Settings.tsx:587
msgid "Opens external embeds settings"
msgstr ""
#: src/view/shell/desktop/RightNav.tsx:156
#: src/view/shell/Drawer.tsx:641
msgid "Opens list of invite codes"
@@ -1526,7 +1585,7 @@ msgstr "मॉडरेशन सेटिंग्स खोलें"
msgid "Opens screen with all saved feeds"
msgstr "सभी बचाया फ़ीड के साथ स्क्रीन खोलें"
#: src/view/screens/Settings.tsx:581
#: src/view/screens/Settings.tsx:614
msgid "Opens the app password settings page"
msgstr "ऐप पासवर्ड सेटिंग पेज खोलें"
@@ -1534,11 +1593,11 @@ msgstr "ऐप पासवर्ड सेटिंग पेज खोले
msgid "Opens the home feed preferences"
msgstr "होम फीड वरीयताओं को खोलता है"
#: src/view/screens/Settings.tsx:664
#: src/view/screens/Settings.tsx:697
msgid "Opens the storybook page"
msgstr "स्टोरीबुक पेज खोलें"
#: src/view/screens/Settings.tsx:644
#: src/view/screens/Settings.tsx:677
msgid "Opens the system log page"
msgstr "सिस्टम लॉग पेज खोलें"
@@ -1569,7 +1628,7 @@ msgstr "पृष्ठ नहीं मिला"
#: src/view/com/auth/create/Step2.tsx:122
#: src/view/com/auth/create/Step2.tsx:132
#: src/view/com/auth/login/LoginForm.tsx:217
#: src/view/com/auth/login/LoginForm.tsx:221
#: src/view/com/auth/login/SetNewPasswordForm.tsx:130
#: src/view/com/modals/DeleteAccount.tsx:191
msgid "Password"
@@ -1591,6 +1650,19 @@ msgstr "चित्र वयस्कों के लिए थे।।"
msgid "Pinned Feeds"
msgstr "पिन किया गया फ़ीड"
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:111
msgid "Play {0}"
msgstr ""
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:54
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:55
msgid "Play Video"
msgstr ""
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:110
msgid "Plays the GIF"
msgstr ""
#: src/view/com/auth/create/state.ts:116
msgid "Please choose your handle."
msgstr ""
@@ -1625,11 +1697,11 @@ msgstr ""
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:214
#: src/view/com/composer/Composer.tsx:215
msgid "Please wait for your link card to finish loading"
msgstr ""
#: src/view/com/composer/Composer.tsx:341
#: src/view/com/composer/Composer.tsx:346
#: src/view/com/post-thread/PostThread.tsx:225
#: src/view/screens/PostThread.tsx:80
msgid "Post"
@@ -1667,16 +1739,17 @@ msgstr "पिछली छवि"
msgid "Primary Language"
msgstr "प्राथमिक भाषा"
#: src/view/screens/PreferencesThreads.tsx:91
#: src/view/screens/PreferencesThreads.tsx:97
msgid "Prioritize Your Follows"
msgstr "अपने फ़ॉलोअर्स को प्राथमिकता दें"
#: src/view/screens/Settings.tsx:570
#: src/view/shell/desktop/RightNav.tsx:84
msgid "Privacy"
msgstr "गोपनीयता"
#: src/view/screens/PrivacyPolicy.tsx:29
#: src/view/screens/Settings.tsx:750
#: src/view/screens/Settings.tsx:783
#: src/view/shell/Drawer.tsx:262
msgid "Privacy Policy"
msgstr "गोपनीयता नीति"
@@ -1693,7 +1766,7 @@ msgstr "प्रसंस्करण..."
msgid "Profile"
msgstr "प्रोफ़ाइल"
#: src/view/screens/Settings.tsx:808
#: src/view/screens/Settings.tsx:841
msgid "Protect your account by verifying your email."
msgstr "अपने ईमेल को सत्यापित करके अपने खाते को सुरक्षित रखें।।"
@@ -1714,6 +1787,10 @@ msgstr "कोटे पोस्ट"
msgid "Quote Post"
msgstr "कोटे पोस्ट"
#: src/view/screens/PreferencesThreads.tsx:86
msgid "Random (aka \"Poster's Roulette\")"
msgstr ""
#: src/view/com/modals/EditImage.tsx:236
msgid "Ratios"
msgstr "अनुपात"
@@ -1786,7 +1863,7 @@ msgstr ""
msgid "Replies to this thread are disabled"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:135
#: src/view/screens/PreferencesHomeFeed.tsx:141
msgid "Reply Filters"
msgstr "फिल्टर"
@@ -1833,9 +1910,9 @@ msgstr "अनुरोध बदलें"
#~ msgid "Request to limit the visibility of my account"
#~ msgstr ""
#: src/view/screens/Settings.tsx:382
#~ msgid "Require alt text before posting"
#~ msgstr "पोस्ट करने से पहले वैकल्पिक टेक्स्ट की आवश्यकता है"
#: src/view/screens/Settings.tsx:422
msgid "Require alt text before posting"
msgstr "पोस्ट करने से पहले वैकल्पिक टेक्स्ट की आवश्यकता है"
#: src/view/com/auth/create/Step2.tsx:68
msgid "Required for this provider"
@@ -1845,7 +1922,7 @@ msgstr "इस प्रदाता के लिए आवश्यक"
msgid "Reset code"
msgstr "कोड रीसेट करें"
#: src/view/screens/Settings.tsx:686
#: src/view/screens/Settings.tsx:719
msgid "Reset onboarding state"
msgstr "ऑनबोर्डिंग स्टेट को रीसेट करें"
@@ -1853,22 +1930,22 @@ msgstr "ऑनबोर्डिंग स्टेट को रीसेट
msgid "Reset password"
msgstr "पासवर्ड रीसेट"
#: src/view/screens/Settings.tsx:676
#: src/view/screens/Settings.tsx:709
msgid "Reset preferences state"
msgstr "प्राथमिकताओं को रीसेट करें"
#: src/view/screens/Settings.tsx:684
#: src/view/screens/Settings.tsx:717
msgid "Resets the onboarding state"
msgstr "ऑनबोर्डिंग स्टेट को रीसेट करें"
#: src/view/screens/Settings.tsx:674
#: src/view/screens/Settings.tsx:707
msgid "Resets the preferences state"
msgstr "प्राथमिकताओं की स्थिति को रीसेट करें"
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/login/LoginForm.tsx:259
#: src/view/com/auth/login/LoginForm.tsx:262
#: src/view/com/auth/login/LoginForm.tsx:263
#: src/view/com/auth/login/LoginForm.tsx:266
#: src/view/com/util/error/ErrorMessage.tsx:55
#: src/view/com/util/error/ErrorScreen.tsx:65
msgid "Retry"
@@ -1878,7 +1955,6 @@ msgstr "फिर से कोशिश करो"
#~ msgid "Retry change handle"
#~ msgstr "हैंडल बदलना फिर से कोशिश करो"
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/BirthDateSettings.tsx:94
#: src/view/com/modals/BirthDateSettings.tsx:97
#: src/view/com/modals/ChangeHandle.tsx:173
@@ -1950,7 +2026,7 @@ msgstr "Bluesky Social का चयन करें"
msgid "Select from an existing account"
msgstr "मौजूदा खाते से चुनें"
#: src/view/com/auth/login/LoginForm.tsx:143
#: src/view/com/auth/login/LoginForm.tsx:147
msgid "Select service"
msgstr "सेवा चुनें"
@@ -1991,23 +2067,23 @@ msgstr "रिपोर्ट भेजें"
msgid "Set new password"
msgstr "नया पासवर्ड सेट करें"
#: src/view/screens/PreferencesHomeFeed.tsx:216
#: src/view/screens/PreferencesHomeFeed.tsx:222
msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
msgstr "अपने फ़ीड से सभी उद्धरण पदों को छिपाने के लिए इस सेटिंग को \"नहीं\" में सेट करें। Reposts अभी भी दिखाई देगा।।"
#: src/view/screens/PreferencesHomeFeed.tsx:113
#: src/view/screens/PreferencesHomeFeed.tsx:119
msgid "Set this setting to \"No\" to hide all replies from your feed."
msgstr "इस सेटिंग को अपने फ़ीड से सभी उत्तरों को छिपाने के लिए \"नहीं\" पर सेट करें।।"
#: src/view/screens/PreferencesHomeFeed.tsx:182
#: src/view/screens/PreferencesHomeFeed.tsx:188
msgid "Set this setting to \"No\" to hide all reposts from your feed."
msgstr "इस सेटिंग को अपने फ़ीड से सभी पोस्ट छिपाने के लिए \"नहीं\" करने के लिए सेट करें।।"
#: src/view/screens/PreferencesThreads.tsx:116
#: src/view/screens/PreferencesThreads.tsx:122
msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
msgstr "इस सेटिंग को \"हाँ\" में सेट करने के लिए एक थ्रेडेड व्यू में जवाब दिखाने के लिए। यह एक प्रयोगात्मक विशेषता है।।"
#: src/view/screens/PreferencesHomeFeed.tsx:252
#: src/view/screens/PreferencesHomeFeed.tsx:258
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
msgstr "इस सेटिंग को अपने निम्नलिखित फ़ीड में अपने सहेजे गए फ़ीड के नमूने दिखाने के लिए \"हाँ\" पर सेट करें। यह एक प्रयोगात्मक विशेषता है।।"
@@ -2045,23 +2121,27 @@ msgstr "दिखाओ"
msgid "Show anyway"
msgstr "दिखाओ"
#: src/view/screens/PreferencesHomeFeed.tsx:249
#: src/view/com/modals/EmbedConsent.tsx:87
msgid "Show embeds from {0}"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:255
msgid "Show Posts from My Feeds"
msgstr "मेरी फीड से पोस्ट दिखाएं"
#: src/view/screens/PreferencesHomeFeed.tsx:213
#: src/view/screens/PreferencesHomeFeed.tsx:219
msgid "Show Quote Posts"
msgstr "उद्धरण पोस्ट दिखाओ"
#: src/view/screens/PreferencesHomeFeed.tsx:110
#: src/view/screens/PreferencesHomeFeed.tsx:116
msgid "Show Replies"
msgstr "उत्तर दिखाएँ"
#: src/view/screens/PreferencesThreads.tsx:94
#: src/view/screens/PreferencesThreads.tsx:100
msgid "Show replies by people you follow before all other replies."
msgstr "अन्य सभी उत्तरों से पहले उन लोगों के उत्तर दिखाएं जिन्हें आप फ़ॉलो करते हैं।"
#: src/view/screens/PreferencesHomeFeed.tsx:179
#: src/view/screens/PreferencesHomeFeed.tsx:185
msgid "Show Reposts"
msgstr "रीपोस्ट दिखाएँ"
@@ -2098,7 +2178,7 @@ msgstr "{0} के रूप में साइन इन करें"
msgid "Sign in as..."
msgstr "... के रूप में साइन इन करें"
#: src/view/com/auth/login/LoginForm.tsx:130
#: src/view/com/auth/login/LoginForm.tsx:134
msgid "Sign into"
msgstr "साइन इन करें"
@@ -2152,11 +2232,11 @@ msgstr "स्क्वायर"
msgid "Staging"
msgstr "स्टेजिंग"
#: src/view/screens/Settings.tsx:730
#: src/view/screens/Settings.tsx:763
msgid "Status page"
msgstr "स्थिति पृष्ठ"
#: src/view/screens/Settings.tsx:666
#: src/view/screens/Settings.tsx:699
msgid "Storybook"
msgstr "Storybook"
@@ -2189,7 +2269,7 @@ msgstr "खाते बदलें"
#~ msgid "System"
#~ msgstr "प्रणाली"
#: src/view/screens/Settings.tsx:646
#: src/view/screens/Settings.tsx:679
msgid "System log"
msgstr "सिस्टम लॉग"
@@ -2201,7 +2281,7 @@ msgstr "लंबा"
msgid "Terms"
msgstr "शर्तें"
#: src/view/screens/Settings.tsx:744
#: src/view/screens/Settings.tsx:777
#: src/view/screens/TermsOfService.tsx:29
#: src/view/shell/Drawer.tsx:256
msgid "Terms of Service"
@@ -2256,6 +2336,10 @@ msgstr "यह {screenDescription} फ्लैग किया गया है
msgid "This account has requested that users sign in to view their profile."
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:68
msgid "This content is hosted by {0}. Do you want to enable external media?"
msgstr ""
#: src/view/com/posts/FeedErrorMessage.tsx:107
msgid "This content is not viewable without a Bluesky account."
msgstr ""
@@ -2297,7 +2381,7 @@ msgstr ""
msgid "Thread Preferences"
msgstr "थ्रेड प्राथमिकता"
#: src/view/screens/PreferencesThreads.tsx:113
#: src/view/screens/PreferencesThreads.tsx:119
msgid "Threaded Mode"
msgstr "थ्रेड मोड"
@@ -2329,7 +2413,7 @@ msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:65
#: src/view/com/auth/login/Login.tsx:76
#: src/view/com/auth/login/LoginForm.tsx:117
#: src/view/com/auth/login/LoginForm.tsx:120
msgid "Unable to contact your service. Please check your Internet connection."
msgstr "आपकी सेवा से संपर्क करने में असमर्थ। कृपया अपने इंटरनेट कनेक्शन की जांच करें।।"
@@ -2347,7 +2431,7 @@ msgstr "अनब्लॉक खाता"
msgid "Undo repost"
msgstr "पुनः पोस्ट पूर्ववत करें"
#: src/view/com/auth/create/state.ts:210
#: src/view/com/auth/create/state.ts:216
msgid "Unfortunately, you do not meet the requirements to create an account."
msgstr ""
@@ -2403,8 +2487,8 @@ msgstr "यूजर हैंडल"
msgid "User Lists"
msgstr "लोग सूचियाँ"
#: src/view/com/auth/login/LoginForm.tsx:170
#: src/view/com/auth/login/LoginForm.tsx:188
#: src/view/com/auth/login/LoginForm.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:192
msgid "Username or email address"
msgstr "यूजर नाम या ईमेल पता"
@@ -2424,15 +2508,15 @@ msgstr ""
msgid "Users in \"{0}\""
msgstr ""
#: src/view/screens/Settings.tsx:769
#: src/view/screens/Settings.tsx:802
msgid "Verify email"
msgstr "ईमेल सत्यापित करें"
#: src/view/screens/Settings.tsx:794
#: src/view/screens/Settings.tsx:827
msgid "Verify my email"
msgstr "मेरी ईमेल सत्यापित करें"
#: src/view/screens/Settings.tsx:803
#: src/view/screens/Settings.tsx:836
msgid "Verify My Email"
msgstr "मेरी ईमेल सत्यापित करें"
@@ -2506,7 +2590,7 @@ msgstr ""
msgid "Wide"
msgstr "चौड़ा"
#: src/view/com/composer/Composer.tsx:413
#: src/view/com/composer/Composer.tsx:418
msgid "Write post"
msgstr "पोस्ट लिखो"
@@ -2514,10 +2598,12 @@ msgstr "पोस्ट लिखो"
msgid "Write your reply"
msgstr "अपना जवाब दें"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:192
#: src/view/screens/PreferencesHomeFeed.tsx:227
#: src/view/screens/PreferencesHomeFeed.tsx:262
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:198
#: src/view/screens/PreferencesHomeFeed.tsx:233
#: src/view/screens/PreferencesHomeFeed.tsx:268
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "Yes"
msgstr "हाँ"
+192 -102
View File
@@ -5,7 +5,7 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: jp\n"
"Language: ja\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
@@ -68,7 +68,7 @@ msgstr "新しいバージョンのアプリが利用可能です。継続して
msgid "Accessibility"
msgstr "アクセシビリティ"
#: src/view/com/auth/login/LoginForm.tsx:159
#: src/view/com/auth/login/LoginForm.tsx:163
#: src/view/screens/Settings.tsx:286
msgid "Account"
msgstr "アカウント"
@@ -98,6 +98,7 @@ msgstr "アカウントを追加"
#: src/view/com/composer/photos/Gallery.tsx:119
#: src/view/com/composer/photos/Gallery.tsx:180
#: src/view/com/modals/AltImage.tsx:93
msgid "Add alt text"
msgstr "ALTテキストを追加"
@@ -110,11 +111,11 @@ msgstr "詳細を追加"
msgid "Add details to report"
msgstr "レポートに詳細を追加"
#: src/view/com/composer/Composer.tsx:442
#: src/view/com/composer/Composer.tsx:447
msgid "Add link card"
msgstr "リンクカードを追加"
#: src/view/com/composer/Composer.tsx:445
#: src/view/com/composer/Composer.tsx:450
msgid "Add link card:"
msgstr "リンクカードを追加:"
@@ -135,7 +136,7 @@ msgstr "マイフィードに追加"
msgid "Added to list"
msgstr "リストに追加"
#: src/view/screens/PreferencesHomeFeed.tsx:164
#: src/view/screens/PreferencesHomeFeed.tsx:170
msgid "Adjust the number of likes a reply must have to be shown in your feed."
msgstr "返信がフィードに表示されるために必要な「いいね」の数を調整します。"
@@ -143,7 +144,7 @@ msgstr "返信がフィードに表示されるために必要な「いいね」
msgid "Adult Content"
msgstr "成人向けコンテンツ"
#: src/view/screens/Settings.tsx:569
#: src/view/screens/Settings.tsx:602
msgid "Advanced"
msgstr "高度な設定"
@@ -176,7 +177,7 @@ msgstr "および"
msgid "App Language"
msgstr "アプリの言語"
#: src/view/screens/Settings.tsx:589
#: src/view/screens/Settings.tsx:622
msgid "App passwords"
msgstr "アプリパスワード"
@@ -212,7 +213,7 @@ msgstr "外観"
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr "本当にアプリパスワード「{name}」を削除しますか?"
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Are you sure you'd like to discard this draft?"
msgstr "本当にこの下書きを破棄しますか?"
@@ -231,7 +232,7 @@ msgstr "芸術的または性的ではないヌード。"
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:250
#: src/view/com/auth/login/LoginForm.tsx:254
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
#: src/view/com/modals/report/InputIssueDetails.tsx:46
#: src/view/com/post-thread/PostThread.tsx:388
@@ -327,7 +328,7 @@ msgstr "Blueskyはログアウトしたユーザーにあなたのプロフィ
msgid "Bluesky.Social"
msgstr "Bluesky.Social"
#: src/view/screens/Settings.tsx:718
#: src/view/screens/Settings.tsx:751
msgid "Build version {0} {1}"
msgstr "ビルドバージョン {0} {1}"
@@ -345,9 +346,8 @@ msgstr "カメラ"
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr "文字、数字、スペース、ハイフン、およびアンダースコアのみが使用可能です。長さは4文字以上32文字以下である必要があります。"
#: src/view/com/composer/Composer.tsx:289
#: src/view/com/composer/Composer.tsx:292
#: src/view/com/modals/AltImage.tsx:128
#: src/view/com/composer/Composer.tsx:294
#: src/view/com/composer/Composer.tsx:297
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
#: src/view/com/modals/Confirm.tsx:88
@@ -371,8 +371,8 @@ msgid "Cancel account deletion"
msgstr "アカウントの削除をキャンセル"
#: src/view/com/modals/AltImage.tsx:123
msgid "Cancel add image alt text"
msgstr "画像のALTテキストの追加をキャンセル"
#~ msgid "Cancel add image alt text"
#~ msgstr "画像のALTテキストの追加をキャンセル"
#: src/view/com/modals/ChangeHandle.tsx:149
msgid "Cancel change handle"
@@ -403,8 +403,8 @@ msgstr "Waitlistの登録をキャンセル"
msgid "Change"
msgstr "変更"
#: src/view/screens/Settings.tsx:601
#: src/view/screens/Settings.tsx:610
#: src/view/screens/Settings.tsx:634
#: src/view/screens/Settings.tsx:643
msgid "Change handle"
msgstr "ハンドルを変更"
@@ -434,7 +434,7 @@ msgstr "入力したメールアドレスの受信トレイを確認して、以
#: src/view/com/modals/Threadgate.tsx:72
msgid "Choose \"Everybody\" or \"Nobody\""
msgstr ""
msgstr "「全員」と「返信不可」のどちらかを選択"
#: src/view/com/modals/ServerInput.tsx:38
msgid "Choose Service"
@@ -448,19 +448,19 @@ msgstr "カスタムフィードを使用してあなたの体験を強化する
msgid "Choose your password"
msgstr "パスワードを選択"
#: src/view/screens/Settings.tsx:694
#: src/view/screens/Settings.tsx:727
msgid "Clear all legacy storage data"
msgstr "レガシーストレージデータをすべてクリア"
#: src/view/screens/Settings.tsx:696
#: src/view/screens/Settings.tsx:729
msgid "Clear all legacy storage data (restart after this)"
msgstr "すべてのレガシーストレージデータをクリア(この後再起動します)"
#: src/view/screens/Settings.tsx:706
#: src/view/screens/Settings.tsx:739
msgid "Clear all storage data"
msgstr "すべてのストレージデータをクリア"
#: src/view/screens/Settings.tsx:708
#: src/view/screens/Settings.tsx:741
msgid "Clear all storage data (restart after this)"
msgstr "すべてのストレージデータをクリア(この後再起動します)"
@@ -501,8 +501,8 @@ msgstr "返信を作成"
#: src/view/com/modals/Confirm.tsx:75
#: src/view/com/modals/SelfLabel.tsx:154
#: src/view/com/modals/VerifyEmail.tsx:225
#: src/view/screens/PreferencesHomeFeed.tsx:299
#: src/view/screens/PreferencesThreads.tsx:153
#: src/view/screens/PreferencesHomeFeed.tsx:305
#: src/view/screens/PreferencesThreads.tsx:159
msgid "Confirm"
msgstr "確認"
@@ -526,7 +526,7 @@ msgid "Confirmation code"
msgstr "確認コード"
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:269
#: src/view/com/auth/login/LoginForm.tsx:273
msgid "Connecting..."
msgstr "接続中..."
@@ -616,11 +616,15 @@ msgstr "作成済み {0}"
msgid "Custom domain"
msgstr "カスタムドメイン"
#: src/view/screens/Settings.tsx:615
#: src/view/screens/PreferencesExternalEmbeds.tsx:55
msgid "Customize media from external sites."
msgstr ""
#: src/view/screens/Settings.tsx:648
msgid "Danger Zone"
msgstr "危険地帯"
#: src/view/screens/Settings.tsx:622
#: src/view/screens/Settings.tsx:655
msgid "Delete account"
msgstr "アカウントを削除"
@@ -642,7 +646,7 @@ msgstr "リストを削除"
msgid "Delete my account"
msgstr "マイアカウントを削除"
#: src/view/screens/Settings.tsx:632
#: src/view/screens/Settings.tsx:665
msgid "Delete my account…"
msgstr "マイアカウントを削除…"
@@ -669,19 +673,19 @@ msgstr "説明"
msgid "Dev Server"
msgstr "開発者サーバー"
#: src/view/screens/Settings.tsx:637
#: src/view/screens/Settings.tsx:670
msgid "Developer Tools"
msgstr "開発者ツール"
#: src/view/com/composer/Composer.tsx:210
#: src/view/com/composer/Composer.tsx:211
msgid "Did you want to say anything?"
msgstr ""
#: src/view/com/composer/Composer.tsx:143
#: src/view/com/composer/Composer.tsx:144
msgid "Discard"
msgstr "破棄"
#: src/view/com/composer/Composer.tsx:137
#: src/view/com/composer/Composer.tsx:138
msgid "Discard draft"
msgstr "下書きを破棄"
@@ -706,6 +710,7 @@ msgid "Domain verified!"
msgstr "ドメインを確認しました!"
#: src/view/com/auth/onboarding/RecommendedFollows.tsx:86
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/ContentFilteringSettings.tsx:88
#: src/view/com/modals/ContentFilteringSettings.tsx:96
#: src/view/com/modals/crop-image/CropImage.web.tsx:152
@@ -715,8 +720,8 @@ msgstr "ドメインを確認しました!"
#: src/view/com/modals/Threadgate.tsx:129
#: src/view/com/modals/Threadgate.tsx:132
#: src/view/com/modals/UserAddRemoveLists.tsx:79
#: src/view/screens/PreferencesHomeFeed.tsx:302
#: src/view/screens/PreferencesThreads.tsx:156
#: src/view/screens/PreferencesHomeFeed.tsx:308
#: src/view/screens/PreferencesThreads.tsx:162
msgid "Done"
msgstr "完了"
@@ -777,7 +782,15 @@ msgstr "メールアドレスを更新"
msgid "Email:"
msgstr "メールアドレス:"
#: src/view/screens/PreferencesHomeFeed.tsx:138
#: src/view/com/modals/EmbedConsent.tsx:113
msgid "Enable {0} only"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:97
msgid "Enable External Media"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:144
msgid "Enable this setting to only see replies between people you follow."
msgstr "この設定を有効にすると、自分がフォローしているユーザーからの返信だけが表示されます。"
@@ -821,6 +834,20 @@ msgstr "全員"
msgid "Expand alt text"
msgstr "ALTテキストを展開"
#: src/view/com/modals/EmbedConsent.tsx:64
msgid "External Media"
msgstr ""
#: src/view/com/modals/EmbedConsent.tsx:75
#: src/view/screens/PreferencesExternalEmbeds.tsx:66
msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button."
msgstr ""
#: src/view/screens/PreferencesExternalEmbeds.tsx:52
#: src/view/screens/Settings.tsx:595
msgid "External Media Preferences"
msgstr ""
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:109
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:141
msgid "Failed to load recommended feeds"
@@ -868,7 +895,7 @@ msgstr "右側の検索ツールでユーザーを検索"
msgid "Finding similar accounts..."
msgstr "似ているアカウントを検索中..."
#: src/view/screens/PreferencesHomeFeed.tsx:102
#: src/view/screens/PreferencesHomeFeed.tsx:108
msgid "Fine-tune the content you see on your home screen."
msgstr "ホーム画面に表示されるコンテンツを微調整します。"
@@ -888,7 +915,7 @@ msgstr "何人かのユーザーをフォローして開始します。興味を
msgid "Followed users"
msgstr "自分がフォローしているユーザー"
#: src/view/screens/PreferencesHomeFeed.tsx:145
#: src/view/screens/PreferencesHomeFeed.tsx:151
msgid "Followed users only"
msgstr "自分がフォローしているユーザーのみ"
@@ -917,11 +944,11 @@ msgstr "セキュリティ上の理由から、メールアドレスに確認コ
msgid "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."
msgstr "セキュリティ上の理由から、これを再度表示することはできません。このパスワードを紛失した場合は、新しいパスワードを生成する必要があります。"
#: src/view/com/auth/login/LoginForm.tsx:232
#: src/view/com/auth/login/LoginForm.tsx:236
msgid "Forgot"
msgstr "忘れた"
#: src/view/com/auth/login/LoginForm.tsx:229
#: src/view/com/auth/login/LoginForm.tsx:233
msgid "Forgot password"
msgstr "パスワードを忘れた"
@@ -953,7 +980,7 @@ msgid "Go Back"
msgstr "戻る"
#: src/view/com/auth/login/ForgotPasswordForm.tsx:181
#: src/view/com/auth/login/LoginForm.tsx:279
#: src/view/com/auth/login/LoginForm.tsx:283
#: src/view/com/auth/login/SetNewPasswordForm.tsx:163
msgid "Go to next"
msgstr "次へ"
@@ -978,11 +1005,11 @@ msgstr "非表示"
#: src/view/com/util/forms/PostDropdownBtn.tsx:173
msgid "Hide post"
msgstr ""
msgstr "投稿を非表示にする"
#: src/view/com/util/forms/PostDropdownBtn.tsx:177
msgid "Hide this post?"
msgstr ""
msgstr "この投稿を非表示にしますか?"
#: src/view/com/notifications/FeedItem.tsx:316
msgid "Hide user list"
@@ -1016,7 +1043,7 @@ msgid "Home"
msgstr "ホーム"
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/PreferencesHomeFeed.tsx:101
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
msgstr "ホームフィードの設定"
@@ -1051,7 +1078,7 @@ msgstr "画像のALTテキスト"
msgid "Image options"
msgstr "画像のオプション"
#: src/view/com/auth/login/LoginForm.tsx:113
#: src/view/com/auth/login/LoginForm.tsx:115
msgid "Invalid username or password"
msgstr "無効なユーザー名またはパスワード"
@@ -1204,7 +1231,7 @@ msgstr "ローカル開発者サーバー"
#: src/view/screens/Moderation.tsx:136
msgid "Logged-out visibility"
msgstr "ログアウトした状態の可視性"
msgstr "ログアウトしたユーザーからの可視性"
#: src/view/com/auth/login/ChooseAccountForm.tsx:133
msgid "Login to account that is not listed"
@@ -1264,6 +1291,10 @@ msgstr "その他のフィード"
msgid "More options"
msgstr "その他のオプション"
#: src/view/screens/PreferencesThreads.tsx:82
msgid "Most-liked replies first"
msgstr "いいねの数が多い順に返信を表示"
#: src/view/com/profile/ProfileHeader.tsx:370
msgid "Mute Account"
msgstr "アカウントをミュート"
@@ -1321,6 +1352,11 @@ msgstr "保存されたフィード"
msgid "Name"
msgstr "名前"
#: src/view/com/modals/EmbedConsent.tsx:107
#: src/view/com/modals/EmbedConsent.tsx:123
msgid "Never load embeds from {0}"
msgstr ""
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:72
msgid "Never lose access to your followers and data."
msgstr "フォロワーやデータへのアクセスを失うことはありません。"
@@ -1344,10 +1380,14 @@ msgstr "新しい投稿"
msgid "New Post"
msgstr "新しい投稿"
#: src/view/screens/PreferencesThreads.tsx:79
msgid "Newest replies first"
msgstr "新しい順に返信を表示"
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:282
#: src/view/com/auth/login/LoginForm.tsx:286
#: src/view/com/auth/login/SetNewPasswordForm.tsx:156
#: src/view/com/auth/login/SetNewPasswordForm.tsx:166
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:79
@@ -1358,10 +1398,12 @@ msgstr "次へ"
msgid "Next image"
msgstr "次の画像"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:191
#: src/view/screens/PreferencesHomeFeed.tsx:226
#: src/view/screens/PreferencesHomeFeed.tsx:263
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:197
#: src/view/screens/PreferencesHomeFeed.tsx:232
#: src/view/screens/PreferencesHomeFeed.tsx:269
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "No"
msgstr "いいえ"
@@ -1386,6 +1428,10 @@ msgstr "「{query}」の検索結果はありません"
msgid "No results found for {query}"
msgstr "「{query}」の検索結果はありません"
#: src/view/com/modals/EmbedConsent.tsx:129
msgid "No thanks"
msgstr ""
#: src/view/com/modals/Threadgate.tsx:82
msgid "Nobody"
msgstr "返信不可"
@@ -1419,7 +1465,11 @@ msgstr "ちょっと!"
msgid "Okay"
msgstr "OK"
#: src/view/com/composer/Composer.tsx:358
#: src/view/screens/PreferencesThreads.tsx:78
msgid "Oldest replies first"
msgstr "古い順に返信を表示"
#: src/view/com/composer/Composer.tsx:363
msgid "One or more images is missing alt text."
msgstr "1つもしくは複数の画像にALTテキストがありません。"
@@ -1427,6 +1477,11 @@ msgstr "1つもしくは複数の画像にALTテキストがありません。"
msgid "Only {0} can reply."
msgstr "{0}のみ返信可能"
#: src/view/com/composer/Composer.tsx:468
#: src/view/com/composer/Composer.tsx:469
msgid "Open emoji picker"
msgstr "絵文字を入力"
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr "ナビゲーションを開く"
@@ -1435,6 +1490,10 @@ msgstr "ナビゲーションを開く"
msgid "Opens configurable language settings"
msgstr "構成可能な言語設定を開く"
#: src/view/screens/Settings.tsx:587
msgid "Opens external embeds settings"
msgstr ""
#: src/view/shell/desktop/RightNav.tsx:156
#: src/view/shell/Drawer.tsx:641
msgid "Opens list of invite codes"
@@ -1452,7 +1511,7 @@ msgstr "モデレーションの設定を開く"
msgid "Opens screen with all saved feeds"
msgstr "保存されたすべてのフィードで画面を開く"
#: src/view/screens/Settings.tsx:581
#: src/view/screens/Settings.tsx:614
msgid "Opens the app password settings page"
msgstr "アプリパスワード設定ページを開く"
@@ -1460,11 +1519,11 @@ msgstr "アプリパスワード設定ページを開く"
msgid "Opens the home feed preferences"
msgstr "ホームフィードの設定を開く"
#: src/view/screens/Settings.tsx:664
#: src/view/screens/Settings.tsx:697
msgid "Opens the storybook page"
msgstr "ストーリーブックのページを開く"
#: src/view/screens/Settings.tsx:644
#: src/view/screens/Settings.tsx:677
msgid "Opens the system log page"
msgstr "システムログのページを開く"
@@ -1474,7 +1533,7 @@ msgstr "スレッドの設定を開く"
#: src/view/com/modals/Threadgate.tsx:89
msgid "Or combine these options:"
msgstr ""
msgstr "または以下のオプションを組み合わせてください:"
#: src/view/com/auth/login/ChooseAccountForm.tsx:138
msgid "Other account"
@@ -1495,7 +1554,7 @@ msgstr "ページが見つかりません"
#: src/view/com/auth/create/Step2.tsx:122
#: src/view/com/auth/create/Step2.tsx:132
#: src/view/com/auth/login/LoginForm.tsx:217
#: src/view/com/auth/login/LoginForm.tsx:221
#: src/view/com/auth/login/SetNewPasswordForm.tsx:130
#: src/view/com/modals/DeleteAccount.tsx:191
msgid "Password"
@@ -1517,6 +1576,19 @@ msgstr "成人向けの写真です。"
msgid "Pinned Feeds"
msgstr "ピン留めされたフィード"
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:111
msgid "Play {0}"
msgstr ""
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:54
#: src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx:55
msgid "Play Video"
msgstr ""
#: src/view/com/util/post-embeds/ExternalGifEmbed.tsx:110
msgid "Plays the GIF"
msgstr ""
#: src/view/com/auth/create/state.ts:116
msgid "Please choose your handle."
msgstr "ハンドルをお選びください。"
@@ -1551,11 +1623,11 @@ msgstr ""
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr "この判断が誤っていると考える理由を教えてください。"
#: src/view/com/composer/Composer.tsx:214
#: src/view/com/composer/Composer.tsx:215
msgid "Please wait for your link card to finish loading"
msgstr ""
msgstr "リンクカードがロードされるまでお待ちください"
#: src/view/com/composer/Composer.tsx:341
#: src/view/com/composer/Composer.tsx:346
#: src/view/com/post-thread/PostThread.tsx:225
#: src/view/screens/PostThread.tsx:80
msgid "Post"
@@ -1593,16 +1665,17 @@ msgstr "前の画像"
msgid "Primary Language"
msgstr "第一言語"
#: src/view/screens/PreferencesThreads.tsx:91
#: src/view/screens/PreferencesThreads.tsx:97
msgid "Prioritize Your Follows"
msgstr "あなたのフォローを優先"
#: src/view/screens/Settings.tsx:570
#: src/view/shell/desktop/RightNav.tsx:84
msgid "Privacy"
msgstr "プライバシー"
#: src/view/screens/PrivacyPolicy.tsx:29
#: src/view/screens/Settings.tsx:750
#: src/view/screens/Settings.tsx:783
#: src/view/shell/Drawer.tsx:262
msgid "Privacy Policy"
msgstr "プライバシーポリシー"
@@ -1619,7 +1692,7 @@ msgstr "処理中..."
msgid "Profile"
msgstr "プロフィール"
#: src/view/screens/Settings.tsx:808
#: src/view/screens/Settings.tsx:841
msgid "Protect your account by verifying your email."
msgstr "メールアドレスを確認してアカウントを保護します。"
@@ -1640,6 +1713,10 @@ msgstr "引用"
msgid "Quote Post"
msgstr "引用"
#: src/view/screens/PreferencesThreads.tsx:86
msgid "Random (aka \"Poster's Roulette\")"
msgstr "ランダムな順番で表示(別名「投稿者のルーレット」)"
#: src/view/com/modals/EditImage.tsx:236
msgid "Ratios"
msgstr "比率"
@@ -1707,7 +1784,7 @@ msgstr "返信"
msgid "Replies to this thread are disabled"
msgstr "このスレッドへの返信はできません"
#: src/view/screens/PreferencesHomeFeed.tsx:135
#: src/view/screens/PreferencesHomeFeed.tsx:141
msgid "Reply Filters"
msgstr "返信のフィルター"
@@ -1750,6 +1827,10 @@ msgstr "リポストしたユーザー"
msgid "Request Change"
msgstr "変更を要求"
#: src/view/screens/Settings.tsx:422
msgid "Require alt text before posting"
msgstr "画像投稿時にALTテキストを必須とする"
#: src/view/com/auth/create/Step2.tsx:68
msgid "Required for this provider"
msgstr "このプロバイダーに必要"
@@ -1758,7 +1839,7 @@ msgstr "このプロバイダーに必要"
msgid "Reset code"
msgstr "コードをリセット"
#: src/view/screens/Settings.tsx:686
#: src/view/screens/Settings.tsx:719
msgid "Reset onboarding state"
msgstr "オンボーディングの状態をリセット"
@@ -1766,28 +1847,27 @@ msgstr "オンボーディングの状態をリセット"
msgid "Reset password"
msgstr "パスワードをリセット"
#: src/view/screens/Settings.tsx:676
#: src/view/screens/Settings.tsx:709
msgid "Reset preferences state"
msgstr "設定をリセット"
#: src/view/screens/Settings.tsx:684
#: src/view/screens/Settings.tsx:717
msgid "Resets the onboarding state"
msgstr "オンボーディングの状態をリセット"
#: src/view/screens/Settings.tsx:674
#: src/view/screens/Settings.tsx:707
msgid "Resets the preferences state"
msgstr "設定の状態をリセット"
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/login/LoginForm.tsx:259
#: src/view/com/auth/login/LoginForm.tsx:262
#: src/view/com/auth/login/LoginForm.tsx:263
#: src/view/com/auth/login/LoginForm.tsx:266
#: src/view/com/util/error/ErrorMessage.tsx:55
#: src/view/com/util/error/ErrorScreen.tsx:65
msgid "Retry"
msgstr "再試行"
#: src/view/com/modals/AltImage.tsx:115
#: src/view/com/modals/BirthDateSettings.tsx:94
#: src/view/com/modals/BirthDateSettings.tsx:97
#: src/view/com/modals/ChangeHandle.tsx:173
@@ -1837,7 +1917,7 @@ msgstr "検索"
#: src/view/com/auth/LoggedOut.tsx:104
#: src/view/com/auth/LoggedOut.tsx:105
msgid "Search for users"
msgstr ""
msgstr "ユーザーを検索"
#: src/view/com/modals/ChangeEmail.tsx:110
msgid "Security Step Required"
@@ -1855,7 +1935,7 @@ msgstr "Bluesky Socialを選択"
msgid "Select from an existing account"
msgstr "既存のアカウントから選択"
#: src/view/com/auth/login/LoginForm.tsx:143
#: src/view/com/auth/login/LoginForm.tsx:147
msgid "Select service"
msgstr "サービスを選択"
@@ -1896,25 +1976,25 @@ msgstr "報告を送信"
msgid "Set new password"
msgstr "新しいパスワードを設定"
#: src/view/screens/PreferencesHomeFeed.tsx:216
#: src/view/screens/PreferencesHomeFeed.tsx:222
msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
msgstr "フィード内の引用をすべて非表示にするには、この設定を「いいえ」にします。リポストは引き続き表示されます。"
#: src/view/screens/PreferencesHomeFeed.tsx:113
#: src/view/screens/PreferencesHomeFeed.tsx:119
msgid "Set this setting to \"No\" to hide all replies from your feed."
msgstr "フィード内の返信をすべて非表示にするには、この設定を「いいえ」にします。"
#: src/view/screens/PreferencesHomeFeed.tsx:182
#: src/view/screens/PreferencesHomeFeed.tsx:188
msgid "Set this setting to \"No\" to hide all reposts from your feed."
msgstr "フィード内のリポストをすべて非表示にするには、この設定を「いいえ」にします。"
#: src/view/screens/PreferencesThreads.tsx:116
#: src/view/screens/PreferencesThreads.tsx:122
msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
msgstr "スレッド表示で返信を表示するには、この設定を「はい」にします。これは実験的な機能です。"
#: src/view/screens/PreferencesHomeFeed.tsx:252
#: src/view/screens/PreferencesHomeFeed.tsx:258
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
msgstr "保存されたフィードのサンプルを次のフィードに表示するには、この設定を「はい」にします。これは実験的な機能です。"
msgstr "保存されたフィードから投稿を抽出して「Following」フィードに表示するには、この設定を「はい」にします。これは実験的な機能です。"
#: src/view/screens/Settings.tsx:277
#: src/view/shell/desktop/LeftNav.tsx:433
@@ -1946,23 +2026,27 @@ msgstr "表示"
msgid "Show anyway"
msgstr "とにかく表示"
#: src/view/screens/PreferencesHomeFeed.tsx:249
#: src/view/com/modals/EmbedConsent.tsx:87
msgid "Show embeds from {0}"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:255
msgid "Show Posts from My Feeds"
msgstr "マイフィードからの投稿を表示"
#: src/view/screens/PreferencesHomeFeed.tsx:213
#: src/view/screens/PreferencesHomeFeed.tsx:219
msgid "Show Quote Posts"
msgstr "引用を表示"
#: src/view/screens/PreferencesHomeFeed.tsx:110
#: src/view/screens/PreferencesHomeFeed.tsx:116
msgid "Show Replies"
msgstr "返信を表示"
#: src/view/screens/PreferencesThreads.tsx:94
#: src/view/screens/PreferencesThreads.tsx:100
msgid "Show replies by people you follow before all other replies."
msgstr "自分がフォローしているユーザーからの返信を、他のすべての返信の前に表示します。"
#: src/view/screens/PreferencesHomeFeed.tsx:179
#: src/view/screens/PreferencesHomeFeed.tsx:185
msgid "Show Reposts"
msgstr "リポストを表示"
@@ -1999,7 +2083,7 @@ msgstr "{0}としてサインイン"
msgid "Sign in as..."
msgstr "アカウントの選択"
#: src/view/com/auth/login/LoginForm.tsx:130
#: src/view/com/auth/login/LoginForm.tsx:134
msgid "Sign into"
msgstr "サインイン"
@@ -2053,11 +2137,11 @@ msgstr "正方形"
msgid "Staging"
msgstr "ステージング"
#: src/view/screens/Settings.tsx:730
#: src/view/screens/Settings.tsx:763
msgid "Status page"
msgstr "ステータスページ"
#: src/view/screens/Settings.tsx:666
#: src/view/screens/Settings.tsx:699
msgid "Storybook"
msgstr "ストーリーブック"
@@ -2086,7 +2170,7 @@ msgstr "サポート"
msgid "Switch Account"
msgstr "アカウントを切り替える"
#: src/view/screens/Settings.tsx:646
#: src/view/screens/Settings.tsx:679
msgid "System log"
msgstr "システムログ"
@@ -2098,7 +2182,7 @@ msgstr "トール"
msgid "Terms"
msgstr "条件"
#: src/view/screens/Settings.tsx:744
#: src/view/screens/Settings.tsx:777
#: src/view/screens/TermsOfService.tsx:29
#: src/view/shell/Drawer.tsx:256
msgid "Terms of Service"
@@ -2153,6 +2237,10 @@ msgstr "この{screenDescription}にはフラグが設定されています:"
msgid "This account has requested that users sign in to view their profile."
msgstr "このアカウントを閲覧するためにはサインインが必要です。"
#: src/view/com/modals/EmbedConsent.tsx:68
msgid "This content is hosted by {0}. Do you want to enable external media?"
msgstr ""
#: src/view/com/posts/FeedErrorMessage.tsx:107
msgid "This content is not viewable without a Bluesky account."
msgstr "このコンテンツはBlueskyのアカウントがないと閲覧できません。"
@@ -2187,14 +2275,14 @@ msgstr "この警告は、メディアが接続されている投稿にのみ使
#: src/view/com/util/forms/PostDropdownBtn.tsx:178
msgid "This will hide this post from your feeds."
msgstr ""
msgstr "この投稿をあなたのフィードにおいて非表示にします。"
#: src/view/screens/PreferencesThreads.tsx:53
#: src/view/screens/Settings.tsx:503
msgid "Thread Preferences"
msgstr "スレッドの設定"
#: src/view/screens/PreferencesThreads.tsx:113
#: src/view/screens/PreferencesThreads.tsx:119
msgid "Threaded Mode"
msgstr "スレッドモード"
@@ -2226,7 +2314,7 @@ msgstr "リストでのミュートを解除"
#: src/view/com/auth/create/CreateAccount.tsx:65
#: src/view/com/auth/login/Login.tsx:76
#: src/view/com/auth/login/LoginForm.tsx:117
#: src/view/com/auth/login/LoginForm.tsx:120
msgid "Unable to contact your service. Please check your Internet connection."
msgstr "あなたのサービスに接続できません。インターネットの接続を確認してください。"
@@ -2244,7 +2332,7 @@ msgstr "アカウントのブロックを解除"
msgid "Undo repost"
msgstr "リポストを元に戻す"
#: src/view/com/auth/create/state.ts:210
#: src/view/com/auth/create/state.ts:216
msgid "Unfortunately, you do not meet the requirements to create an account."
msgstr "残念ながら、アカウントを作成するための要件を満たしていません。"
@@ -2300,8 +2388,8 @@ msgstr "ユーザーハンドル"
msgid "User Lists"
msgstr "ユーザーリスト"
#: src/view/com/auth/login/LoginForm.tsx:170
#: src/view/com/auth/login/LoginForm.tsx:188
#: src/view/com/auth/login/LoginForm.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:192
msgid "Username or email address"
msgstr "ユーザー名またはメールアドレス"
@@ -2317,15 +2405,15 @@ msgstr "<0/>にフォローされているユーザー"
msgid "Users in \"{0}\""
msgstr "{0}のユーザー"
#: src/view/screens/Settings.tsx:769
#: src/view/screens/Settings.tsx:802
msgid "Verify email"
msgstr "メールアドレスを確認"
#: src/view/screens/Settings.tsx:794
#: src/view/screens/Settings.tsx:827
msgid "Verify my email"
msgstr "メールアドレスを確認"
#: src/view/screens/Settings.tsx:803
#: src/view/screens/Settings.tsx:836
msgid "Verify My Email"
msgstr "メールアドレスを確認"
@@ -2387,7 +2475,7 @@ msgstr "返信できるユーザー"
msgid "Wide"
msgstr "ワイド"
#: src/view/com/composer/Composer.tsx:413
#: src/view/com/composer/Composer.tsx:418
msgid "Write post"
msgstr "投稿を書く"
@@ -2395,10 +2483,12 @@ msgstr "投稿を書く"
msgid "Write your reply"
msgstr "返信を書く"
#: src/view/screens/PreferencesHomeFeed.tsx:120
#: src/view/screens/PreferencesHomeFeed.tsx:192
#: src/view/screens/PreferencesHomeFeed.tsx:227
#: src/view/screens/PreferencesHomeFeed.tsx:262
#: src/view/screens/PreferencesHomeFeed.tsx:126
#: src/view/screens/PreferencesHomeFeed.tsx:198
#: src/view/screens/PreferencesHomeFeed.tsx:233
#: src/view/screens/PreferencesHomeFeed.tsx:268
#: src/view/screens/PreferencesThreads.tsx:106
#: src/view/screens/PreferencesThreads.tsx:129
msgid "Yes"
msgstr "はい"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -26,6 +26,7 @@ export const router = new Router({
AppPasswords: '/settings/app-passwords',
PreferencesHomeFeed: '/settings/home-feed',
PreferencesThreads: '/settings/threads',
PreferencesExternalEmbeds: '/settings/external-embeds',
SavedFeeds: '/settings/saved-feeds',
Support: '/support',
PrivacyPolicy: '/support/privacy',
+8
View File
@@ -6,6 +6,7 @@ import {Image as RNImage} from 'react-native-image-crop-picker'
import {ImageModel} from '#/state/models/media/image'
import {GalleryModel} from '#/state/models/media/gallery'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {EmbedPlayerSource} from '#/lib/strings/embed-player.ts'
import {ThreadgateSetting} from '../queries/threadgate'
export interface ConfirmModal {
@@ -180,6 +181,12 @@ export interface LinkWarningModal {
href: string
}
export interface EmbedConsentModal {
name: 'embed-consent'
source: EmbedPlayerSource
onAccept: () => void
}
export type Modal =
// Account
| AddAppPasswordModal
@@ -223,6 +230,7 @@ export type Modal =
// Generic
| ConfirmModal
| LinkWarningModal
| EmbedConsentModal
const ModalContext = React.createContext<{
isModalActive: boolean
+1
View File
@@ -109,6 +109,7 @@ export function transform(legacy: Partial<LegacySchema>): Schema {
step: legacy.onboarding?.step || defaults.onboarding.step,
},
hiddenPosts: defaults.hiddenPosts,
externalEmbeds: defaults.externalEmbeds,
}
}
+16
View File
@@ -1,6 +1,8 @@
import {z} from 'zod'
import {deviceLocales} from '#/platform/detection'
const externalEmbedOptions = ['show', 'hide'] as const
// only data needed for rendering account page
const accountSchema = z.object({
service: z.string(),
@@ -30,6 +32,19 @@ export const schema = z.object({
appLanguage: z.string(),
}),
requireAltTextEnabled: z.boolean(), // should move to server
externalEmbeds: z
.object({
giphy: z.enum(externalEmbedOptions).optional(),
tenor: z.enum(externalEmbedOptions).optional(),
youtube: z.enum(externalEmbedOptions).optional(),
youtubeShorts: z.enum(externalEmbedOptions).optional(),
twitch: z.enum(externalEmbedOptions).optional(),
vimeo: z.enum(externalEmbedOptions).optional(),
spotify: z.enum(externalEmbedOptions).optional(),
appleMusic: z.enum(externalEmbedOptions).optional(),
soundcloud: z.enum(externalEmbedOptions).optional(),
})
.optional(),
mutedThreads: z.array(z.string()), // should move to server
invites: z.object({
copiedInvites: z.array(z.string()),
@@ -60,6 +75,7 @@ export const defaults: Schema = {
appLanguage: deviceLocales[0] || 'en',
},
requireAltTextEnabled: false,
externalEmbeds: {},
mutedThreads: [],
invites: {
copiedInvites: [],
@@ -0,0 +1,54 @@
import React from 'react'
import * as persisted from '#/state/persisted'
import {EmbedPlayerSource} from 'lib/strings/embed-player'
type StateContext = persisted.Schema['externalEmbeds']
type SetContext = (source: EmbedPlayerSource, value: 'show' | 'hide') => void
const stateContext = React.createContext<StateContext>(
persisted.defaults.externalEmbeds,
)
const setContext = React.createContext<SetContext>({} as SetContext)
export function Provider({children}: React.PropsWithChildren<{}>) {
const [state, setState] = React.useState(persisted.get('externalEmbeds'))
const setStateWrapped = React.useCallback(
(source: EmbedPlayerSource, value: 'show' | 'hide') => {
setState(prev => {
persisted.write('externalEmbeds', {
...prev,
[source]: value,
})
return {
...prev,
[source]: value,
}
})
},
[setState],
)
React.useEffect(() => {
return persisted.onUpdate(() => {
setState(persisted.get('externalEmbeds'))
})
}, [setStateWrapped])
return (
<stateContext.Provider value={state}>
<setContext.Provider value={setStateWrapped}>
{children}
</setContext.Provider>
</stateContext.Provider>
)
}
export function useExternalEmbedsPrefs() {
return React.useContext(stateContext)
}
export function useSetExternalEmbedPref() {
return React.useContext(setContext)
}
+8 -1
View File
@@ -2,19 +2,26 @@ import React from 'react'
import {Provider as LanguagesProvider} from './languages'
import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required'
import {Provider as HiddenPostsProvider} from '../preferences/hidden-posts'
import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs'
export {useLanguagePrefs, useLanguagePrefsApi} from './languages'
export {
useRequireAltTextEnabled,
useSetRequireAltTextEnabled,
} from './alt-text-required'
export {
useExternalEmbedsPrefs,
useSetExternalEmbedPref,
} from './external-embeds-prefs'
export * from './hidden-posts'
export function Provider({children}: React.PropsWithChildren<{}>) {
return (
<LanguagesProvider>
<AltTextRequiredProvider>
<HiddenPostsProvider>{children}</HiddenPostsProvider>
<ExternalEmbedsProvider>
<HiddenPostsProvider>{children}</HiddenPostsProvider>
</ExternalEmbedsProvider>
</AltTextRequiredProvider>
</LanguagesProvider>
)
+2
View File
@@ -24,6 +24,8 @@ export function useActorAutocompleteQuery(prefix: string) {
const {data: follows, isFetching} = useMyFollowsQuery()
const moderationOpts = useModerationOpts()
prefix = prefix.toLowerCase()
return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY(prefix || ''),
-1
View File
@@ -9,7 +9,6 @@ export const RQKEY = () => ['app-passwords']
export function useAppPasswordsQuery() {
return useQuery({
staleTime: STALE.MINUTES.FIVE,
refetchInterval: STALE.MINUTES.ONE,
queryKey: RQKEY(),
queryFn: async () => {
const res = await getAgent().com.atproto.server.listAppPasswords({})
-1
View File
@@ -16,7 +16,6 @@ export type InviteCodesQueryResponse = Exclude<
export function useInviteCodesQuery() {
return useQuery({
staleTime: STALE.MINUTES.FIVE,
refetchInterval: STALE.MINUTES.FIVE,
queryKey: ['inviteCodes'],
queryFn: async () => {
const res = await getAgent()
@@ -15,6 +15,7 @@ import {useMutedThreads} from '#/state/muted-threads'
import {RQKEY as RQKEY_NOTIFS} from './feed'
import {logger} from '#/logger'
import {truncateAndInvalidate} from '../util'
import {AppState} from 'react-native'
const UPDATE_INTERVAL = 30 * 1e3 // 30sec
@@ -97,6 +98,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
async checkUnread({invalidate}: {invalidate?: boolean} = {}) {
try {
if (!getAgent().session) return
if (AppState.currentState !== 'active') {
return
}
// count
const page = await fetchPage({
+4
View File
@@ -1,4 +1,5 @@
import React, {useCallback, useEffect, useRef} from 'react'
import {AppState} from 'react-native'
import {AppBskyFeedDefs, AppBskyFeedPost, PostModeration} from '@atproto/api'
import {
useInfiniteQuery,
@@ -312,6 +313,9 @@ export async function pollLatest(page: FeedPage | undefined) {
if (!page) {
return false
}
if (AppState.currentState !== 'active') {
return
}
logger.debug('usePostFeedQuery: pollLatest')
const post = await page.api.peekLatest()
+4 -8
View File
@@ -181,14 +181,10 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const createAccount = React.useCallback<ApiContext['createAccount']>(
async ({service, email, password, handle, inviteCode}: any) => {
logger.debug(
`session: creating account`,
{
service,
handle,
},
logger.DebugContext.session,
)
logger.info(`session: creating account`, {
service,
handle,
})
track('Try Create Account')
const agent = new BskyAgent({service})
+1
View File
@@ -30,6 +30,7 @@ export interface ComposerOpts {
onPost?: () => void
quote?: ComposerOptsQuote
mention?: string // handle of user to mention
openPicker?: (pos: DOMRect | undefined) => void
}
type StateContext = ComposerOpts | undefined
+7 -1
View File
@@ -136,7 +136,13 @@ export async function submit({
msg`Invite code not accepted. Check that you input it correctly and try again.`,
)
}
logger.error('Failed to create account', {error: e})
if ([400, 429].includes(e.status)) {
logger.warn('Failed to create account', {error: e})
} else {
logger.error(`Failed to create account (${e.status} status)`, {error: e})
}
uiDispatch({type: 'set-processing', value: false})
uiDispatch({type: 'set-error', value: cleanError(errMsg)})
throw e
+5 -1
View File
@@ -107,17 +107,21 @@ export const LoginForm = ({
})
} catch (e: any) {
const errMsg = e.toString()
logger.warn('Failed to login', {error: e})
setIsProcessing(false)
if (errMsg.includes('Authentication Required')) {
logger.info('Failed to login due to invalid credentials', {
error: errMsg,
})
setError(_(msg`Invalid username or password`))
} else if (isNetworkError(e)) {
logger.warn('Failed to login due to network error', {error: errMsg})
setError(
_(
msg`Unable to contact your service. Please check your Internet connection.`,
),
)
} else {
logger.warn('Failed to login', {error: errMsg})
setError(cleanError(errMsg))
}
}
+19 -2
View File
@@ -6,6 +6,7 @@ import {
Keyboard,
KeyboardAvoidingView,
Platform,
Pressable,
ScrollView,
StyleSheet,
TouchableOpacity,
@@ -46,7 +47,6 @@ import {Gallery} from './photos/Gallery'
import {MAX_GRAPHEME_LENGTH} from 'lib/constants'
import {LabelsBtn} from './labels/LabelsBtn'
import {SelectLangBtn} from './select-language/SelectLangBtn'
import {EmojiPickerButton} from './text-input/web/EmojiPicker.web'
import {insertMentionAt} from 'lib/strings/mention-manip'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -70,6 +70,7 @@ export const ComposePost = observer(function ComposePost({
onPost,
quote: initQuote,
mention: initMention,
openPicker,
}: Props) {
const {currentAccount} = useSession()
const {data: currentProfile} = useProfileQuery({did: currentAccount!.did})
@@ -274,6 +275,10 @@ export const ComposePost = observer(function ComposePost({
const canSelectImages = useMemo(() => gallery.size < 4, [gallery.size])
const hasMedia = gallery.size > 0 || Boolean(extLink)
const onEmojiButtonPress = useCallback(() => {
openPicker?.(textInput.current?.getCursorPosition())
}, [openPicker])
return (
<KeyboardAvoidingView
testID="composePostView"
@@ -456,7 +461,19 @@ export const ComposePost = observer(function ComposePost({
<OpenCameraBtn gallery={gallery} />
</>
) : null}
{!isMobile ? <EmojiPickerButton /> : null}
{!isMobile ? (
<Pressable
onPress={onEmojiButtonPress}
accessibilityRole="button"
accessibilityLabel={_(msg`Open emoji picker`)}
accessibilityHint={_(msg`Open emoji picker`)}>
<FontAwesomeIcon
icon={['far', 'face-smile']}
color={pal.colors.link}
size={22}
/>
</Pressable>
) : null}
<View style={s.flex1} />
<SelectLangBtn />
<CharProgress count={graphemeLength} />
@@ -32,6 +32,7 @@ import {POST_IMG_MAX} from 'lib/constants'
export interface TextInputRef {
focus: () => void
blur: () => void
getCursorPosition: () => DOMRect | undefined
}
interface TextInputProps extends ComponentProps<typeof RNTextInput> {
@@ -74,6 +75,7 @@ export const TextInput = forwardRef(function TextInputImpl(
blur: () => {
textInput.current?.blur()
},
getCursorPosition: () => undefined, // Not implemented on native
}))
const onChangeText = useCallback(
@@ -22,6 +22,7 @@ import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
export interface TextInputRef {
focus: () => void
blur: () => void
getCursorPosition: () => DOMRect | undefined
}
interface TextInputProps {
@@ -169,6 +170,10 @@ export const TextInput = React.forwardRef(function TextInputImpl(
React.useImperativeHandle(ref, () => ({
focus: () => {}, // TODO
blur: () => {}, // TODO
getCursorPosition: () => {
const pos = editor?.state.selection.$anchor.pos
return pos ? editor?.view.coordsAtPos(pos) : undefined
},
}))
return (
@@ -1,11 +1,17 @@
import React from 'react'
import Picker from '@emoji-mart/react'
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import {
StyleSheet,
TouchableWithoutFeedback,
useWindowDimensions,
View,
} from 'react-native'
import {textInputWebEmitter} from '../TextInput.web'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {usePalette} from 'lib/hooks/usePalette'
import {useMediaQuery} from 'react-responsive'
const HEIGHT_OFFSET = 40
const WIDTH_OFFSET = 100
const PICKER_HEIGHT = 435 + HEIGHT_OFFSET
const PICKER_WIDTH = 350 + WIDTH_OFFSET
export type Emoji = {
aliases?: string[]
@@ -18,59 +24,87 @@ export type Emoji = {
unified: string
}
export function EmojiPickerButton() {
const pal = usePalette('default')
const [open, setOpen] = React.useState(false)
const onOpenChange = (o: boolean) => {
setOpen(o)
}
const close = () => {
setOpen(false)
}
return (
<DropdownMenu.Root open={open} onOpenChange={onOpenChange}>
<DropdownMenu.Trigger style={styles.trigger}>
<FontAwesomeIcon
icon={['far', 'face-smile']}
color={pal.colors.link}
size={22}
/>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<EmojiPicker close={close} />
</DropdownMenu.Portal>
</DropdownMenu.Root>
)
export interface EmojiPickerState {
isOpen: boolean
pos: {top: number; left: number; right: number; bottom: number}
}
export function EmojiPicker({close}: {close: () => void}) {
interface IProps {
state: EmojiPickerState
close: () => void
}
export function EmojiPicker({state, close}: IProps) {
const {height, width} = useWindowDimensions()
const isShiftDown = React.useRef(false)
const position = React.useMemo(() => {
const fitsBelow = state.pos.top + PICKER_HEIGHT < height
const fitsAbove = PICKER_HEIGHT < state.pos.top
const placeOnLeft = PICKER_WIDTH < state.pos.left
const screenYMiddle = height / 2 - PICKER_HEIGHT / 2
if (fitsBelow) {
return {
top: state.pos.top + HEIGHT_OFFSET,
}
} else if (fitsAbove) {
return {
bottom: height - state.pos.bottom + HEIGHT_OFFSET,
}
} else {
return {
top: screenYMiddle,
left: placeOnLeft ? state.pos.left - PICKER_WIDTH : undefined,
right: !placeOnLeft
? width - state.pos.right - PICKER_WIDTH
: undefined,
}
}
}, [state.pos, height, width])
React.useEffect(() => {
if (!state.isOpen) return
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Shift') {
isShiftDown.current = true
}
}
const onKeyUp = (e: KeyboardEvent) => {
if (e.key === 'Shift') {
isShiftDown.current = false
}
}
window.addEventListener('keydown', onKeyDown, true)
window.addEventListener('keyup', onKeyUp, true)
return () => {
window.removeEventListener('keydown', onKeyDown, true)
window.removeEventListener('keyup', onKeyUp, true)
}
}, [state.isOpen])
const onInsert = (emoji: Emoji) => {
textInputWebEmitter.emit('emoji-inserted', emoji)
close()
if (!isShiftDown.current) {
close()
}
}
const reducedPadding = useMediaQuery({query: '(max-height: 750px)'})
const noPadding = useMediaQuery({query: '(max-height: 550px)'})
const noPicker = useMediaQuery({query: '(max-height: 350px)'})
if (!state.isOpen) return null
return (
// eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors
<TouchableWithoutFeedback onPress={close} accessibilityViewIsModal>
<TouchableWithoutFeedback
accessibilityRole="button"
onPress={close}
accessibilityViewIsModal>
<View style={styles.mask}>
{/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors */}
<TouchableWithoutFeedback
onPress={e => {
e.stopPropagation() // prevent event from bubbling up to the mask
}}>
<View
style={[
styles.picker,
{
paddingTop: noPadding ? 0 : reducedPadding ? 150 : 325,
display: noPicker ? 'none' : 'flex',
},
]}>
<TouchableWithoutFeedback onPress={e => e.stopPropagation()}>
<View style={[{position: 'absolute'}, position]}>
<Picker
data={async () => {
return (await import('./EmojiPickerData.json')).default
@@ -93,15 +127,7 @@ const styles = StyleSheet.create({
right: 0,
width: '100%',
height: '100%',
},
trigger: {
backgroundColor: 'transparent',
// @ts-ignore web only -prf
border: 'none',
paddingTop: 4,
paddingLeft: 12,
paddingRight: 12,
cursor: 'pointer',
alignItems: 'center',
},
picker: {
marginHorizontal: 'auto',
+1 -1
View File
@@ -229,7 +229,7 @@ export function FeedSourceCardLoaded({
</View>
{showSaveBtn && feed.type === 'feed' && (
<View>
<View style={[s.justifyCenter]}>
<Pressable
testID={`feed-${feed.displayName}-toggleSave`}
disabled={isSavePending || isPinPending || isRemovePending}
+65 -82
View File
@@ -1,14 +1,12 @@
import React, {useMemo, useCallback, useState} from 'react'
import {
ImageStyle,
KeyboardAvoidingView,
ScrollView,
StyleSheet,
TextInput,
TouchableOpacity,
View,
useWindowDimensions,
} from 'react-native'
import {ScrollView, TextInput} from './util'
import {Image} from 'expo-image'
import {usePalette} from 'lib/hooks/usePalette'
import {gradients, s} from 'lib/styles'
@@ -17,13 +15,13 @@ import {MAX_ALT_TEXT} from 'lib/constants'
import {useTheme} from 'lib/ThemeContext'
import {Text} from '../util/text/Text'
import LinearGradient from 'react-native-linear-gradient'
import {isAndroid, isWeb} from 'platform/detection'
import {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']
export const snapPoints = ['100%']
interface Props {
image: ImageModel
@@ -54,102 +52,86 @@ export function Component({image}: Props) {
}
}, [image, windim])
const onUpdate = useCallback(
(v: string) => {
v = enforceLen(v, MAX_ALT_TEXT)
setAltText(v)
image.setAltText(v)
},
[setAltText, image],
)
const onPressSave = useCallback(() => {
image.setAltText(altText)
closeModal()
}, [closeModal, image, altText])
const onPressCancel = () => {
closeModal()
}
return (
<KeyboardAvoidingView
behavior={isAndroid ? 'height' : 'padding'}
style={[pal.view, styles.container]}>
<ScrollView
testID="altTextImageModal"
style={styles.scrollContainer}
keyboardShouldPersistTaps="always"
nativeID="imageAltText">
<View style={styles.scrollInner}>
<View style={[pal.viewLight, styles.imageContainer]}>
<Image
testID="selectedPhotoImage"
style={imageStyles}
source={{
uri: image.cropped?.path ?? image.path,
}}
contentFit="contain"
accessible={true}
accessibilityIgnoresInvertColors
/>
</View>
<TextInput
testID="altTextImageInput"
style={[styles.textArea, pal.border, pal.text]}
keyboardAppearance={theme.colorScheme}
multiline
placeholder="Add alt text"
placeholderTextColor={pal.colors.textLight}
value={altText}
onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))}
accessibilityLabel={_(msg`Image alt text`)}
accessibilityHint=""
accessibilityLabelledBy="imageAltText"
autoFocus
<ScrollView
testID="altTextImageModal"
style={[pal.view, styles.scrollContainer]}
keyboardShouldPersistTaps="always"
nativeID="imageAltText">
<View style={styles.scrollInner}>
<View style={[pal.viewLight, styles.imageContainer]}>
<Image
testID="selectedPhotoImage"
style={imageStyles}
source={{
uri: image.cropped?.path ?? image.path,
}}
contentFit="contain"
accessible={true}
accessibilityIgnoresInvertColors
/>
<View style={styles.buttonControls}>
<TouchableOpacity
testID="altTextImageSaveBtn"
onPress={onPressSave}
accessibilityLabel={_(msg`Save alt text`)}
accessibilityHint={`Saves alt text, which reads: ${altText}`}
accessibilityRole="button">
<LinearGradient
colors={[gradients.blueLight.start, gradients.blueLight.end]}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}
style={[styles.button]}>
<Text type="button-lg" style={[s.white, s.bold]}>
<Trans>Save</Trans>
</Text>
</LinearGradient>
</TouchableOpacity>
<TouchableOpacity
testID="altTextImageCancelBtn"
onPress={onPressCancel}
accessibilityRole="button"
accessibilityLabel={_(msg`Cancel add image alt text`)}
accessibilityHint=""
onAccessibilityEscape={onPressCancel}>
<View style={[styles.button]}>
<Text type="button-lg" style={[pal.textLight]}>
<Trans>Cancel</Trans>
</Text>
</View>
</TouchableOpacity>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
<TextInput
testID="altTextImageInput"
style={[styles.textArea, pal.border, pal.text]}
keyboardAppearance={theme.colorScheme}
multiline
placeholder={_(msg`Add alt text`)}
placeholderTextColor={pal.colors.textLight}
value={altText}
onChangeText={onUpdate}
accessibilityLabel={_(msg`Image alt text`)}
accessibilityHint=""
accessibilityLabelledBy="imageAltText"
autoFocus
/>
<View style={styles.buttonControls}>
<TouchableOpacity
testID="altTextImageSaveBtn"
onPress={onPressSave}
accessibilityLabel={_(msg`Save alt text`)}
accessibilityHint=""
accessibilityRole="button">
<LinearGradient
colors={[gradients.blueLight.start, gradients.blueLight.end]}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}
style={[styles.button]}>
<Text type="button-lg" style={[s.white, s.bold]}>
<Trans>Done</Trans>
</Text>
</LinearGradient>
</TouchableOpacity>
</View>
</View>
</ScrollView>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
height: '100%',
width: '100%',
paddingVertical: isWeb ? 0 : 18,
},
scrollContainer: {
flex: 1,
height: '100%',
paddingHorizontal: isWeb ? 0 : 12,
paddingVertical: isWeb ? 0 : 24,
},
scrollInner: {
gap: 12,
paddingTop: isWeb ? 0 : 12,
},
imageContainer: {
borderRadius: 8,
@@ -173,5 +155,6 @@ const styles = StyleSheet.create({
},
buttonControls: {
gap: 8,
paddingBottom: isWeb ? 0 : 50,
},
})
+153
View File
@@ -0,0 +1,153 @@
import React from 'react'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
import LinearGradient from 'react-native-linear-gradient'
import {s, colors, gradients} from 'lib/styles'
import {Text} from '../util/text/Text'
import {ScrollView} from './util'
import {usePalette} from 'lib/hooks/usePalette'
import {
EmbedPlayerSource,
embedPlayerSources,
externalEmbedLabels,
} from '#/lib/strings/embed-player'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals'
import {useSetExternalEmbedPref} from '#/state/preferences/external-embeds-prefs'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
export const snapPoints = [450]
export function Component({
onAccept,
source,
}: {
onAccept: () => void
source: EmbedPlayerSource
}) {
const pal = usePalette('default')
const {closeModal} = useModalControls()
const {_} = useLingui()
const setExternalEmbedPref = useSetExternalEmbedPref()
const {isMobile} = useWebMediaQueries()
const onShowAllPress = React.useCallback(() => {
for (const key of embedPlayerSources) {
setExternalEmbedPref(key, 'show')
}
onAccept()
closeModal()
}, [closeModal, onAccept, setExternalEmbedPref])
const onShowPress = React.useCallback(() => {
setExternalEmbedPref(source, 'show')
onAccept()
closeModal()
}, [closeModal, onAccept, setExternalEmbedPref, source])
const onHidePress = React.useCallback(() => {
setExternalEmbedPref(source, 'hide')
closeModal()
}, [closeModal, setExternalEmbedPref, source])
return (
<ScrollView
testID="embedConsentModal"
style={[
s.flex1,
pal.view,
isMobile
? {paddingHorizontal: 20, paddingTop: 10}
: {paddingHorizontal: 30},
]}>
<Text style={[pal.text, styles.title]}>
<Trans>External Media</Trans>
</Text>
<Text style={pal.text}>
<Trans>
This content is hosted by {externalEmbedLabels[source]}. Do you want
to enable external media?
</Trans>
</Text>
<View style={[s.mt10]} />
<Text style={pal.textLight}>
<Trans>
External media may allow websites to collect information about you and
your device. No information is sent or requested until you press the
"play" button.
</Trans>
</Text>
<View style={[s.mt20]} />
<TouchableOpacity
testID="enableAllBtn"
onPress={onShowAllPress}
accessibilityRole="button"
accessibilityLabel={_(
msg`Show embeds from ${externalEmbedLabels[source]}`,
)}
accessibilityHint=""
onAccessibilityEscape={closeModal}>
<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]}>
<Trans>Enable External Media</Trans>
</Text>
</LinearGradient>
</TouchableOpacity>
<View style={[s.mt10]} />
<TouchableOpacity
testID="enableSourceBtn"
onPress={onShowPress}
accessibilityRole="button"
accessibilityLabel={_(
msg`Never load embeds from ${externalEmbedLabels[source]}`,
)}
accessibilityHint=""
onAccessibilityEscape={closeModal}>
<View style={[styles.btn, pal.btn]}>
<Text style={[pal.text, s.bold, s.f18]}>
<Trans>Enable {externalEmbedLabels[source]} only</Trans>
</Text>
</View>
</TouchableOpacity>
<View style={[s.mt10]} />
<TouchableOpacity
testID="disableSourceBtn"
onPress={onHidePress}
accessibilityRole="button"
accessibilityLabel={_(
msg`Never load embeds from ${externalEmbedLabels[source]}`,
)}
accessibilityHint=""
onAccessibilityEscape={closeModal}>
<View style={[styles.btn, pal.btn]}>
<Text style={[pal.text, s.bold, s.f18]}>
<Trans>No thanks</Trans>
</Text>
</View>
</TouchableOpacity>
</ScrollView>
)
}
const styles = StyleSheet.create({
title: {
textAlign: 'center',
fontWeight: 'bold',
fontSize: 24,
marginBottom: 12,
},
btn: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
borderRadius: 32,
padding: 14,
backgroundColor: colors.gray1,
},
})
+4
View File
@@ -38,6 +38,7 @@ import * as VerifyEmailModal from './VerifyEmail'
import * as ChangeEmailModal from './ChangeEmail'
import * as SwitchAccountModal from './SwitchAccount'
import * as LinkWarningModal from './LinkWarning'
import * as EmbedConsentModal from './EmbedConsent'
const DEFAULT_SNAPPOINTS = ['90%']
const HANDLE_HEIGHT = 24
@@ -176,6 +177,9 @@ export function ModalsContainer() {
} else if (activeModal?.name === 'link-warning') {
snapPoints = LinkWarningModal.snapPoints
element = <LinkWarningModal.Component {...activeModal} />
} else if (activeModal?.name === 'embed-consent') {
snapPoints = EmbedConsentModal.snapPoints
element = <EmbedConsentModal.Component {...activeModal} />
} else {
return null
}
+3
View File
@@ -34,6 +34,7 @@ import * as BirthDateSettingsModal from './BirthDateSettings'
import * as VerifyEmailModal from './VerifyEmail'
import * as ChangeEmailModal from './ChangeEmail'
import * as LinkWarningModal from './LinkWarning'
import * as EmbedConsentModal from './EmbedConsent'
export function ModalsContainer() {
const {isModalActive, activeModals} = useModals()
@@ -129,6 +130,8 @@ function Modal({modal}: {modal: ModalIface}) {
element = <ChangeEmailModal.Component />
} else if (modal.name === 'link-warning') {
element = <LinkWarningModal.Component {...modal} />
} else if (modal.name === 'embed-consent') {
element = <EmbedConsentModal.Component {...modal} />
} else {
return null
}
@@ -0,0 +1,170 @@
import {EmbedPlayerParams, getGifDims} from 'lib/strings/embed-player'
import React from 'react'
import {Image, ImageLoadEventData} from 'expo-image'
import {
ActivityIndicator,
GestureResponderEvent,
LayoutChangeEvent,
Pressable,
StyleSheet,
View,
} from 'react-native'
import {isIOS, isNative, isWeb} from '#/platform/detection'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useExternalEmbedsPrefs} from 'state/preferences'
import {useModalControls} from 'state/modals'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {AppBskyEmbedExternal} from '@atproto/api'
export function ExternalGifEmbed({
link,
params,
}: {
link: AppBskyEmbedExternal.ViewExternal
params: EmbedPlayerParams
}) {
const externalEmbedsPrefs = useExternalEmbedsPrefs()
const {openModal} = useModalControls()
const {_} = useLingui()
const thumbHasLoaded = React.useRef(false)
const viewWidth = React.useRef(0)
// Tracking if the placer has been activated
const [isPlayerActive, setIsPlayerActive] = React.useState(false)
// Tracking whether the gif has been loaded yet
const [isPrefetched, setIsPrefetched] = React.useState(false)
// Tracking whether the image is animating
const [isAnimating, setIsAnimating] = React.useState(true)
const [imageDims, setImageDims] = React.useState({height: 100, width: 1})
// Used for controlling animation
const imageRef = React.useRef<Image>(null)
const load = React.useCallback(() => {
setIsPlayerActive(true)
Image.prefetch(params.playerUri).then(() => {
// Replace the image once it's fetched
setIsPrefetched(true)
})
}, [params.playerUri])
const onPlayPress = React.useCallback(
(event: GestureResponderEvent) => {
// Don't propagate on web
event.preventDefault()
// Show consent if this is the first load
if (externalEmbedsPrefs?.[params.source] === undefined) {
openModal({
name: 'embed-consent',
source: params.source,
onAccept: load,
})
return
}
// If the player isn't active, we want to activate it and prefetch the gif
if (!isPlayerActive) {
load()
return
}
// Control animation on native
setIsAnimating(prev => {
if (prev) {
if (isNative) {
imageRef.current?.stopAnimating()
}
return false
} else {
if (isNative) {
imageRef.current?.startAnimating()
}
return true
}
})
},
[externalEmbedsPrefs, isPlayerActive, load, openModal, params.source],
)
const onLoad = React.useCallback((e: ImageLoadEventData) => {
if (thumbHasLoaded.current) return
setImageDims(getGifDims(e.source.height, e.source.width, viewWidth.current))
thumbHasLoaded.current = true
}, [])
const onLayout = React.useCallback((e: LayoutChangeEvent) => {
viewWidth.current = e.nativeEvent.layout.width
}, [])
return (
<Pressable
style={[
{height: imageDims.height},
styles.topRadius,
styles.gifContainer,
]}
onPress={onPlayPress}
onLayout={onLayout}
accessibilityRole="button"
accessibilityHint={_(msg`Plays the GIF`)}
accessibilityLabel={_(msg`Play ${link.title}`)}>
{(!isPrefetched || !isAnimating) && ( // If we have not loaded or are not animating, show the overlay
<View style={[styles.layer, styles.overlayLayer]}>
<View style={[styles.overlayContainer, styles.topRadius]}>
{!isAnimating || !isPlayerActive ? ( // Play button when not animating or not active
<FontAwesomeIcon icon="play" size={42} color="white" />
) : (
// Activity indicator while gif loads
<ActivityIndicator size="large" color="white" />
)}
</View>
</View>
)}
<Image
source={{
uri:
!isPrefetched || (isWeb && !isAnimating)
? link.thumb
: params.playerUri,
}} // Web uses the thumb to control playback
style={{flex: 1}}
ref={imageRef}
onLoad={onLoad}
autoplay={isAnimating}
contentFit="contain"
accessibilityIgnoresInvertColors
accessibilityLabel={link.title}
accessibilityHint={link.title}
cachePolicy={isIOS ? 'disk' : 'memory-disk'} // cant control playback with memory-disk on ios
/>
</Pressable>
)
}
const styles = StyleSheet.create({
topRadius: {
borderTopLeftRadius: 6,
borderTopRightRadius: 6,
},
layer: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
overlayContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.5)',
},
overlayLayer: {
zIndex: 2,
},
gifContainer: {
width: '100%',
overflow: 'hidden',
},
})
@@ -8,6 +8,8 @@ import {AppBskyEmbedExternal} from '@atproto/api'
import {toNiceDomain} from 'lib/strings/url-helpers'
import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player'
import {ExternalPlayer} from 'view/com/util/post-embeds/ExternalPlayerEmbed'
import {ExternalGifEmbed} from 'view/com/util/post-embeds/ExternalGifEmbed'
import {useExternalEmbedsPrefs} from 'state/preferences'
export const ExternalLinkEmbed = ({
link,
@@ -16,36 +18,27 @@ export const ExternalLinkEmbed = ({
}) => {
const pal = usePalette('default')
const {isMobile} = useWebMediaQueries()
const externalEmbedPrefs = useExternalEmbedsPrefs()
const embedPlayerParams = React.useMemo(
() => parseEmbedPlayerFromUrl(link.uri),
[link.uri],
)
const embedPlayerParams = React.useMemo(() => {
const params = parseEmbedPlayerFromUrl(link.uri)
if (params && externalEmbedPrefs?.[params.source] !== 'hide') {
return params
}
}, [link.uri, externalEmbedPrefs])
return (
<View
style={{
flexDirection: !isMobile && !embedPlayerParams ? 'row' : 'column',
}}>
<View style={{flexDirection: 'column'}}>
{link.thumb && !embedPlayerParams ? (
<View
style={
!isMobile
? {
borderTopLeftRadius: 6,
borderBottomLeftRadius: 6,
width: 120,
aspectRatio: 1,
overflow: 'hidden',
}
: {
borderTopLeftRadius: 6,
borderTopRightRadius: 6,
width: '100%',
height: 200,
overflow: 'hidden',
}
}>
style={{
borderTopLeftRadius: 6,
borderTopRightRadius: 6,
width: '100%',
height: isMobile ? 200 : 300,
overflow: 'hidden',
}}>
<Image
style={styles.extImage}
source={{uri: link.thumb}}
@@ -53,15 +46,17 @@ export const ExternalLinkEmbed = ({
/>
</View>
) : undefined}
{embedPlayerParams && (
<ExternalPlayer link={link} params={embedPlayerParams} />
)}
{(embedPlayerParams?.isGif && (
<ExternalGifEmbed link={link} params={embedPlayerParams} />
)) ||
(embedPlayerParams && (
<ExternalPlayer link={link} params={embedPlayerParams} />
))}
<View
style={{
paddingHorizontal: isMobile ? 10 : 14,
paddingTop: 8,
paddingBottom: 10,
flex: !isMobile ? 1 : undefined,
}}>
<Text
type="sm"
@@ -69,16 +64,15 @@ export const ExternalLinkEmbed = ({
style={[pal.textLight, styles.extUri]}>
{toNiceDomain(link.uri)}
</Text>
<Text
type="lg-bold"
numberOfLines={isMobile ? 4 : 2}
style={[pal.text]}>
{link.title || link.uri}
</Text>
{link.description ? (
{!embedPlayerParams?.isGif && (
<Text type="lg-bold" numberOfLines={4} style={[pal.text]}>
{link.title || link.uri}
</Text>
)}
{link.description && !embedPlayerParams?.hideDetails ? (
<Text
type="md"
numberOfLines={isMobile ? 4 : 2}
numberOfLines={4}
style={[pal.text, styles.extDescription]}>
{link.description}
</Text>
@@ -90,8 +84,7 @@ export const ExternalLinkEmbed = ({
const styles = StyleSheet.create({
extImage: {
width: '100%',
height: 200,
flex: 1,
},
extUri: {
marginTop: 2,
@@ -1,22 +1,32 @@
import React from 'react'
import {
ActivityIndicator,
Dimensions,
GestureResponderEvent,
Pressable,
StyleSheet,
useWindowDimensions,
View,
} from 'react-native'
import Animated, {
measure,
runOnJS,
useAnimatedRef,
useFrameCallback,
} from 'react-native-reanimated'
import {Image} from 'expo-image'
import {WebView} from 'react-native-webview'
import YoutubePlayer from 'react-native-youtube-iframe'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {AppBskyEmbedExternal} from '@atproto/api'
import {EmbedPlayerParams, getPlayerHeight} from 'lib/strings/embed-player'
import {EventStopper} from '../EventStopper'
import {AppBskyEmbedExternal} from '@atproto/api'
import {isNative} from 'platform/detection'
import {useNavigation} from '@react-navigation/native'
import {NavigationProp} from 'lib/routes/types'
import {useExternalEmbedsPrefs} from 'state/preferences'
import {useModalControls} from 'state/modals'
interface ShouldStartLoadRequest {
url: string
@@ -32,6 +42,8 @@ function PlaceholderOverlay({
isPlayerActive: boolean
onPress: (event: GestureResponderEvent) => void
}) {
const {_} = useLingui()
// If the player is active and not loading, we don't want to show the overlay.
if (isPlayerActive && !isLoading) return null
@@ -39,8 +51,8 @@ function PlaceholderOverlay({
<View style={[styles.layer, styles.overlayLayer]}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Play Video"
accessibilityHint=""
accessibilityLabel={_(msg`Play Video`)}
accessibilityHint={_(msg`Play Video`)}
onPress={onPress}
style={[styles.overlayContainer, styles.topRadius]}>
{!isPlayerActive ? (
@@ -77,31 +89,21 @@ function Player({
return (
<View style={[styles.layer, styles.playerLayer]}>
<EventStopper>
{isNative && params.type === 'youtube_video' ? (
<YoutubePlayer
videoId={params.videoId}
play
height={height}
onReady={onLoad}
webViewStyle={[styles.webview, styles.topRadius]}
<View style={{height, width: '100%'}}>
<WebView
javaScriptEnabled={true}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
mediaPlaybackRequiresUserAction={false}
allowsInlineMediaPlayback
bounces={false}
allowsFullscreenVideo
nestedScrollEnabled
source={{uri: params.playerUri}}
onLoad={onLoad}
setSupportMultipleWindows={false} // Prevent any redirects from opening a new window (ads)
style={[styles.webview, styles.topRadius]}
/>
) : (
<View style={{height, width: '100%'}}>
<WebView
javaScriptEnabled={true}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
mediaPlaybackRequiresUserAction={false}
allowsInlineMediaPlayback
bounces={false}
allowsFullscreenVideo
nestedScrollEnabled
source={{uri: params.playerUri}}
onLoad={onLoad}
setSupportMultipleWindows={false} // Prevent any redirects from opening a new window (ads)
style={[styles.webview, styles.topRadius]}
/>
</View>
)}
</View>
</EventStopper>
</View>
)
@@ -116,6 +118,10 @@ export function ExternalPlayer({
params: EmbedPlayerParams
}) {
const navigation = useNavigation<NavigationProp>()
const insets = useSafeAreaInsets()
const windowDims = useWindowDimensions()
const externalEmbedsPrefs = useExternalEmbedsPrefs()
const {openModal} = useModalControls()
const [isPlayerActive, setPlayerActive] = React.useState(false)
const [isLoading, setIsLoading] = React.useState(true)
@@ -124,34 +130,51 @@ export function ExternalPlayer({
height: 0,
})
const viewRef = React.useRef<View>(null)
const viewRef = useAnimatedRef()
const frameCallback = useFrameCallback(() => {
const measurement = measure(viewRef)
if (!measurement) return
const {height: winHeight, width: winWidth} = windowDims
// Get the proper screen height depending on what is going on
const realWinHeight = isNative // If it is native, we always want the larger number
? winHeight > winWidth
? winHeight
: winWidth
: winHeight // On web, we always want the actual screen height
const top = measurement.pageY
const bot = measurement.pageY + measurement.height
// We can use the same logic on all platforms against the screenHeight that we get above
const isVisible = top <= realWinHeight - insets.bottom && bot >= insets.top
if (!isVisible) {
runOnJS(setPlayerActive)(false)
}
}, false) // False here disables autostarting the callback
// watch for leaving the viewport due to scrolling
React.useEffect(() => {
// We don't want to do anything if the player isn't active
if (!isPlayerActive) return
// Interval for scrolling works in most cases, However, for twitch embeds, if we navigate away from the screen the webview will
// continue playing. We need to watch for the blur event
const unsubscribe = navigation.addListener('blur', () => {
setPlayerActive(false)
})
const interval = setInterval(() => {
viewRef.current?.measure((x, y, w, h, pageX, pageY) => {
const window = Dimensions.get('window')
const top = pageY
const bot = pageY + h
const isVisible = isNative
? top >= 0 && bot <= window.height
: !(top >= window.height || bot <= 0)
if (!isVisible) {
setPlayerActive(false)
}
})
}, 1e3)
// Start watching for changes
frameCallback.setActive(true)
return () => {
unsubscribe()
clearInterval(interval)
frameCallback.setActive(false)
}
}, [viewRef, navigation])
}, [navigation, isPlayerActive, frameCallback])
// calculate height for the player and the screen size
const height = React.useMemo(
@@ -168,12 +191,26 @@ export function ExternalPlayer({
setIsLoading(false)
}, [])
const onPlayPress = React.useCallback((event: GestureResponderEvent) => {
// Prevent this from propagating upward on web
event.preventDefault()
const onPlayPress = React.useCallback(
(event: GestureResponderEvent) => {
// Prevent this from propagating upward on web
event.preventDefault()
setPlayerActive(true)
}, [])
if (externalEmbedsPrefs?.[params.source] === undefined) {
openModal({
name: 'embed-consent',
source: params.source,
onAccept: () => {
setPlayerActive(true)
},
})
return
}
setPlayerActive(true)
},
[externalEmbedsPrefs, openModal, params.source],
)
// measure the layout to set sizing
const onLayout = React.useCallback(
@@ -187,7 +224,7 @@ export function ExternalPlayer({
)
return (
<View
<Animated.View
ref={viewRef}
style={{height}}
collapsable={false}
@@ -205,7 +242,6 @@ export function ExternalPlayer({
accessibilityIgnoresInvertColors
/>
)}
<PlaceholderOverlay
isLoading={isLoading}
isPlayerActive={isPlayerActive}
@@ -217,7 +253,7 @@ export function ExternalPlayer({
height={height}
onLoad={onLoad}
/>
</View>
</Animated.View>
)
}
@@ -248,4 +284,8 @@ const styles = StyleSheet.create({
webview: {
backgroundColor: 'transparent',
},
gifContainer: {
width: '100%',
overflow: 'hidden',
},
})
@@ -98,6 +98,7 @@ export function QuoteEmbed({
return (
<Link
style={[styles.container, pal.borderDark, style]}
hoverStyle={{borderColor: pal.colors.borderLinkHover}}
href={itemHref}
title={itemTitle}>
<PostMeta
+9 -9
View File
@@ -63,7 +63,7 @@ export function PostEmbeds({
const mediaModeration = isModOnQuote ? {} : moderation
const quoteModeration = isModOnQuote ? moderation : {}
return (
<View style={[styles.stackContainer, style]}>
<View style={style}>
<PostEmbeds embed={embed.media} moderation={mediaModeration} />
<ContentHider moderation={quoteModeration}>
<MaybeQuoteEmbed embed={embed.record} moderation={quoteModeration} />
@@ -168,11 +168,14 @@ export function PostEmbeds({
const link = embed.external
return (
<View style={[styles.extOuter, pal.view, pal.border, style]}>
<Link asAnchor href={link.uri}>
<ExternalLinkEmbed link={link} />
</Link>
</View>
<Link
asAnchor
anchorNoUnderline
href={link.uri}
style={[styles.extOuter, pal.view, pal.borderDark, style]}
hoverStyle={{borderColor: pal.colors.borderLinkHover}}>
<ExternalLinkEmbed link={link} />
</Link>
)
}
@@ -180,9 +183,6 @@ export function PostEmbeds({
}
const styles = StyleSheet.create({
stackContainer: {
gap: 6,
},
imagesContainer: {
marginTop: 8,
},
+6 -4
View File
@@ -29,9 +29,10 @@ import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight'
import {faCircle} from '@fortawesome/free-regular-svg-icons/faCircle'
import {faCircleCheck as farCircleCheck} from '@fortawesome/free-regular-svg-icons/faCircleCheck'
import {faCircleCheck} from '@fortawesome/free-solid-svg-icons/faCircleCheck'
import {faCircleExclamation} from '@fortawesome/free-solid-svg-icons/faCircleExclamation'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faCircleDot} from '@fortawesome/free-solid-svg-icons/faCircleDot'
import {faCircleExclamation} from '@fortawesome/free-solid-svg-icons/faCircleExclamation'
import {faCirclePlay} from '@fortawesome/free-regular-svg-icons/faCirclePlay'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faClone} from '@fortawesome/free-solid-svg-icons/faClone'
import {faClone as farClone} from '@fortawesome/free-regular-svg-icons/faClone'
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
@@ -129,9 +130,10 @@ library.add(
faCircle,
faCircleCheck,
farCircleCheck,
faCircleExclamation,
faCircleUser,
faCircleDot,
faCircleExclamation,
faCirclePlay,
faCircleUser,
faClone,
farClone,
faComment,
+4 -1
View File
@@ -19,6 +19,7 @@ import {useSession} from '#/state/session'
import {loadString, saveString} from '#/lib/storage'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {clamp} from '#/lib/numbers'
import {PROD_DEFAULT_FEED} from '#/lib/constants'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export function HomeScreen(props: Props) {
@@ -109,7 +110,9 @@ function HomeScreenReady({
const homeFeedParams = React.useMemo<FeedParams>(() => {
return {
mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled),
mergeFeedSources: preferences.feeds.saved,
mergeFeedSources: preferences.feedViewPrefs.lab_mergeFeedEnabled
? preferences.feeds.saved
: [PROD_DEFAULT_FEED('whats-hot')],
}
}, [preferences])
+7 -1
View File
@@ -62,7 +62,7 @@ export function ModerationScreen({}: Props) {
]}
testID="moderationScreen">
<ViewHeader title={_(msg`Moderation`)} showOnDesktop />
<ScrollView>
<ScrollView contentContainerStyle={[styles.noBorder]}>
<View style={styles.spacer} />
<TouchableOpacity
testID="contentFilteringBtn"
@@ -275,4 +275,10 @@ const styles = StyleSheet.create({
borderRadius: 30,
marginRight: 12,
},
noBorder: {
borderBottomWidth: 0,
borderRightWidth: 0,
borderLeftWidth: 0,
borderTopWidth: 0,
},
})
@@ -0,0 +1,138 @@
import React from 'react'
import {StyleSheet, View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {s} from 'lib/styles'
import {Text} from '../com/util/text/Text'
import {usePalette} from 'lib/hooks/usePalette'
import {useAnalytics} from 'lib/analytics/analytics'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {
EmbedPlayerSource,
externalEmbedLabels,
} from '#/lib/strings/embed-player'
import {useSetMinimalShellMode} from '#/state/shell'
import {Trans} from '@lingui/macro'
import {ScrollView} from '../com/util/Views'
import {
useExternalEmbedsPrefs,
useSetExternalEmbedPref,
} from 'state/preferences'
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
import {SimpleViewHeader} from '../com/util/SimpleViewHeader'
type Props = NativeStackScreenProps<
CommonNavigatorParams,
'PreferencesExternalEmbeds'
>
export function PreferencesExternalEmbeds({}: Props) {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {screen} = useAnalytics()
const {isMobile} = useWebMediaQueries()
useFocusEffect(
React.useCallback(() => {
screen('PreferencesExternalEmbeds')
setMinimalShellMode(false)
}, [screen, setMinimalShellMode]),
)
return (
<View style={s.hContentRegion} testID="preferencesExternalEmbedsScreen">
<SimpleViewHeader
showBackButton={isMobile}
style={[
pal.border,
{borderBottomWidth: 1},
!isMobile && {borderLeftWidth: 1, borderRightWidth: 1},
]}>
<View style={{flex: 1}}>
<Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}>
<Trans>External Media Preferences</Trans>
</Text>
<Text style={pal.textLight}>
<Trans>Customize media from external sites.</Trans>
</Text>
</View>
</SimpleViewHeader>
<ScrollView
// @ts-ignore web only -prf
dataSet={{'stable-gutters': 1}}
contentContainerStyle={[pal.viewLight, {paddingBottom: 200}]}>
<View style={[pal.view]}>
<View style={styles.infoCard}>
<Text style={pal.text}>
<Trans>
External media may allow websites to collect information about
you and your device. No information is sent or requested until
you press the "play" button.
</Trans>
</Text>
</View>
</View>
<Text type="xl-bold" style={[pal.text, styles.heading]}>
Enable media players for
</Text>
{Object.entries(externalEmbedLabels).map(([key, label]) => (
<PrefSelector
source={key as EmbedPlayerSource}
label={label}
key={key}
/>
))}
</ScrollView>
</View>
)
}
function PrefSelector({
source,
label,
}: {
source: EmbedPlayerSource
label: string
}) {
const pal = usePalette('default')
const setExternalEmbedPref = useSetExternalEmbedPref()
const sources = useExternalEmbedsPrefs()
return (
<View>
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label={label}
labelType="lg"
isSelected={sources?.[source] === 'show'}
onPress={() =>
setExternalEmbedPref(
source,
sources?.[source] === 'show' ? 'hide' : 'show',
)
}
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
heading: {
paddingHorizontal: 18,
paddingTop: 14,
paddingBottom: 14,
},
spacer: {
height: 8,
},
infoCard: {
paddingHorizontal: 20,
paddingVertical: 14,
},
toggleCard: {
paddingVertical: 8,
paddingHorizontal: 6,
marginBottom: 1,
},
})
+7 -1
View File
@@ -29,6 +29,7 @@ function RepliesThresholdInput({
const pal = usePalette('default')
const [value, setValue] = useState(initialValue)
const {mutate: setFeedViewPref} = useSetFeedViewPreferencesMutation()
const preValue = React.useRef(initialValue)
const save = React.useMemo(
() =>
debounce(
@@ -46,7 +47,12 @@ function RepliesThresholdInput({
<Slider
value={value}
onValueChange={(v: number | number[]) => {
const threshold = Math.floor(Array.isArray(v) ? v[0] : v)
let threshold = Array.isArray(v) ? v[0] : v
if (threshold > preValue.current) threshold = Math.floor(threshold)
else threshold = Math.ceil(threshold)
preValue.current = threshold
setValue(threshold)
save(threshold)
}}
+9 -3
View File
@@ -82,7 +82,7 @@ export function SavedFeeds({}: Props) {
isTabletOrDesktop && styles.desktopContainer,
]}>
<ViewHeader title={_(msg`Edit My Feeds`)} showOnDesktop showBorder />
<ScrollView style={s.flex1}>
<ScrollView style={s.flex1} contentContainerStyle={[styles.noBorder]}>
<View style={[pal.text, pal.border, styles.title]}>
<Text type="title" style={pal.text}>
<Trans>Pinned Feeds</Trans>
@@ -288,7 +288,7 @@ function ListItem({
<FeedSourceCard
key={feedUri}
feedUri={feedUri}
style={styles.noBorder}
style={styles.noTopBorder}
showSaveBtn
showMinimalPlaceholder
/>
@@ -344,7 +344,7 @@ const styles = StyleSheet.create({
webArrowUpButton: {
marginBottom: 10,
},
noBorder: {
noTopBorder: {
borderTopWidth: 0,
},
footerText: {
@@ -352,4 +352,10 @@ const styles = StyleSheet.create({
paddingTop: 22,
paddingBottom: 100,
},
noBorder: {
borderBottomWidth: 0,
borderRightWidth: 0,
borderLeftWidth: 0,
borderTopWidth: 0,
},
})
+34 -1
View File
@@ -419,7 +419,7 @@ export function SettingsScreen({}: Props) {
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label="Require alt text before posting"
label={_(msg`Require alt text before posting`)}
labelType="lg"
isSelected={requireAltTextEnabled}
onPress={() => setRequireAltTextEnabled(!requireAltTextEnabled)}
@@ -563,6 +563,39 @@ export function SettingsScreen({}: Props) {
<Trans>Moderation</Trans>
</Text>
</TouchableOpacity>
<View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Privacy</Trans>
</Text>
<TouchableOpacity
testID="externalEmbedsBtn"
style={[
styles.linkCard,
pal.view,
isSwitchingAccounts && styles.dimmed,
]}
onPress={
isSwitchingAccounts
? undefined
: () => navigation.navigate('PreferencesExternalEmbeds')
}
accessibilityRole="button"
accessibilityHint=""
accessibilityLabel={_(msg`Opens external embeds settings`)}>
<View style={[styles.iconContainer, pal.btn]}>
<FontAwesomeIcon
icon={['far', 'circle-play']}
style={pal.text as FontAwesomeIconStyle}
/>
</View>
<Text type="lg" style={pal.text}>
<Trans>External Media Preferences</Trans>
</Text>
</TouchableOpacity>
<View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}>
+26
View File
@@ -5,6 +5,10 @@ import {ComposePost} from '../com/composer/Composer'
import {useComposerState} from 'state/shell/composer'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {
EmojiPicker,
EmojiPickerState,
} from 'view/com/composer/text-input/web/EmojiPicker.web.tsx'
const BOTTOM_BAR_HEIGHT = 61
@@ -13,6 +17,26 @@ export function Composer({}: {winHeight: number}) {
const {isMobile} = useWebMediaQueries()
const state = useComposerState()
const [pickerState, setPickerState] = React.useState<EmojiPickerState>({
isOpen: false,
pos: {top: 0, left: 0, right: 0, bottom: 0},
})
const onOpenPicker = React.useCallback((pos: DOMRect | undefined) => {
if (!pos) return
setPickerState({
isOpen: true,
pos,
})
}, [])
const onClosePicker = React.useCallback(() => {
setPickerState(prev => ({
...prev,
isOpen: false,
}))
}, [])
// rendering
// =
@@ -41,8 +65,10 @@ export function Composer({}: {winHeight: number}) {
quote={state.quote}
onPost={state.onPost}
mention={state.mention}
openPicker={onOpenPicker}
/>
</Animated.View>
<EmojiPicker state={pickerState} close={onClosePicker} />
</Animated.View>
)
}
+3 -3
View File
@@ -180,14 +180,14 @@ const styles = StyleSheet.create({
position: 'absolute',
// @ts-ignore web only
left: 'calc(50vw + 320px)',
width: 304,
width: 300,
maxHeight: '100%',
overflowY: 'auto',
},
message: {
paddingVertical: 18,
paddingHorizontal: 10,
paddingHorizontal: 12,
},
messageLine: {
marginBottom: 10,
@@ -195,7 +195,7 @@ const styles = StyleSheet.create({
inviteCodes: {
borderTopWidth: 1,
paddingHorizontal: 16,
paddingHorizontal: 12,
paddingVertical: 12,
flexDirection: 'row',
},
+46
View File
@@ -0,0 +1,46 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"types": ["react-native", "jest"],
"lib": [
"es2019",
"es2020.bigint",
"es2020.date",
"es2020.number",
"es2020.promise",
"es2020.string",
"es2020.symbol.wellknown",
"es2021.promise",
"es2021.string",
"es2021.weakref",
"es2022.array",
"es2022.object",
"es2022.string"
],
"allowJs": true,
"jsx": "react-native",
"noEmit": true,
"isolatedModules": true,
"strict": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": false,
"esModuleInterop": true,
"paths": {
"#/*": ["./src/*"],
"lib/*": ["./src/lib/*"],
"platform/*": ["./src/platform/*"],
"state/*": ["./src/state/*"],
"view/*": ["./src/view/*"],
"crypto": ["./src/platform/crypto.ts"]
}
},
"exclude": [
"node_modules",
"babel.config.js",
"metro.config.js",
"jest.config.js"
]
}
+54 -19
View File
@@ -3335,6 +3335,11 @@
resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a"
integrity sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==
"@flatten-js/interval-tree@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@flatten-js/interval-tree/-/interval-tree-1.1.2.tgz#fcc891da48bc230392884be01c26fe8c625702e8"
integrity sha512-OwLoV9E/XM6b7bes2rSFnGNjyRy7vcoIHFTnmBR2WAaZTf0Fe4EX4GdA65vU1KgFAasti7iRSg2dZfYd1Zt00Q==
"@floating-ui/core@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.1.tgz#0d633f4b76052668afb932492ac452f7ebe97f17"
@@ -8986,6 +8991,16 @@ builtins@^1.0.3:
resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==
bunyamin@^1.5.0:
version "1.5.1"
resolved "https://registry.yarnpkg.com/bunyamin/-/bunyamin-1.5.1.tgz#14df1b2f0b82d781d8f8d81eb2e83542353ac8d7"
integrity sha512-VgWWb3G3HwajZF8fFM8TJjkWOqeDBZgzWBeQb7EhKQTQd33Zri0nghLeg4r86kQqqNlo/p9Jjgwh/O7Q6XpZIg==
dependencies:
"@flatten-js/interval-tree" "^1.1.2"
multi-sort-stream "^1.0.4"
stream-json "^1.7.5"
trace-event-lib "^1.3.1"
bunyan-debug-stream@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bunyan-debug-stream/-/bunyan-debug-stream-3.1.0.tgz#78309c67ad85cfb8f011155334152c49209dcda8"
@@ -9003,6 +9018,18 @@ bunyan@^1.8.12:
mv "~2"
safe-json-stringify "~1"
bunyan@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-2.0.5.tgz#9dd056755220dddd8b5bb9cf76f3d0d766e96e71"
integrity sha512-Jvl74TdxCN6rSP9W1I6+UOUtwslTDqsSFkDqZlFb/ilaSvQ+bZAnXT/GT97IZ5L+Vph0joPZPhxUyn6FLNmFAA==
dependencies:
exeunt "1.1.0"
optionalDependencies:
dtrace-provider "~0.8"
moment "^2.19.3"
mv "~2"
safe-json-stringify "~1"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
@@ -10304,10 +10331,10 @@ detect-port-alt@^1.1.6:
address "^1.0.1"
debug "^2.6.0"
detox@^20.13.0:
version "20.13.0"
resolved "https://registry.yarnpkg.com/detox/-/detox-20.13.0.tgz#923111638dfdb16089eea4f07bf4f0b56468d097"
integrity sha512-p9MUcoHWFTqSDaoaN+/hnJYdzNYqdelUr/sxzy3zLoS/qehnVJv2yG9pYqz/+gKpJaMIpw2+TVw9imdAx5JpaA==
detox@^20.14.8:
version "20.14.8"
resolved "https://registry.yarnpkg.com/detox/-/detox-20.14.8.tgz#0a550cf677fc98a68d56d162e1c5caad317de9ca"
integrity sha512-3E/0/7Cb7x+wcBsZpCxD8FykZUsFnfVT00d6PWH940boc0Mo1Kzabh+I151X/On4qZMqVdUzgwmap/z8g/kmaw==
dependencies:
ajv "^8.6.3"
bunyan "^1.8.12"
@@ -10321,6 +10348,7 @@ detox@^20.13.0:
funpermaproxy "^1.1.0"
glob "^8.0.3"
ini "^1.3.4"
jest-environment-emit "^1.0.5"
json-cycle "^1.3.0"
lodash "^4.17.11"
multi-sort-stream "^1.0.3"
@@ -11339,6 +11367,11 @@ execa@^5.0.0, execa@^5.1.1:
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
exeunt@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/exeunt/-/exeunt-1.1.0.tgz#af72db6f94b3cb75e921aee375d513049843d284"
integrity sha512-dd++Yn/0Fp+gtJ04YHov7MeAii+LFivJc6KqnJNfplzLVUkUDrfKoQDTLlCgzcW15vY5hKlHasWeIsQJ8agHsw==
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
@@ -13772,6 +13805,20 @@ jest-each@^29.7.0:
jest-util "^29.7.0"
pretty-format "^29.7.0"
jest-environment-emit@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/jest-environment-emit/-/jest-environment-emit-1.0.5.tgz#e6f33451f98b88ccd48e9e1188bb535880f03c1b"
integrity sha512-OsQ08AhYxkkyDBTIow+9ogNmJheQIGWQKp0Nku+1ToLWjAj2Pd6LmypN8HgUIqYHs4HFcqkQ25kaf1qExmoZpg==
dependencies:
bunyamin "^1.5.0"
bunyan "^2.0.5"
bunyan-debug-stream "^3.1.0"
funpermaproxy "^1.1.0"
lodash.merge "^4.6.2"
node-ipc "9.2.1"
strip-ansi "^6.0.0"
tslib "^2.5.3"
jest-environment-jsdom@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546"
@@ -15868,7 +15915,7 @@ ms@2.1.3, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
multi-sort-stream@^1.0.3:
multi-sort-stream@^1.0.3, multi-sort-stream@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/multi-sort-stream/-/multi-sort-stream-1.0.4.tgz#e4348edc9edc36e16333e531a90c0f166235cc99"
integrity sha512-hAZ8JOEQFbgdLe8HWZbb7gdZg0/yAIHF00Qfo3kd0rXFv96nXe+/bPTrKHZ2QMHugGX4FiAyET1Lt+jiB+7Qlg==
@@ -18198,11 +18245,6 @@ react-native-screens@~3.27.0:
react-freeze "^1.0.0"
warn-once "^0.1.0"
react-native-splash-screen@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.3.0.tgz#3af71ed17afe50fee69590a45aec399d071ead02"
integrity sha512-rGjt6HkoSXxMqH4SQUJ1gnPQlPJV8+J47+4yhgTIan4bVvAwJhEeJH7wWt9hXSdH4+VfwTS0GTaflj1Tw83IhA==
react-native-svg@14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-14.0.0.tgz#ea1974dec9a91a09c6a38b7bf58d85e857c291f5"
@@ -18262,13 +18304,6 @@ react-native-webview@^13.6.3:
escape-string-regexp "2.0.0"
invariant "2.2.4"
react-native-youtube-iframe@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/react-native-youtube-iframe/-/react-native-youtube-iframe-2.3.0.tgz#40ca8e55db929b91bfa8e8d30e411658cbc304c5"
integrity sha512-M+z63xwXVtS4dX3k8PbtHUUcWN+gRZt6J1EtPE7Y60BMOB979KjpkdrHqeR96or9pNR2W8K5tQhIkMXW2jwo7Q==
dependencies:
events "^3.2.0"
react-native@0.73.1:
version "0.73.1"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.1.tgz#5eafaa7e54feeab8b55e8b8e4efc4d21052a4fff"
@@ -19624,7 +19659,7 @@ stream-chain@^2.2.5:
resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09"
integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==
stream-json@^1.7.4:
stream-json@^1.7.4, stream-json@^1.7.5:
version "1.8.0"
resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.8.0.tgz#53f486b2e3b4496c506131f8d7260ba42def151c"
integrity sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==
@@ -20398,7 +20433,7 @@ tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0:
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0, tslib@^2.5.3:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==