feat(mobile): translation for operation (#3396)
This commit is contained in:
parent
c471acc2dd
commit
7efa6aa96a
|
|
@ -6,6 +6,7 @@ import { saveToLibraryAsync } from "expo-media-library"
|
|||
import { shareAsync } from "expo-sharing"
|
||||
import type { PropsWithChildren } from "react"
|
||||
import { useRef } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import type { View } from "react-native"
|
||||
import { findNodeHandle, Image, Pressable } from "react-native"
|
||||
|
||||
|
|
@ -35,6 +36,7 @@ const getIOSNativeImageActions = () => {
|
|||
}
|
||||
|
||||
export const ImageContextMenu = ({ imageUrl, entryId, children }: ImageContextMenuProps) => {
|
||||
const { t } = useTranslation()
|
||||
const entry = useEntry(entryId!)
|
||||
const feedId = entry?.feedId
|
||||
const view = useSelectedView()
|
||||
|
|
@ -105,7 +107,9 @@ export const ImageContextMenu = ({ imageUrl, entryId, children }: ImageContextMe
|
|||
name: isEntryStarred ? "star.slash" : "star",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>{isEntryStarred ? "Unstar" : "Star"}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>
|
||||
{isEntryStarred ? t("operation.unstar") : t("operation.star")}
|
||||
</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
)}
|
||||
|
||||
|
|
@ -183,7 +187,7 @@ export const ImageContextMenu = ({ imageUrl, entryId, children }: ImageContextMe
|
|||
name: "square.and.arrow.up",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>Share</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.share")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { cn } from "@follow/utils"
|
||||
import { t } from "i18next"
|
||||
import type { Dispatch, FC, ReactElement, ReactNode, SetStateAction } from "react"
|
||||
import {
|
||||
cloneElement,
|
||||
|
|
@ -213,14 +214,14 @@ class DialogStatic {
|
|||
<View className="flex-row gap-4 px-6 pb-4">
|
||||
<DialogDynamicButtonAction
|
||||
fallbackCaller={handleClose}
|
||||
text={override?.cancelText ?? props.cancelText ?? "Cancel"}
|
||||
text={override?.cancelText ?? props.cancelText ?? t("common:words.cancel")}
|
||||
type="cancel"
|
||||
textClassName={cn(props.variant === "destructive" && "font-bold")}
|
||||
/>
|
||||
|
||||
<DialogDynamicButtonAction
|
||||
fallbackCaller={handleConfirm}
|
||||
text={override?.confirmText ?? props.confirmText ?? "Confirm"}
|
||||
text={override?.confirmText ?? props.confirmText ?? t("common:words.confirm")}
|
||||
type="confirm"
|
||||
className={props.variant === "destructive" ? "bg-red" : "bg-accent"}
|
||||
textClassName={cn(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { PortalProvider } from "@gorhom/portal"
|
||||
import type { PropsWithChildren } from "react"
|
||||
import { useCallback } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Share, Text, View } from "react-native"
|
||||
|
||||
import {
|
||||
|
|
@ -19,6 +20,7 @@ import { useEntry } from "@/src/store/entry/hooks"
|
|||
import { unreadSyncService } from "@/src/store/unread/store"
|
||||
|
||||
export const EntryItemContextMenu = ({ id, children }: PropsWithChildren<{ id: string }>) => {
|
||||
const { t } = useTranslation()
|
||||
const entry = useEntry(id)
|
||||
const feedId = entry?.feedId
|
||||
const view = useSelectedView()
|
||||
|
|
@ -62,7 +64,7 @@ export const EntryItemContextMenu = ({ id, children }: PropsWithChildren<{ id: s
|
|||
unreadSyncService.markEntryAsRead(id)
|
||||
}}
|
||||
>
|
||||
<ContextMenu.ItemTitle>Mark as Read</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.mark_as_read")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "checkmark",
|
||||
|
|
@ -92,7 +94,9 @@ export const EntryItemContextMenu = ({ id, children }: PropsWithChildren<{ id: s
|
|||
name: isEntryStarred ? "star.slash" : "star",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>{isEntryStarred ? "Unstar" : "Star"}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>
|
||||
{isEntryStarred ? t("operation.unstar") : t("operation.star")}
|
||||
</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
)}
|
||||
|
||||
|
|
@ -109,7 +113,7 @@ export const EntryItemContextMenu = ({ id, children }: PropsWithChildren<{ id: s
|
|||
name: "link",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>Open Link</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.open_link")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
)}
|
||||
|
||||
|
|
@ -130,7 +134,7 @@ export const EntryItemContextMenu = ({ id, children }: PropsWithChildren<{ id: s
|
|||
name: "square.and.arrow.up",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>Share</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.share")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
)}
|
||||
</ContextMenu.Content>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { FeedViewType } from "@follow/constants"
|
||||
import type { FC, PropsWithChildren } from "react"
|
||||
import { useCallback, useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import type { ListRenderItemInfo } from "react-native"
|
||||
import { Alert, Clipboard, FlatList, View } from "react-native"
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ export const SubscriptionFeedItemContextMenu: FC<
|
|||
view?: FeedViewType
|
||||
}
|
||||
> = ({ id, children, view }) => {
|
||||
const { t } = useTranslation()
|
||||
const allCategories = useSubscriptionCategory(view)
|
||||
const navigation = useNavigation()
|
||||
return (
|
||||
|
|
@ -50,7 +52,7 @@ export const SubscriptionFeedItemContextMenu: FC<
|
|||
unreadSyncService.markFeedAsRead(id)
|
||||
}, [id])}
|
||||
>
|
||||
<ContextMenu.ItemTitle>Mark All As Read</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.mark_all_as_read")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "checklist.checked",
|
||||
|
|
@ -78,7 +80,7 @@ export const SubscriptionFeedItemContextMenu: FC<
|
|||
|
||||
<ContextMenu.Sub key="AddToCategory">
|
||||
<ContextMenu.SubTrigger key="SubTrigger/AddToCategory">
|
||||
<ContextMenu.ItemTitle>Add To Category</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.add_feeds_to_category")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.SubTrigger>
|
||||
|
||||
<ContextMenu.SubContent>
|
||||
|
|
@ -126,7 +128,7 @@ export const SubscriptionFeedItemContextMenu: FC<
|
|||
</ContextMenu.Sub>
|
||||
|
||||
<ContextMenu.Item key="Edit">
|
||||
<ContextMenu.ItemTitle>Edit</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.edit")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "square.and.pencil",
|
||||
|
|
@ -152,7 +154,7 @@ export const SubscriptionFeedItemContextMenu: FC<
|
|||
}
|
||||
}, [id])}
|
||||
>
|
||||
<ContextMenu.ItemTitle>Copy Link</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.copy_link")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "link",
|
||||
|
|
@ -171,16 +173,16 @@ export const SubscriptionFeedItemContextMenu: FC<
|
|||
style: "cancel",
|
||||
},
|
||||
{
|
||||
text: "Unsubscribe",
|
||||
text: t("operation.unfollow"),
|
||||
style: "destructive",
|
||||
onPress: () => {
|
||||
subscriptionSyncService.unsubscribe(id)
|
||||
},
|
||||
},
|
||||
])
|
||||
}, [id])}
|
||||
}, [id, t])}
|
||||
>
|
||||
<ContextMenu.ItemTitle>Unsubscribe</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.unfollow")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "xmark",
|
||||
|
|
@ -202,6 +204,7 @@ export const SubscriptionFeedCategoryContextMenu = ({
|
|||
feedIds: string[]
|
||||
view: FeedViewType
|
||||
}>) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<ContextMenu.Root>
|
||||
<ContextMenu.Trigger>{children}</ContextMenu.Trigger>
|
||||
|
|
@ -213,7 +216,7 @@ export const SubscriptionFeedCategoryContextMenu = ({
|
|||
unreadSyncService.markFeedAsRead(feedIds)
|
||||
}, [feedIds])}
|
||||
>
|
||||
<ContextMenu.ItemTitle>Mark All As Read</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.mark_all_as_read")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "checklist.checked",
|
||||
|
|
@ -223,7 +226,7 @@ export const SubscriptionFeedCategoryContextMenu = ({
|
|||
|
||||
<ContextMenu.Sub key="ChangeToOtherView">
|
||||
<ContextMenu.SubTrigger key="SubTrigger/ChangeToOtherView">
|
||||
<ContextMenu.ItemTitle>Change To Other View</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.change_to_other_view")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.SubTrigger>
|
||||
|
||||
<ContextMenu.SubContent>
|
||||
|
|
@ -243,7 +246,7 @@ export const SubscriptionFeedCategoryContextMenu = ({
|
|||
</ContextMenu.Sub>
|
||||
|
||||
<ContextMenu.Item key="EditCategory">
|
||||
<ContextMenu.ItemTitle>Edit Category</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.rename_category")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "square.and.pencil",
|
||||
|
|
@ -251,7 +254,7 @@ export const SubscriptionFeedCategoryContextMenu = ({
|
|||
/>
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item key="DeleteCategory" destructive>
|
||||
<ContextMenu.ItemTitle>Delete Category</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.delete_category")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "trash",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { env } from "@follow/shared/src/env"
|
||||
import type { FC, PropsWithChildren } from "react"
|
||||
import { useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Alert, Clipboard } from "react-native"
|
||||
|
||||
import { ContextMenu } from "@/src/components/ui/context-menu"
|
||||
|
|
@ -14,11 +15,12 @@ export const SubscriptionListItemContextMenu: FC<
|
|||
id: string
|
||||
}
|
||||
> = ({ id, children }) => {
|
||||
const { t } = useTranslation()
|
||||
const isOwnList = useIsOwnList(id)
|
||||
const actions = useMemo(
|
||||
() => [
|
||||
isOwnList && {
|
||||
title: "Edit",
|
||||
title: t("operation.edit"),
|
||||
onSelect: () => {
|
||||
const list = getList(id)
|
||||
if (!list) return
|
||||
|
|
@ -26,7 +28,7 @@ export const SubscriptionListItemContextMenu: FC<
|
|||
},
|
||||
},
|
||||
{
|
||||
title: "Copy Link",
|
||||
title: t("operation.copy_link"),
|
||||
onSelect: () => {
|
||||
const list = getList(id)
|
||||
if (!list) return
|
||||
|
|
@ -35,16 +37,16 @@ export const SubscriptionListItemContextMenu: FC<
|
|||
},
|
||||
},
|
||||
{
|
||||
title: "Unsubscribe",
|
||||
title: t("operation.unfollow"),
|
||||
destructive: true,
|
||||
onSelect: () => {
|
||||
Alert.alert("Unsubscribe", "Are you sure you want to unsubscribe?", [
|
||||
Alert.alert(t("operation.unfollow"), "Are you sure you want to unsubscribe?", [
|
||||
{
|
||||
text: "Cancel",
|
||||
style: "cancel",
|
||||
},
|
||||
{
|
||||
text: "Unsubscribe",
|
||||
text: t("operation.unfollow"),
|
||||
style: "destructive",
|
||||
onPress: () => {
|
||||
subscriptionSyncService.unsubscribe(id)
|
||||
|
|
@ -54,7 +56,7 @@ export const SubscriptionListItemContextMenu: FC<
|
|||
},
|
||||
},
|
||||
],
|
||||
[id, isOwnList],
|
||||
[id, isOwnList, t],
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { PropsWithChildren } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Clipboard, Share } from "react-native"
|
||||
|
||||
import { ContextMenu } from "@/src/components/ui/context-menu"
|
||||
|
|
@ -14,6 +15,7 @@ type VideoContextMenuProps = PropsWithChildren<{
|
|||
}>
|
||||
|
||||
export const VideoContextMenu = ({ entryId, children }: VideoContextMenuProps) => {
|
||||
const { t } = useTranslation()
|
||||
const entry = useEntry(entryId)
|
||||
const feedId = entry?.feedId
|
||||
const view = useSelectedView()
|
||||
|
|
@ -50,7 +52,9 @@ export const VideoContextMenu = ({ entryId, children }: VideoContextMenuProps) =
|
|||
name: isEntryStarred ? "star.slash" : "star",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>{isEntryStarred ? "Unstar" : "Star"}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>
|
||||
{isEntryStarred ? t("operation.unstar") : t("operation.star")}
|
||||
</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
)}
|
||||
|
||||
|
|
@ -66,7 +70,7 @@ export const VideoContextMenu = ({ entryId, children }: VideoContextMenuProps) =
|
|||
name: "link",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>Open Link</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.open_link")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
|
||||
<ContextMenu.Item
|
||||
|
|
@ -82,7 +86,7 @@ export const VideoContextMenu = ({ entryId, children }: VideoContextMenuProps) =
|
|||
name: "document.on.document",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>Copy Link</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.copy_link")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item
|
||||
key="Share"
|
||||
|
|
@ -101,7 +105,7 @@ export const VideoContextMenu = ({ entryId, children }: VideoContextMenuProps) =
|
|||
name: "square.and.arrow.up",
|
||||
}}
|
||||
/>
|
||||
<ContextMenu.ItemTitle>Share</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.share")}</ContextMenu.ItemTitle>
|
||||
</ContextMenu.Item>
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { t } from "i18next"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Text, View } from "react-native"
|
||||
|
||||
import { CheckCircleCuteReIcon } from "@/src/icons/check_circle_cute_re"
|
||||
|
|
@ -8,11 +10,12 @@ import { unreadSyncService } from "@/src/store/unread/store"
|
|||
import { useSelectedView } from "../screen/atoms"
|
||||
|
||||
export const MarkAllAsReadDialog: DialogComponent = () => {
|
||||
const { t } = useTranslation()
|
||||
const selectedView = useSelectedView()
|
||||
const ctx = Dialog.useDialogContext()
|
||||
return (
|
||||
<View>
|
||||
<Text className="text-label">Do you want to mark all items as read?</Text>
|
||||
<Text className="text-label">{t("operation.mark_all_as_read_confirm")}</Text>
|
||||
<Dialog.DialogConfirm
|
||||
onPress={() => {
|
||||
ctx?.dismiss()
|
||||
|
|
@ -26,8 +29,7 @@ export const MarkAllAsReadDialog: DialogComponent = () => {
|
|||
)
|
||||
}
|
||||
|
||||
MarkAllAsReadDialog.title = "Mark All as Read"
|
||||
MarkAllAsReadDialog.title = t("operation.mark_all_as_read")
|
||||
MarkAllAsReadDialog.id = "mark-all-as-read"
|
||||
|
||||
MarkAllAsReadDialog.title = "Mark All as Read"
|
||||
MarkAllAsReadDialog.headerIcon = <CheckCircleCuteReIcon />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useAtom } from "jotai"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Clipboard, Share, TouchableOpacity, View } from "react-native"
|
||||
import type { SharedValue } from "react-native-reanimated"
|
||||
import Animated, { interpolate, useAnimatedStyle } from "react-native-reanimated"
|
||||
|
|
@ -56,6 +57,7 @@ const HeaderRightActionsImpl = ({
|
|||
titleOpacityShareValue,
|
||||
isHeaderTitleVisible,
|
||||
}: HeaderRightActionsProps) => {
|
||||
const { t } = useTranslation()
|
||||
const labelColor = useColor("label")
|
||||
const isStarred = useIsEntryStarred(entryId)
|
||||
const [extraActionContainerWidth, setExtraActionContainerWidth] = useState(0)
|
||||
|
|
@ -150,7 +152,7 @@ const HeaderRightActionsImpl = ({
|
|||
const actionItems = [
|
||||
subscription && {
|
||||
key: "Star",
|
||||
title: isStarred ? "Unstar" : "Star",
|
||||
title: isStarred ? t("operation.unstar") : t("operation.star"),
|
||||
icon: isStarred ? <StarCuteFiIcon /> : <StarCuteReIcon />,
|
||||
iconIOS: {
|
||||
name: isStarred ? "star.fill" : "star",
|
||||
|
|
@ -189,7 +191,7 @@ const HeaderRightActionsImpl = ({
|
|||
},
|
||||
{
|
||||
key: "Share",
|
||||
title: "Share",
|
||||
title: t("operation.share"),
|
||||
icon: <Share3CuteReIcon />,
|
||||
iconIOS: { name: "square.and.arrow.up" },
|
||||
onPress: handleShare,
|
||||
|
|
@ -257,7 +259,7 @@ const HeaderRightActionsImpl = ({
|
|||
</DropdownMenu.Group>
|
||||
)}
|
||||
<DropdownMenu.Item key="CopyLink" onSelect={handleCopyLink}>
|
||||
<DropdownMenu.ItemTitle>Copy Link</DropdownMenu.ItemTitle>
|
||||
<DropdownMenu.ItemTitle>{t("operation.copy_link")}</DropdownMenu.ItemTitle>
|
||||
<DropdownMenu.ItemIcon ios={{ name: "link" }} />
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item key="OpenInBrowser" onSelect={handleOpenInBrowser}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { env } from "@follow/shared/src/env"
|
||||
import { useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Share, View } from "react-native"
|
||||
import { useColor } from "react-native-uikit-colors"
|
||||
|
||||
|
|
@ -76,12 +77,13 @@ export function TimelineSelectorProvider({
|
|||
}
|
||||
|
||||
function FeedShareAction({ feedId }: { feedId?: string }) {
|
||||
const { t } = useTranslation()
|
||||
const label = useColor("label")
|
||||
|
||||
if (!feedId) return null
|
||||
return (
|
||||
<UIBarButton
|
||||
label="Share"
|
||||
label={t("operation.share")}
|
||||
normalIcon={<Share3CuteReIcon height={24} width={24} color={label} />}
|
||||
onPress={() => {
|
||||
const feed = getFeed(feedId)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { FeedViewType } from "@follow/constants"
|
||||
import type { FC, PropsWithChildren } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { ContextMenu } from "@/src/components/ui/context-menu"
|
||||
import { unreadSyncService } from "@/src/store/unread/store"
|
||||
|
|
@ -7,6 +8,7 @@ import { unreadSyncService } from "@/src/store/unread/store"
|
|||
export const TimelineViewSelectorContextMenu: FC<
|
||||
PropsWithChildren<{ type: string | undefined; viewId: FeedViewType | undefined }>
|
||||
> = ({ children, type, viewId }) => {
|
||||
const { t } = useTranslation()
|
||||
if (type !== "view" || viewId === undefined) return children
|
||||
|
||||
return (
|
||||
|
|
@ -19,7 +21,7 @@ export const TimelineViewSelectorContextMenu: FC<
|
|||
unreadSyncService.markViewAsRead(viewId)
|
||||
}}
|
||||
>
|
||||
<ContextMenu.ItemTitle>Mark as Read</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemTitle>{t("operation.mark_as_read")}</ContextMenu.ItemTitle>
|
||||
<ContextMenu.ItemIcon
|
||||
ios={{
|
||||
name: "checklist.checked",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { cn } from "@follow/utils"
|
|||
import * as Haptics from "expo-haptics"
|
||||
import type { PropsWithChildren } from "react"
|
||||
import { useCallback } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { TouchableOpacity, View } from "react-native"
|
||||
|
||||
import { setGeneralSetting, useGeneralSettingKey } from "@/src/atoms/settings/general"
|
||||
|
|
@ -54,12 +55,13 @@ export function HomeLeftAction() {
|
|||
}
|
||||
|
||||
export function HomeSharedRightAction(props: PropsWithChildren) {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<ActionGroup>
|
||||
{props.children}
|
||||
|
||||
<UIBarButton
|
||||
label="Mark All as Read"
|
||||
label={t("operation.mark_all_as_read")}
|
||||
normalIcon={<CheckCircleCuteReIcon height={24} width={24} color={accentColor} />}
|
||||
onPress={() => {
|
||||
Dialog.show(MarkAllAsReadDialog)
|
||||
|
|
@ -80,17 +82,27 @@ const useButtonVariant = ({ variant = "primary" }: HeaderActionButtonProps) => {
|
|||
return { size, color }
|
||||
}
|
||||
export const UnreadOnlyActionButton = ({ variant = "primary" }: HeaderActionButtonProps) => {
|
||||
const { t } = useTranslation()
|
||||
const unreadOnly = useGeneralSettingKey("unreadOnly")
|
||||
const { size, color } = useButtonVariant({ variant })
|
||||
return (
|
||||
<UIBarButton
|
||||
label={unreadOnly ? "Show All" : "Show Unread Only"}
|
||||
label={
|
||||
unreadOnly
|
||||
? t("operation.toggle_unread_only.show_all.label")
|
||||
: t("operation.toggle_unread_only.show_unread_only.label")
|
||||
}
|
||||
normalIcon={<RoundCuteReIcon height={size} width={size} color={color} />}
|
||||
selectedIcon={<RoundCuteFiIcon height={size} width={size} color={color} />}
|
||||
onPress={() => {
|
||||
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)
|
||||
setGeneralSetting("unreadOnly", !unreadOnly)
|
||||
toast.success(`Showing ${unreadOnly ? "all" : "unread"} entries`, { position: "bottom" })
|
||||
toast.success(
|
||||
unreadOnly
|
||||
? t("operation.toggle_unread_only.show_all.success")
|
||||
: t("operation.toggle_unread_only.show_unread_only.success"),
|
||||
{ position: "bottom" },
|
||||
)
|
||||
}}
|
||||
selected={unreadOnly}
|
||||
overlay={false}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "التغيير إلى عرض آخر",
|
||||
"operation.copy_link": "نسخ الرابط",
|
||||
"operation.delete_category": "حذف الفئة",
|
||||
"operation.edit": "تحرير",
|
||||
"operation.mark_all_as_read": "تحديد الكل كمقروء",
|
||||
"operation.mark_all_as_read_confirm": "تأكيد تحديد الكل كمقروء؟",
|
||||
"operation.mark_all_as_read_which": "هل تريد تحديد <which /> كمقروء؟",
|
||||
"operation.mark_as_read": "تحديد كمقروء",
|
||||
"operation.rename_category": "إعادة تسمية الفئة",
|
||||
"operation.share": "مشاركة",
|
||||
"operation.star": "تمييز بنجمة",
|
||||
"operation.unfollow": "إلغاء المتابعة",
|
||||
"profile.title": "ملف {{name}} الشخصي",
|
||||
"profile.uncategorized_feeds": "الخلاصات غير المصنفة",
|
||||
"tabs.discover": "اكتشف",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "تغيير إلى عرض آخر",
|
||||
"operation.copy_link": "نسخ الرابط",
|
||||
"operation.delete_category": "حذف الفئة",
|
||||
"operation.edit": "تحرير",
|
||||
"operation.mark_all_as_read": "تحديد الكل كمقروء",
|
||||
"operation.mark_all_as_read_confirm": "تأكيد تحديد الكل كمقروء؟",
|
||||
"operation.mark_all_as_read_which": "تحديد <which /> كمقروء؟",
|
||||
"operation.mark_as_read": "تحديد كمقروء",
|
||||
"operation.rename_category": "إعادة تسمية الفئة",
|
||||
"operation.share": "مشاركة",
|
||||
"operation.star": "إضافة إلى المفضلة",
|
||||
"operation.unfollow": "إلغاء المتابعة",
|
||||
"profile.title": "ملف {{name}} الشخصي",
|
||||
"profile.uncategorized_feeds": "الخلاصات غير المصنفة",
|
||||
"tabs.discover": "اكتشف",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "التبديل إلى طريقة عرض أخرى",
|
||||
"operation.copy_link": "نسخ الرابط",
|
||||
"operation.delete_category": "حذف الفئة",
|
||||
"operation.edit": "تحرير",
|
||||
"operation.mark_all_as_read": "وضع علامة الكل كمقروء",
|
||||
"operation.mark_all_as_read_confirm": "تأكيد وضع علامة الجميع كمقروء؟",
|
||||
"operation.mark_all_as_read_which": "وضع علامة <which /> كمقروء؟",
|
||||
"operation.mark_as_read": "وضع علامة كمقروء",
|
||||
"operation.rename_category": "إعادة تسمية الفئة",
|
||||
"operation.share": "مشاركة",
|
||||
"operation.star": "تفضيل",
|
||||
"operation.unfollow": "إلغاء المتابعة",
|
||||
"profile.title": "ملف {{name}} الشخصي",
|
||||
"profile.uncategorized_feeds": "الخلاصات غير المصنفة",
|
||||
"tabs.discover": "اكتشف",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "تغيير إلى عرض آخر",
|
||||
"operation.copy_link": "نسخ الرابط",
|
||||
"operation.delete_category": "حذف الفئة",
|
||||
"operation.edit": "تعديل",
|
||||
"operation.mark_all_as_read": "وضع علامة على الكل كمقروء",
|
||||
"operation.mark_all_as_read_confirm": "تأكيد وضع علامة على الكل كمقروء؟",
|
||||
"operation.mark_all_as_read_which": "وضع علامة على <which /> كمقروء؟",
|
||||
"operation.mark_as_read": "وضع علامة كمقروء",
|
||||
"operation.rename_category": "إعادة تسمية الفئة",
|
||||
"operation.share": "مشاركة",
|
||||
"operation.star": "إضافة إلى المفضلة",
|
||||
"operation.unfollow": "إلغاء المتابعة",
|
||||
"profile.title": "ملف {{name}} الشخصي",
|
||||
"profile.uncategorized_feeds": "الخلاصات غير المصنفة",
|
||||
"tabs.discover": "اكتشف",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "التغيير إلى عرض آخر",
|
||||
"operation.copy_link": "نسخ الرابط",
|
||||
"operation.delete_category": "حذف الفئة",
|
||||
"operation.edit": "تحرير",
|
||||
"operation.mark_all_as_read": "تمييز الكل كمقروء",
|
||||
"operation.mark_all_as_read_confirm": "هل ترغب في تأكيد تمييز الكل كمقروء؟",
|
||||
"operation.mark_all_as_read_which": "تمييز <which /> كمقروء؟",
|
||||
"operation.mark_as_read": "تمييز كمقروء",
|
||||
"operation.rename_category": "إعادة تسمية الفئة",
|
||||
"operation.share": "مشاركة",
|
||||
"operation.star": "تمييز",
|
||||
"operation.unfollow": "إلغاء المتابعة",
|
||||
"profile.title": "ملف {{name}} الشخصي",
|
||||
"profile.uncategorized_feeds": "الخلاصات غير المصنفة",
|
||||
"tabs.discover": "اكتشف",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "التغيير إلى عرض آخر",
|
||||
"operation.copy_link": "نسخ الرابط",
|
||||
"operation.delete_category": "حذف الفئة",
|
||||
"operation.edit": "تحرير",
|
||||
"operation.mark_all_as_read": "وضع علامة على الكل كمقروء",
|
||||
"operation.mark_all_as_read_confirm": "تأكيد وضع الجميع كمقروء؟",
|
||||
"operation.mark_all_as_read_which": "وضع علامة <which /> كمقروء؟",
|
||||
"operation.mark_as_read": "وضع علامة كمقروء",
|
||||
"operation.rename_category": "إعادة تسمية الفئة",
|
||||
"operation.share": "مشاركة",
|
||||
"operation.star": "إضافة إلى المفضلة",
|
||||
"operation.unfollow": "إلغاء المتابعة",
|
||||
"profile.title": "ملف {{name}} الشخصي",
|
||||
"profile.uncategorized_feeds": "الخلاصات غير المصنفة",
|
||||
"tabs.discover": "اكتشف",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "Zu anderer Ansicht wechseln",
|
||||
"operation.copy_link": "Link kopieren",
|
||||
"operation.delete_category": "Kategorie löschen",
|
||||
"operation.edit": "Bearbeiten",
|
||||
"operation.mark_all_as_read": "Alles als gelesen markieren",
|
||||
"operation.mark_all_as_read_confirm": "Möchten Sie alle als gelesen markieren?",
|
||||
"operation.mark_all_as_read_which": "<which /> als gelesen markieren?",
|
||||
"operation.mark_as_read": "Als gelesen markieren",
|
||||
"operation.rename_category": "Kategorie umbenennen",
|
||||
"operation.share": "Teilen",
|
||||
"operation.star": "Favorisieren",
|
||||
"operation.unfollow": "Entfolgen",
|
||||
"profile.title": "{{name}}s Profil",
|
||||
"profile.uncategorized_feeds": "Unkategorisierte Feeds",
|
||||
"tabs.discover": "Entdecken",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,23 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "Move to Category",
|
||||
"operation.change_to_other_view": "Switch to Another View",
|
||||
"operation.copy_link": "Copy Link",
|
||||
"operation.delete_category": "Delete Category",
|
||||
"operation.edit": "Edit",
|
||||
"operation.mark_all_as_read": "Mark all as read",
|
||||
"operation.mark_all_as_read_confirm": "Confirm mark all as read?",
|
||||
"operation.mark_all_as_read_which": "Mark <which /> as read?",
|
||||
"operation.mark_as_read": "Mark as Read",
|
||||
"operation.open_link": "Open Link",
|
||||
"operation.rename_category": "Rename Category",
|
||||
"operation.share": "Share",
|
||||
"operation.star": "Star",
|
||||
"operation.toggle_unread_only.show_all.label": "Show All",
|
||||
"operation.toggle_unread_only.show_all.success": "Showing all entries",
|
||||
"operation.toggle_unread_only.show_unread_only.label": "Show Unread Only",
|
||||
"operation.toggle_unread_only.show_unread_only.success": "Showing unread entries only",
|
||||
"operation.unfollow": "Unfollow",
|
||||
"operation.unstar": "Unstar",
|
||||
"profile.title": "{{name}}'s Profile",
|
||||
"profile.uncategorized_feeds": "Uncategorized feeds",
|
||||
"tabs.discover": "Discover",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "Cambiar a otra vista",
|
||||
"operation.copy_link": "Copiar enlace",
|
||||
"operation.delete_category": "Eliminar categoría",
|
||||
"operation.edit": "Editar",
|
||||
"operation.mark_all_as_read": "Marcar todo como leído",
|
||||
"operation.mark_all_as_read_confirm": "¿Confirmar marcar todo como leído?",
|
||||
"operation.mark_all_as_read_which": "¿Marcar <which /> como leído?",
|
||||
"operation.mark_as_read": "Marcar como leído",
|
||||
"operation.rename_category": "Renombrar categoría",
|
||||
"operation.share": "Compartir",
|
||||
"operation.star": "Agregar a favoritos",
|
||||
"operation.unfollow": "Dejar de seguir",
|
||||
"profile.title": "Perfil de {{name}}",
|
||||
"profile.uncategorized_feeds": "Feeds sin categorizar",
|
||||
"tabs.discover": "Descubrir",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "Vaihda toiseen näkymään",
|
||||
"operation.copy_link": "Kopioi linkki",
|
||||
"operation.delete_category": "Poista kategoria",
|
||||
"operation.edit": "Muokkaa",
|
||||
"operation.mark_all_as_read": "Merkitse kaikki luetuiksi",
|
||||
"operation.mark_all_as_read_confirm": "Vahvista kaikki merkinnät luetuiksi?",
|
||||
"operation.mark_all_as_read_which": "Merkitäänkö <which /> luetuksi?",
|
||||
"operation.mark_as_read": "Merkitse luetuksi",
|
||||
"operation.rename_category": "Nimeä kategoria uudelleen",
|
||||
"operation.share": "Jaa",
|
||||
"operation.star": "Tähtää",
|
||||
"operation.unfollow": "Lopeta seuraaminen",
|
||||
"profile.title": "{{name}}n profiili",
|
||||
"profile.uncategorized_feeds": "Luokittelemattomat syötteet",
|
||||
"tabs.discover": "Löydä",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "Changer pour une autre vue",
|
||||
"operation.copy_link": "Copier le lien",
|
||||
"operation.delete_category": "Supprimer la catégorie",
|
||||
"operation.edit": "Éditer",
|
||||
"operation.mark_all_as_read": "Tout marquer comme lu",
|
||||
"operation.mark_all_as_read_confirm": "Confirmez que vous voulez tout marquer comme lu ?",
|
||||
"operation.mark_all_as_read_which": "Marquer <which /> comme lu ?",
|
||||
"operation.mark_as_read": "Marquer comme lu",
|
||||
"operation.rename_category": "Renommer la catégorie",
|
||||
"operation.share": "Partager",
|
||||
"operation.star": "Mettre en favori",
|
||||
"operation.unfollow": "Se désabonner",
|
||||
"profile.title": "Profil de {{name}}",
|
||||
"profile.uncategorized_feeds": "Flux non catégorisés",
|
||||
"tabs.discover": "Découvrir",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "Cambia ad altra visualizzazione",
|
||||
"operation.copy_link": "Copia link",
|
||||
"operation.delete_category": "Elimina categoria",
|
||||
"operation.edit": "Modifica",
|
||||
"operation.mark_all_as_read": "Segna tutto come letto",
|
||||
"operation.mark_all_as_read_confirm": "Confermi di segnare tutto come letto?",
|
||||
"operation.mark_all_as_read_which": "Segna <which /> come letto?",
|
||||
"operation.mark_as_read": "Segna come letto",
|
||||
"operation.rename_category": "Rinomina categoria",
|
||||
"operation.share": "Condividi",
|
||||
"operation.star": "Aggiungi ai preferiti",
|
||||
"operation.unfollow": "Smetti di seguire",
|
||||
"profile.title": "Profilo di {{name}}",
|
||||
"profile.uncategorized_feeds": "Feed non categorizzati",
|
||||
"tabs.discover": "Scopri",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "カテゴリーに移動",
|
||||
"operation.change_to_other_view": "他のビューに切り替え",
|
||||
"operation.copy_link": "リンクをコピー",
|
||||
"operation.delete_category": "カテゴリーを削除",
|
||||
"operation.edit": "編集",
|
||||
"operation.mark_all_as_read": "すべてを既読にする",
|
||||
"operation.mark_all_as_read_confirm": "すべてを既読にしますか?",
|
||||
"operation.mark_all_as_read_which": "<which />を既読にしますか?",
|
||||
"operation.mark_as_read": "既読にする",
|
||||
"operation.rename_category": "カテゴリーをリネーム",
|
||||
"operation.share": "共有",
|
||||
"operation.star": "スター",
|
||||
"operation.unfollow": "フォロー解除",
|
||||
"profile.title": "{{name}}のプロフィール",
|
||||
"profile.uncategorized_feeds": "未分類のフィード",
|
||||
"tabs.discover": "発見",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "카테고리로 이동",
|
||||
"operation.change_to_other_view": "다른 보기로 변경",
|
||||
"operation.copy_link": "링크 복사",
|
||||
"operation.delete_category": "카테고리 삭제",
|
||||
"operation.edit": "편집",
|
||||
"operation.mark_all_as_read": "모두 읽음으로 표시",
|
||||
"operation.mark_all_as_read_confirm": "모두 읽음으로 표시하시겠습니까?",
|
||||
"operation.mark_all_as_read_which": "<which />을 (를) 모두 읽음으로 표시하시겠습니까?",
|
||||
"operation.mark_as_read": "읽음으로 표시",
|
||||
"operation.rename_category": "카테고리 이름 변경",
|
||||
"operation.share": "공유",
|
||||
"operation.star": "별표",
|
||||
"operation.unfollow": "언팔로우",
|
||||
"profile.title": "{{name}}의 프로필",
|
||||
"profile.uncategorized_feeds": "분류되지 않은 피드",
|
||||
"tabs.discover": "발견",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "他のビューに切り替え",
|
||||
"operation.copy_link": "リンクをコピー",
|
||||
"operation.delete_category": "カテゴリーを削除",
|
||||
"operation.edit": "編集",
|
||||
"operation.mark_all_as_read": "すべてを既読にする",
|
||||
"operation.mark_all_as_read_confirm": "すべてを既読にしますか?",
|
||||
"operation.mark_all_as_read_which": "<which />を既読にしますか?",
|
||||
"operation.mark_as_read": "既読にする",
|
||||
"operation.rename_category": "カテゴリーの名前を変更",
|
||||
"operation.share": "共有",
|
||||
"operation.star": "スター",
|
||||
"operation.unfollow": "フォロー解除",
|
||||
"profile.title": "Perfil de {{name}}",
|
||||
"profile.uncategorized_feeds": "Feeds não categorizados",
|
||||
"tabs.discover": "Descobrir",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "Переместить в категорию",
|
||||
"operation.change_to_other_view": "Изменить на другой вид",
|
||||
"operation.copy_link": "Копировать ссылку",
|
||||
"operation.delete_category": "Удалить категорию",
|
||||
"operation.edit": "Редактировать",
|
||||
"operation.mark_all_as_read": "Отметить все как прочитанное",
|
||||
"operation.mark_all_as_read_confirm": "Подтвердить отметку всего как прочитанное?",
|
||||
"operation.mark_all_as_read_which": "Отметить <which /> как прочитанное?",
|
||||
"operation.mark_as_read": "Отметить как прочитанное",
|
||||
"operation.rename_category": "Переименовать категорию",
|
||||
"operation.share": "Поделиться",
|
||||
"operation.star": "Добавить в избранное",
|
||||
"operation.unfollow": "Отписаться",
|
||||
"profile.title": "Профиль {{name}}",
|
||||
"profile.uncategorized_feeds": "Некатегоризированные ленты",
|
||||
"tabs.discover": "Открыть",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"operation.change_to_other_view": "Diğer görünüme geç",
|
||||
"operation.copy_link": "Bağlantıyı kopyala",
|
||||
"operation.delete_category": "Kategoriyi sil",
|
||||
"operation.edit": "Düzenle",
|
||||
"operation.mark_all_as_read": "Tümünü okundu olarak işaretle",
|
||||
"operation.mark_all_as_read_confirm": "Tümünü okundu olarak işaretlemeyi onaylıyor musunuz?",
|
||||
"operation.mark_all_as_read_which": "<which /> okundu olarak işaretlensin mi?",
|
||||
"operation.mark_as_read": "Okundu olarak işaretle",
|
||||
"operation.rename_category": "Kategoriyi yeniden adlandır",
|
||||
"operation.share": "Paylaş",
|
||||
"operation.star": "Yıldızla",
|
||||
"operation.unfollow": "Takibi bırak",
|
||||
"profile.title": "{{name}}'nin Profili",
|
||||
"profile.uncategorized_feeds": "Kategorize edilmemiş beslemeler",
|
||||
"tabs.discover": "Keşfet",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,23 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "移动至分类",
|
||||
"operation.change_to_other_view": "更改为其他视图",
|
||||
"operation.copy_link": "复制链接",
|
||||
"operation.delete_category": "删除分类",
|
||||
"operation.edit": "编辑",
|
||||
"operation.mark_all_as_read": "全部标记为已读",
|
||||
"operation.mark_all_as_read_confirm": "确认将全部标记为已读?",
|
||||
"operation.mark_all_as_read_which": "将 <which /> 标记为已读?",
|
||||
"operation.mark_as_read": "标记为已读",
|
||||
"operation.open_link": "打开链接",
|
||||
"operation.rename_category": "重命名分类",
|
||||
"operation.share": "分享",
|
||||
"operation.star": "收藏",
|
||||
"operation.toggle_unread_only.show_all.label": "显示全部",
|
||||
"operation.toggle_unread_only.show_all.success": "正在显示所有条目",
|
||||
"operation.toggle_unread_only.show_unread_only.label": "仅显示未读",
|
||||
"operation.toggle_unread_only.show_unread_only.success": "仅显示未读条目",
|
||||
"operation.unfollow": "取消订阅",
|
||||
"operation.unstar": "取消收藏",
|
||||
"profile.title": "{{name}}的个人资料",
|
||||
"profile.uncategorized_feeds": "未分类的订阅源",
|
||||
"tabs.discover": "发现",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "移至分類",
|
||||
"operation.change_to_other_view": "切換到其他視圖",
|
||||
"operation.copy_link": "複製連結",
|
||||
"operation.delete_category": "刪除分類",
|
||||
"operation.edit": "編輯",
|
||||
"operation.mark_all_as_read": "全部標記為已讀",
|
||||
"operation.mark_all_as_read_confirm": "確定將所有標記為已讀?",
|
||||
"operation.mark_all_as_read_which": "確定將 <which /> 標記為已讀?",
|
||||
"operation.mark_as_read": "標記為已讀",
|
||||
"operation.rename_category": "重新命名分類",
|
||||
"operation.share": "分享",
|
||||
"operation.star": "收藏",
|
||||
"operation.unfollow": "取消追隨",
|
||||
"profile.title": "{{name}}的個人資料",
|
||||
"profile.uncategorized_feeds": "未分類的訂閱源",
|
||||
"tabs.discover": "探索",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
{
|
||||
"operation.add_feeds_to_category": "新增 RSS 摘要到類別",
|
||||
"operation.change_to_other_view": "切換到其他視圖",
|
||||
"operation.copy_link": "複製連結",
|
||||
"operation.delete_category": "刪除類別",
|
||||
"operation.edit": "編輯",
|
||||
"operation.mark_all_as_read": "全部標記為已讀",
|
||||
"operation.mark_all_as_read_confirm": "確認將全部標記為已讀?",
|
||||
"operation.mark_all_as_read_which": "將 <which /> 標記為已讀?",
|
||||
"operation.mark_as_read": "標記為已讀",
|
||||
"operation.rename_category": "重新命名類別",
|
||||
"operation.share": "分享",
|
||||
"operation.star": "收藏",
|
||||
"operation.unfollow": "取消跟隨",
|
||||
"profile.title": "{{name}} 的個人資料",
|
||||
"profile.uncategorized_feeds": "未分類的 RSS 摘要",
|
||||
"tabs.discover": "探索",
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build:web": "turbo run Folo#build:web",
|
||||
"dedupe:locales": "eslint --fix locales/**/*.json",
|
||||
"dedupe:locales": "eslint --fix locales/**",
|
||||
"depcheck": "npx depcheck --quiet",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
|
|
|
|||
|
|
@ -1,20 +1,38 @@
|
|||
import fs from "node:fs"
|
||||
import path from "node:path"
|
||||
|
||||
const sourceDir = "./locales/common"
|
||||
const targetDir = "./locales/common"
|
||||
const sourceDir = "./locales/app"
|
||||
const targetDir = "./locales/mobile/default"
|
||||
const keysToCopy: string[] = [
|
||||
// // kept the duplicate keys in locales/app
|
||||
// "words.starred",
|
||||
// "words.inbox",
|
||||
// "words.feeds",
|
||||
// "words.lists",
|
||||
// "words.search",
|
||||
"cancel",
|
||||
"close",
|
||||
"confirm",
|
||||
"sidebar.feed_column.context_menu.mark_as_read",
|
||||
"entry_actions.star",
|
||||
"entry_actions.share",
|
||||
"mark_all_read_button.mark_all_as_read",
|
||||
"sidebar.feed_column.context_menu.add_feeds_to_category",
|
||||
"sidebar.feed_actions.edit",
|
||||
"entry_actions.copy_link",
|
||||
"sidebar.feed_actions.unfollow",
|
||||
"sidebar.feed_column.context_menu.change_to_other_view",
|
||||
"sidebar.feed_column.context_menu.rename_category",
|
||||
"sidebar.feed_column.context_menu.delete_category",
|
||||
"mark_all_read_button.confirm_mark_all",
|
||||
"mark_all_read_button.confirm_mark_all_info",
|
||||
]
|
||||
const keysToPlace = [
|
||||
"operation.mark_as_read",
|
||||
"operation.star",
|
||||
"operation.share",
|
||||
"operation.mark_all_as_read",
|
||||
"operation.add_feeds_to_category",
|
||||
"operation.edit",
|
||||
"operation.copy_link",
|
||||
"operation.unfollow",
|
||||
"operation.change_to_other_view",
|
||||
"operation.rename_category",
|
||||
"operation.delete_category",
|
||||
"operation.mark_all_as_read_which",
|
||||
"operation.mark_all_as_read_confirm",
|
||||
]
|
||||
const keysToPlace = ["words.cancel", "words.close", "words.confirm"]
|
||||
|
||||
const copyTranslations = (sourceDir: string, targetDir: string) => {
|
||||
const sourceFiles = fs.readdirSync(sourceDir)
|
||||
|
|
|
|||
Loading…
Reference in New Issue