refactor: translation language -> action language (#3154)
* refactor: action language -> action language * type * mobile * type * fix * prefer local settings, drop backward compatibility * update * update * update * chore: auto-fix linting and formatting issues * update * update * update * follow ui * update * add description * fix build * update * update * update
This commit is contained in:
parent
6f5f9e8dd0
commit
8a5f92d0e7
|
|
@ -187,7 +187,9 @@
|
|||
"general.startup_screen.timeline": "Timeline",
|
||||
"general.startup_screen.title": "Startup Screen",
|
||||
"general.timeline": "Timeline",
|
||||
"general.translation_language": "Translation Language",
|
||||
"general.action_language.label": "Action Language",
|
||||
"general.action_language.default": "Default (UI Language)",
|
||||
"general.action_language.description": "The language used for translation and summary",
|
||||
"general.unread": "Unread",
|
||||
"general.voices": "Voices",
|
||||
"integration.eagle.enable.description": "Display 'Save media to Eagle' button when available.",
|
||||
|
|
|
|||
|
|
@ -167,7 +167,6 @@
|
|||
"general.startup_screen.timeline": "タイムライン",
|
||||
"general.startup_screen.title": "スタートアップスクリーン",
|
||||
"general.timeline": "タイムライン",
|
||||
"general.translation_language": "翻訳する言語",
|
||||
"general.unread": "未読",
|
||||
"general.voices": "音声",
|
||||
"integration.eagle.enable.description": "利用可能な場合、'Eagle にメディアを保存' ボタンを表示します。",
|
||||
|
|
|
|||
|
|
@ -172,7 +172,6 @@
|
|||
"general.startup_screen.timeline": "타임라인",
|
||||
"general.startup_screen.title": "시작 화면",
|
||||
"general.timeline": "타임라인",
|
||||
"general.translation_language": "번역 언어",
|
||||
"general.unread": "읽지 않음",
|
||||
"general.voices": "음성",
|
||||
"integration.eagle.enable.description": "가능할 때 '미디어를 Eagle 에 저장' 버튼 표시.",
|
||||
|
|
|
|||
|
|
@ -187,7 +187,6 @@
|
|||
"general.startup_screen.timeline": "时间线",
|
||||
"general.startup_screen.title": "起始界面",
|
||||
"general.timeline": "时间线",
|
||||
"general.translation_language": "翻译语言",
|
||||
"general.unread": "未读",
|
||||
"general.voices": "声音",
|
||||
"integration.eagle.enable.description": "显示「保存到 Eagle」按钮(如果可用)。",
|
||||
|
|
|
|||
|
|
@ -187,7 +187,6 @@
|
|||
"general.startup_screen.timeline": "時間軸",
|
||||
"general.startup_screen.title": "啟動畫面",
|
||||
"general.timeline": "時間軸",
|
||||
"general.translation_language": "翻譯語言",
|
||||
"general.unread": "未讀",
|
||||
"general.voices": "語音",
|
||||
"integration.eagle.enable.description": "顯示「將媒體儲存到 Eagle」按鈕(如果可用)",
|
||||
|
|
|
|||
|
|
@ -172,7 +172,6 @@
|
|||
"general.startup_screen.timeline": "時間軸",
|
||||
"general.startup_screen.title": "開始畫面",
|
||||
"general.timeline": "時間軸",
|
||||
"general.translation_language": "翻譯語言",
|
||||
"general.unread": "未讀",
|
||||
"general.voices": "聲音",
|
||||
"integration.eagle.enable.description": "顯示「將媒體儲存到 Eagle」按鈕(如果可用)。",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
import { createSettingAtom } from "@follow/atoms/helper/setting.js"
|
||||
import type { SupportedLanguages } from "@follow/models"
|
||||
import type { GeneralSettings } from "@follow/shared/interface/settings"
|
||||
|
||||
import { jotaiStore } from "~/lib/jotai"
|
||||
|
||||
export const DEFAULT_ACTION_LANGUAGE = "default"
|
||||
|
||||
const createDefaultSettings = (): GeneralSettings => ({
|
||||
// App
|
||||
appLaunchOnStartup: false,
|
||||
language: "en",
|
||||
translationLanguage: "zh-CN",
|
||||
actionLanguage: DEFAULT_ACTION_LANGUAGE,
|
||||
|
||||
// mobile app
|
||||
startupScreen: "timeline",
|
||||
|
|
@ -47,6 +50,14 @@ export const {
|
|||
settingAtom: __generalSettingAtom,
|
||||
} = createSettingAtom("general", createDefaultSettings)
|
||||
|
||||
export function useActionLanguage() {
|
||||
const actionLanguage = useGeneralSettingSelector((s) => s.actionLanguage)
|
||||
const language = useGeneralSettingSelector((s) => s.language)
|
||||
return (
|
||||
actionLanguage === DEFAULT_ACTION_LANGUAGE ? language : actionLanguage
|
||||
) as SupportedLanguages
|
||||
}
|
||||
|
||||
export const subscribeShouldUseIndexedDB = (callback: (value: boolean) => void) =>
|
||||
jotaiStore.sub(__generalSettingAtom, () => callback(getGeneralSettings().dataPersist))
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,9 @@ export function immersiveTranslate({
|
|||
return
|
||||
}
|
||||
|
||||
const translation = entry.settings?.translation ?? targetLanguage
|
||||
|
||||
const immersiveTranslateMark = html.querySelectorAll("[data-immersive-translate-mark=true]")
|
||||
if (immersiveTranslateMark.length > 0) {
|
||||
if (translation) {
|
||||
if (targetLanguage) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +47,7 @@ export function immersiveTranslate({
|
|||
}
|
||||
}
|
||||
|
||||
if (!translation) {
|
||||
if (!targetLanguage) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +59,7 @@ export function immersiveTranslate({
|
|||
|
||||
translate({
|
||||
entry,
|
||||
language: translation,
|
||||
language: targetLanguage,
|
||||
part: textNode.textContent,
|
||||
extraFields: ["content"],
|
||||
}).then((transformed) => {
|
||||
|
|
@ -96,7 +94,7 @@ export function immersiveTranslate({
|
|||
if (tag.textContent) {
|
||||
const isLanguageMatch = checkLanguage({
|
||||
content: tag.textContent,
|
||||
language: translation,
|
||||
language: targetLanguage,
|
||||
})
|
||||
if (isLanguageMatch) {
|
||||
continue
|
||||
|
|
@ -151,7 +149,7 @@ export function immersiveTranslate({
|
|||
|
||||
translate({
|
||||
entry,
|
||||
language: translation,
|
||||
language: targetLanguage,
|
||||
part: textContent,
|
||||
extraFields: ["content"],
|
||||
}).then((transformed) => {
|
||||
|
|
|
|||
|
|
@ -1,42 +1,13 @@
|
|||
import { parseHtml } from "@follow/components/ui/markdown/parse-html.js"
|
||||
import { views } from "@follow/constants"
|
||||
import type { SupportedLanguages } from "@follow/models/types"
|
||||
import { LANGUAGE_MAP } from "@follow/shared"
|
||||
import { franc } from "franc-min"
|
||||
|
||||
import type { FlatEntryModel } from "~/store/entry"
|
||||
|
||||
import { apiClient } from "./api-fetch"
|
||||
|
||||
export const LanguageMap: Record<
|
||||
SupportedLanguages,
|
||||
{
|
||||
label: string
|
||||
value: string
|
||||
code: string
|
||||
}
|
||||
> = {
|
||||
en: {
|
||||
value: "en",
|
||||
label: "English",
|
||||
code: "eng",
|
||||
},
|
||||
ja: {
|
||||
value: "ja",
|
||||
label: "Japanese",
|
||||
code: "jpn",
|
||||
},
|
||||
"zh-CN": {
|
||||
value: "zh-CN",
|
||||
label: "Simplified Chinese",
|
||||
code: "cmn",
|
||||
},
|
||||
"zh-TW": {
|
||||
value: "zh-TW",
|
||||
label: "Traditional Chinese (Taiwan)",
|
||||
code: "cmn",
|
||||
},
|
||||
}
|
||||
|
||||
export const checkLanguage = ({
|
||||
content,
|
||||
language,
|
||||
|
|
@ -48,10 +19,12 @@ export const checkLanguage = ({
|
|||
const pureContent = parseHtml(content)
|
||||
.toText()
|
||||
.replaceAll(/https?:\/\/\S+|www\.\S+/g, " ")
|
||||
const { code } = LANGUAGE_MAP[language]
|
||||
if (!code) return false
|
||||
const sourceLanguage = franc(pureContent, {
|
||||
only: [LanguageMap[language].code],
|
||||
only: [code],
|
||||
})
|
||||
if (sourceLanguage === LanguageMap[language].code) {
|
||||
if (sourceLanguage === code) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { ActionButton, Button } from "@follow/components/ui/button/index.js"
|
||||
import { Divider } from "@follow/components/ui/divider/index.js"
|
||||
import { Input } from "@follow/components/ui/input/index.js"
|
||||
import { ResponsiveSelect } from "@follow/components/ui/select/responsive.js"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
|
|
@ -10,7 +9,7 @@ import {
|
|||
TableHeader,
|
||||
TableRow,
|
||||
} from "@follow/components/ui/table/index.jsx"
|
||||
import type { ActionModel, SupportedLanguages } from "@follow/models/types"
|
||||
import type { ActionModel } from "@follow/models/types"
|
||||
import { Fragment, useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
|
|
@ -31,28 +30,6 @@ type Action = {
|
|||
onRemove: (data: ActionModel) => void
|
||||
}
|
||||
|
||||
const TransitionOptions: {
|
||||
label: string
|
||||
value: SupportedLanguages
|
||||
}[] = [
|
||||
{
|
||||
label: "English",
|
||||
value: "en",
|
||||
},
|
||||
{
|
||||
label: "日本語",
|
||||
value: "ja",
|
||||
},
|
||||
{
|
||||
label: "简体中文",
|
||||
value: "zh-CN",
|
||||
},
|
||||
{
|
||||
label: "繁體中文",
|
||||
value: "zh-TW",
|
||||
},
|
||||
]
|
||||
|
||||
const AddTableRow = ({ onClick, disabled }: { onClick?: () => void; disabled?: boolean }) => {
|
||||
const { t } = useTranslation("settings")
|
||||
return (
|
||||
|
|
@ -108,26 +85,11 @@ export const TargetActionList = ({ index }: { index: number }) => {
|
|||
title: t("actions.action_card.translate_into"),
|
||||
enabled: !!translation,
|
||||
onInit: (data) => {
|
||||
data.result.translation = "zh-CN"
|
||||
data.result.translation = true
|
||||
},
|
||||
onRemove: (data) => {
|
||||
delete data.result.translation
|
||||
},
|
||||
config: () => (
|
||||
<ResponsiveSelect
|
||||
disabled={disabled}
|
||||
size="sm"
|
||||
value={translation}
|
||||
onValueChange={(value) => {
|
||||
onChange((data) => {
|
||||
data.result.translation = value
|
||||
})
|
||||
}}
|
||||
items={TransitionOptions}
|
||||
triggerClassName="w-fit max-w-44 text-sm"
|
||||
/>
|
||||
),
|
||||
configInline: true,
|
||||
},
|
||||
{
|
||||
title: t("actions.action_card.enable_readability"),
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import {
|
|||
} from "react"
|
||||
import { useEventCallback } from "usehooks-ts"
|
||||
|
||||
import { useGeneralSettingKey } from "~/atoms/settings/general"
|
||||
import { useActionLanguage, useGeneralSettingKey } from "~/atoms/settings/general"
|
||||
import { MediaContainerWidthProvider } from "~/components/ui/media"
|
||||
import { useAuthQuery } from "~/hooks/common/useBizQuery"
|
||||
import { Queries } from "~/queries"
|
||||
|
|
@ -248,11 +248,12 @@ const MasonryRender: React.ComponentType<
|
|||
> = ({ data, index }) => {
|
||||
const firstScreenReady = useContext(FirstScreenReadyContext)
|
||||
const entry = useEntry(data.entryId)
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useAuthQuery(
|
||||
Queries.ai.translation({
|
||||
entry: entry!,
|
||||
view: entry?.view,
|
||||
language: entry?.settings?.translation,
|
||||
language: actionLanguage,
|
||||
}),
|
||||
{
|
||||
enabled: !!entry?.settings?.translation,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { cn } from "@follow/utils/utils"
|
|||
import type { FC } from "react"
|
||||
import { memo } from "react"
|
||||
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { useAuthQuery } from "~/hooks/common"
|
||||
import { Queries } from "~/queries"
|
||||
import type { FlatEntryModel } from "~/store/entry"
|
||||
|
|
@ -20,11 +21,12 @@ interface EntryItemProps {
|
|||
view?: number
|
||||
}
|
||||
function EntryItemImpl({ entry, view }: { entry: FlatEntryModel; view?: number }) {
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useAuthQuery(
|
||||
Queries.ai.translation({
|
||||
entry,
|
||||
view,
|
||||
language: entry.settings?.translation,
|
||||
language: actionLanguage,
|
||||
}),
|
||||
{
|
||||
enabled: !!entry.settings?.translation,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import type { SupportedLanguages } from "@follow/models/types"
|
||||
import { cn } from "@follow/utils/utils"
|
||||
import dayjs from "dayjs"
|
||||
import { useMemo } from "react"
|
||||
|
||||
import { useShowAITranslation } from "~/atoms/ai-translation"
|
||||
import { useGeneralSettingSelector } from "~/atoms/settings/general"
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { useUISettingKey } from "~/atoms/settings/ui"
|
||||
import { useWhoami } from "~/atoms/user"
|
||||
import { RelativeTime } from "~/components/ui/datetime"
|
||||
|
|
@ -49,12 +48,12 @@ export const EntryTitle = ({ entryId, compact }: EntryLinkProps) => {
|
|||
}, [entry?.entries.authorUrl, entry?.entries.url, feed?.siteUrl, feed?.type, inbox])
|
||||
|
||||
const showAITranslation = useShowAITranslation() || !!entry?.settings?.translation
|
||||
const translationLanguage = useGeneralSettingSelector((s) => s.translationLanguage)
|
||||
const actionLanguage = useActionLanguage()
|
||||
|
||||
const translation = useAuthQuery(
|
||||
Queries.ai.translation({
|
||||
entry: entry!,
|
||||
language: entry?.settings?.translation || (translationLanguage as SupportedLanguages),
|
||||
language: actionLanguage,
|
||||
extraFields: ["title"],
|
||||
}),
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { MemoedDangerousHTMLStyle } from "@follow/components/common/MemoedDangerousHTMLStyle.js"
|
||||
import { ScrollArea } from "@follow/components/ui/scroll-area/index.js"
|
||||
import { useTitle } from "@follow/hooks"
|
||||
import type { FeedModel, InboxModel, SupportedLanguages } from "@follow/models/types"
|
||||
import type { FeedModel, InboxModel } from "@follow/models/types"
|
||||
import { IN_ELECTRON } from "@follow/shared/constants"
|
||||
import { stopPropagation } from "@follow/utils/dom"
|
||||
import { cn } from "@follow/utils/utils"
|
||||
|
|
@ -11,7 +11,7 @@ import { useEffect, useMemo, useRef } from "react"
|
|||
|
||||
import { useShowAITranslation } from "~/atoms/ai-translation"
|
||||
import { useEntryIsInReadability } from "~/atoms/readability"
|
||||
import { useGeneralSettingSelector } from "~/atoms/settings/general"
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { useUISettingKey } from "~/atoms/settings/ui"
|
||||
import { ShadowDOM } from "~/components/common/ShadowDOM"
|
||||
import { useInPeekModal } from "~/components/ui/modal/inspire/PeekModal"
|
||||
|
|
@ -117,9 +117,7 @@ export const EntryContent: Component<EntryContentProps> = ({
|
|||
)
|
||||
const customCSS = useUISettingKey("customCSS")
|
||||
const showAITranslation = useShowAITranslation()
|
||||
const translationLanguage = useGeneralSettingSelector(
|
||||
(s) => s.translationLanguage,
|
||||
) as SupportedLanguages
|
||||
const actionLanguage = useActionLanguage()
|
||||
|
||||
if (!entry) return null
|
||||
|
||||
|
|
@ -131,8 +129,7 @@ export const EntryContent: Component<EntryContentProps> = ({
|
|||
const fullText = html.textContent ?? ""
|
||||
if (!fullText) return
|
||||
|
||||
const translation =
|
||||
entry.settings?.translation ?? (showAITranslation ? translationLanguage : undefined)
|
||||
const translation = showAITranslation ? actionLanguage : undefined
|
||||
|
||||
if (translation) {
|
||||
const isLanguageMatch = checkLanguage({
|
||||
|
|
@ -148,7 +145,7 @@ export const EntryContent: Component<EntryContentProps> = ({
|
|||
immersiveTranslate({
|
||||
html,
|
||||
entry,
|
||||
targetLanguage: translation as SupportedLanguages,
|
||||
targetLanguage: translation,
|
||||
cache: {
|
||||
get: (key: string) => getTranslationCache()[key],
|
||||
set: (key: string, value: string) =>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { MemoedDangerousHTMLStyle } from "@follow/components/common/MemoedDangerousHTMLStyle.js"
|
||||
import { ScrollElementContext } from "@follow/components/ui/scroll-area/ctx.js"
|
||||
import { useTitle } from "@follow/hooks"
|
||||
import type { FeedModel, InboxModel, SupportedLanguages } from "@follow/models/types"
|
||||
import type { FeedModel, InboxModel } from "@follow/models/types"
|
||||
import { nextFrame, stopPropagation } from "@follow/utils/dom"
|
||||
import { cn } from "@follow/utils/utils"
|
||||
import { ErrorBoundary } from "@sentry/react"
|
||||
|
|
@ -9,7 +9,7 @@ import { useEffect, useMemo, useState } from "react"
|
|||
|
||||
import { useShowAITranslation } from "~/atoms/ai-translation"
|
||||
import { useAudioPlayerAtomSelector } from "~/atoms/player"
|
||||
import { useGeneralSettingSelector } from "~/atoms/settings/general"
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { useUISettingKey } from "~/atoms/settings/ui"
|
||||
import { ShadowDOM } from "~/components/common/ShadowDOM"
|
||||
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
|
||||
|
|
@ -104,9 +104,7 @@ export const EntryContent: Component<{
|
|||
|
||||
const customCSS = useUISettingKey("customCSS")
|
||||
const showAITranslation = useShowAITranslation()
|
||||
const translationLanguage = useGeneralSettingSelector(
|
||||
(s) => s.translationLanguage,
|
||||
) as SupportedLanguages
|
||||
const actionLanguage = useActionLanguage()
|
||||
|
||||
const contentLineHeight = useUISettingKey("contentLineHeight")
|
||||
const contentFontSize = useUISettingKey("contentFontSize")
|
||||
|
|
@ -134,8 +132,7 @@ export const EntryContent: Component<{
|
|||
const fullText = html.textContent ?? ""
|
||||
if (!fullText) return
|
||||
|
||||
const translation =
|
||||
entry.settings?.translation ?? (showAITranslation ? translationLanguage : undefined)
|
||||
const translation = showAITranslation ? actionLanguage : undefined
|
||||
|
||||
if (translation) {
|
||||
const isLanguageMatch = checkLanguage({
|
||||
|
|
@ -151,7 +148,7 @@ export const EntryContent: Component<{
|
|||
immersiveTranslate({
|
||||
html,
|
||||
entry,
|
||||
targetLanguage: translation as SupportedLanguages,
|
||||
targetLanguage: translation,
|
||||
cache: {
|
||||
get: (key: string) => getTranslationCache()[key],
|
||||
set: (key: string, value: string) =>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
useEntryInReadabilityStatus,
|
||||
useEntryReadabilityContent,
|
||||
} from "~/atoms/readability"
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { enableShowSourceContent } from "~/atoms/source-content"
|
||||
import { CopyButton } from "~/components/ui/button/CopyButton"
|
||||
import { Toc } from "~/components/ui/markdown/components/Toc"
|
||||
|
|
@ -319,10 +320,11 @@ export function AISummary({ entryId }: { entryId: string }) {
|
|||
const { t } = useTranslation()
|
||||
const entry = useEntry(entryId)
|
||||
const showAISummary = useShowAISummary() || !!entry?.settings?.summary
|
||||
const actionLanguage = useActionLanguage()
|
||||
const summary = useAuthQuery(
|
||||
Queries.ai.summary({
|
||||
entryId,
|
||||
language: entry?.settings?.translation,
|
||||
language: actionLanguage,
|
||||
}),
|
||||
{
|
||||
enabled: showAISummary,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useMobile } from "@follow/components/hooks/useMobile.js"
|
||||
import { ResponsiveSelect } from "@follow/components/ui/select/responsive.js"
|
||||
import { useTypeScriptHappyCallback } from "@follow/hooks"
|
||||
import { LANGUAGE_MAP } from "@follow/shared"
|
||||
import { IN_ELECTRON } from "@follow/shared/constants"
|
||||
import { cn } from "@follow/utils/utils"
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
|
|
@ -13,6 +14,7 @@ import { currentSupportedLanguages } from "~/@types/constants"
|
|||
import { defaultResources } from "~/@types/default-resource"
|
||||
import { langLoadingLockMapAtom } from "~/atoms/lang"
|
||||
import {
|
||||
DEFAULT_ACTION_LANGUAGE,
|
||||
setGeneralSetting,
|
||||
useGeneralSettingKey,
|
||||
useGeneralSettingSelector,
|
||||
|
|
@ -22,7 +24,6 @@ import { useProxyValue, useSetProxy } from "~/hooks/biz/useProxySetting"
|
|||
import { useMinimizeToTrayValue, useSetMinimizeToTray } from "~/hooks/biz/useTraySetting"
|
||||
import { fallbackLanguage } from "~/i18n"
|
||||
import { tipcClient } from "~/lib/client"
|
||||
import { LanguageMap } from "~/lib/translate"
|
||||
import { setTranslationCache } from "~/modules/entry-content/atoms"
|
||||
|
||||
import { SettingDescription, SettingInput, SettingSwitch } from "../control"
|
||||
|
|
@ -68,7 +69,7 @@ export const SettingGeneral = () => {
|
|||
IN_ELECTRON && MinimizeToTraySetting,
|
||||
isMobile && StartupScreenSelector,
|
||||
LanguageSelector,
|
||||
TranslateLanguageSelector,
|
||||
ActionLanguageSelector,
|
||||
|
||||
{
|
||||
type: "title",
|
||||
|
|
@ -243,23 +244,31 @@ export const LanguageSelector = ({
|
|||
)
|
||||
}
|
||||
|
||||
const TranslateLanguageSelector = () => {
|
||||
const ActionLanguageSelector = () => {
|
||||
const { t } = useTranslation("settings")
|
||||
const translationLanguage = useGeneralSettingKey("translationLanguage")
|
||||
const actionLanguage = useGeneralSettingKey("actionLanguage")
|
||||
|
||||
return (
|
||||
<div className="mb-3 mt-4 flex items-center justify-between">
|
||||
<span className="shrink-0 text-sm font-medium">{t("general.translation_language")}</span>
|
||||
<div>
|
||||
<span className="shrink-0 text-sm font-medium">{t("general.action_language.label")}</span>
|
||||
<SettingDescription className="w-auto">
|
||||
{t("general.action_language.description")}
|
||||
</SettingDescription>
|
||||
</div>
|
||||
<ResponsiveSelect
|
||||
size="sm"
|
||||
triggerClassName="w-48"
|
||||
defaultValue={translationLanguage}
|
||||
value={translationLanguage}
|
||||
defaultValue={actionLanguage}
|
||||
value={actionLanguage}
|
||||
onValueChange={(value) => {
|
||||
setGeneralSetting("translationLanguage", value)
|
||||
setGeneralSetting("actionLanguage", value)
|
||||
setTranslationCache({})
|
||||
}}
|
||||
items={Object.values(LanguageMap)}
|
||||
items={[
|
||||
{ label: t("general.action_language.default"), value: DEFAULT_ACTION_LANGUAGE },
|
||||
...Object.values(LANGUAGE_MAP),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const createDefaultSettings = (): GeneralSettings => ({
|
|||
// App
|
||||
|
||||
language: "en",
|
||||
translationLanguage: "zh-CN",
|
||||
actionLanguage: "zh-CN",
|
||||
|
||||
// Data control
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export interface GeneralSettings {
|
||||
language: string
|
||||
translationLanguage: string
|
||||
actionLanguage: string
|
||||
|
||||
sendAnonymousData: boolean
|
||||
unreadOnly: boolean
|
||||
|
|
|
|||
|
|
@ -2,32 +2,3 @@ import type { languageSchema } from "@follow/shared/src/hono"
|
|||
import type { z } from "zod"
|
||||
|
||||
export type SupportedLanguages = z.infer<typeof languageSchema>
|
||||
export const LanguageMap: Record<
|
||||
SupportedLanguages,
|
||||
{
|
||||
label: string
|
||||
value: string
|
||||
code: string
|
||||
}
|
||||
> = {
|
||||
en: {
|
||||
value: "en",
|
||||
label: "English",
|
||||
code: "eng",
|
||||
},
|
||||
ja: {
|
||||
value: "ja",
|
||||
label: "Japanese",
|
||||
code: "jpn",
|
||||
},
|
||||
"zh-CN": {
|
||||
value: "zh-CN",
|
||||
label: "Simplified Chinese",
|
||||
code: "cmn",
|
||||
},
|
||||
"zh-TW": {
|
||||
value: "zh-TW",
|
||||
label: "Traditional Chinese (Taiwan)",
|
||||
code: "cmn",
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
import { Select } from "@/src/components/ui/form/Select"
|
||||
import { GroupedInsetListCell } from "@/src/components/ui/grouped/GroupedList"
|
||||
import { actionActions } from "@/src/store/action/store"
|
||||
import type { ActionRule } from "@/src/store/action/types"
|
||||
|
||||
import { translationOptions } from "./constant"
|
||||
|
||||
export const ActionFormTranslation: React.FC<{ rule: ActionRule }> = ({ rule }) => {
|
||||
const currentTranslation = translationOptions.find(
|
||||
(translation) => translation.value === rule.result?.translation,
|
||||
)
|
||||
return (
|
||||
<GroupedInsetListCell
|
||||
label="Translate into"
|
||||
leftClassName="flex-none"
|
||||
rightClassName="flex-1 flex-row items-center gap-4 justify-end"
|
||||
>
|
||||
<Select
|
||||
options={translationOptions}
|
||||
value={currentTranslation?.value}
|
||||
onValueChange={(value) => {
|
||||
actionActions.patchRule(rule.index, { result: { translation: value } })
|
||||
}}
|
||||
wrapperClassName="min-w-40"
|
||||
/>
|
||||
</GroupedInsetListCell>
|
||||
)
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import type { ActionId, ActionRule } from "@/src/store/action/types"
|
|||
|
||||
import { EditRewriteRulesScreen } from "../routes/EditRewriteRules"
|
||||
import { EditWebhooksScreen } from "../routes/EditWebhooks"
|
||||
import { ActionFormTranslation } from "./components"
|
||||
|
||||
export const filterFieldOptions = [
|
||||
{
|
||||
|
|
@ -104,10 +103,6 @@ export const availableActionList: Array<{
|
|||
{
|
||||
value: "translation",
|
||||
label: "Translate into",
|
||||
onEnable: (index) => {
|
||||
actionActions.patchRule(index, { result: { translation: "zh-CN" } })
|
||||
},
|
||||
component: ActionFormTranslation,
|
||||
},
|
||||
{
|
||||
value: "readability",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { LANGUAGE_MAP } from "@follow/shared"
|
||||
import { useLocales } from "expo-localization"
|
||||
import { Text, View } from "react-native"
|
||||
|
||||
|
|
@ -14,12 +15,11 @@ import {
|
|||
GroupedInsetListSectionHeader,
|
||||
} from "@/src/components/ui/grouped/GroupedList"
|
||||
import { Switch } from "@/src/components/ui/switch/Switch"
|
||||
import { LanguageMap } from "@/src/lib/language"
|
||||
import type { NavigationControllerView } from "@/src/lib/navigation/types"
|
||||
|
||||
export const GeneralScreen: NavigationControllerView = () => {
|
||||
const locales = useLocales()
|
||||
const translationLanguage = useGeneralSettingKey("translationLanguage")
|
||||
const actionLanguage = useGeneralSettingKey("actionLanguage")
|
||||
const autoGroup = useGeneralSettingKey("autoGroup")
|
||||
const showUnreadOnLaunch = useGeneralSettingKey("unreadOnly")
|
||||
// const groupByDate = useGeneralSettingKey("groupByDate")
|
||||
|
|
@ -42,15 +42,15 @@ export const GeneralScreen: NavigationControllerView = () => {
|
|||
</GroupedInsetListBaseCell>
|
||||
|
||||
<GroupedInsetListBaseCell>
|
||||
<Text className="text-label">Translation Language</Text>
|
||||
<Text className="text-label">Action Language</Text>
|
||||
|
||||
<View className="w-[150px]">
|
||||
<Select
|
||||
value={translationLanguage}
|
||||
value={actionLanguage}
|
||||
onValueChange={(value) => {
|
||||
setGeneralSetting("translationLanguage", value)
|
||||
setGeneralSetting("actionLanguage", value)
|
||||
}}
|
||||
options={Object.values(LanguageMap)}
|
||||
options={Object.values(LANGUAGE_MAP)}
|
||||
/>
|
||||
</View>
|
||||
</GroupedInsetListBaseCell>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { getGeneralSettings } from "@/src/atoms/settings/general"
|
||||
import type { SummarySchema } from "@/src/database/schemas/types"
|
||||
import { apiClient } from "@/src/lib/api-fetch"
|
||||
import { summaryService } from "@/src/services/summary"
|
||||
|
|
@ -103,14 +104,14 @@ class SummarySyncService {
|
|||
state.generatingStatus[entryId] = SummaryGeneratingStatus.Pending
|
||||
})
|
||||
|
||||
const language = entry.settings?.translation
|
||||
const { actionLanguage } = getGeneralSettings()
|
||||
|
||||
// Use Our AI to generate summary
|
||||
const summary = await apiClient.ai.summary
|
||||
.$get({
|
||||
query: {
|
||||
id: entryId,
|
||||
|
||||
language,
|
||||
language: actionLanguage as any,
|
||||
},
|
||||
})
|
||||
.then((summary) => {
|
||||
|
|
@ -121,7 +122,7 @@ class SummarySyncService {
|
|||
}
|
||||
|
||||
state.data[entryId] = {
|
||||
lang: language,
|
||||
lang: actionLanguage,
|
||||
summary: summary.data,
|
||||
lastAccessed: Date.now(),
|
||||
}
|
||||
|
|
@ -142,7 +143,7 @@ class SummarySyncService {
|
|||
{
|
||||
entryId,
|
||||
summary,
|
||||
language: language ?? null,
|
||||
language: actionLanguage ?? null,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export type ActionModel = {
|
|||
}[][]
|
||||
result: {
|
||||
disabled?: boolean
|
||||
translation?: string
|
||||
translation?: boolean | string
|
||||
summary?: boolean
|
||||
readability?: boolean
|
||||
silence?: boolean
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export * from "./src/bridge"
|
||||
export * from "./src/env"
|
||||
export { type AppType } from "./src/hono"
|
||||
export * from "./src/language"
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ declare const achievementsOpenAPISchema: zod.ZodObject<{
|
|||
tx: string | null;
|
||||
}>;
|
||||
|
||||
declare const languageSchema: z.ZodEnum<["en", "ja", "zh-CN", "zh-TW"]>;
|
||||
declare const languageSchema: z.ZodEnum<["ar-DZ", "ar-IQ", "ar-KW", "ar-MA", "ar-SA", "ar-TN", "de", "en", "es", "fi", "fr", "it", "ja", "ko", "pt", "ru", "tr", "zh-CN", "zh-HK", "zh-TW"]>;
|
||||
declare const ruleFieldSchema: z.ZodEnum<["all", "title", "content", "author", "url", "order"]>;
|
||||
declare const ruleOperatorSchema: z.ZodEnum<["contains", "not_contains", "eq", "not_eq", "gt", "lt", "regex"]>;
|
||||
declare const conditionItemSchema: z.ZodObject<{
|
||||
|
|
@ -407,7 +407,7 @@ declare const actions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|||
condition: ConditionItem[] | ConditionItem[][];
|
||||
result: {
|
||||
disabled?: boolean;
|
||||
translation?: z.infer<typeof languageSchema>;
|
||||
translation?: z.infer<typeof languageSchema> | boolean;
|
||||
summary?: boolean;
|
||||
readability?: boolean;
|
||||
sourceContent?: boolean;
|
||||
|
|
@ -442,7 +442,7 @@ declare const actions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|||
condition: ConditionItem[] | ConditionItem[][];
|
||||
result: {
|
||||
disabled?: boolean;
|
||||
translation?: z.infer<typeof languageSchema>;
|
||||
translation?: z.infer<typeof languageSchema> | boolean;
|
||||
summary?: boolean;
|
||||
readability?: boolean;
|
||||
sourceContent?: boolean;
|
||||
|
|
@ -494,7 +494,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{
|
|||
}>, "many">, "many">]>;
|
||||
result: z.ZodObject<{
|
||||
disabled: z.ZodOptional<z.ZodBoolean>;
|
||||
translation: z.ZodOptional<z.ZodEnum<["en", "ja", "zh-CN", "zh-TW"]>>;
|
||||
translation: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["ar-DZ", "ar-IQ", "ar-KW", "ar-MA", "ar-SA", "ar-TN", "de", "en", "es", "fi", "fr", "it", "ja", "ko", "pt", "ru", "tr", "zh-CN", "zh-HK", "zh-TW"]>, z.ZodBoolean]>>;
|
||||
summary: z.ZodOptional<z.ZodBoolean>;
|
||||
readability: z.ZodOptional<z.ZodBoolean>;
|
||||
sourceContent: z.ZodOptional<z.ZodBoolean>;
|
||||
|
|
@ -527,7 +527,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{
|
|||
webhooks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -546,7 +546,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{
|
|||
webhooks?: string[] | undefined;
|
||||
}, {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -577,7 +577,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -608,7 +608,7 @@ declare const actionsItemOpenAPISchema: z.ZodObject<{
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -708,7 +708,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
}>, "many">, "many">]>;
|
||||
result: z.ZodObject<{
|
||||
disabled: z.ZodOptional<z.ZodBoolean>;
|
||||
translation: z.ZodOptional<z.ZodEnum<["en", "ja", "zh-CN", "zh-TW"]>>;
|
||||
translation: z.ZodOptional<z.ZodUnion<[z.ZodEnum<["ar-DZ", "ar-IQ", "ar-KW", "ar-MA", "ar-SA", "ar-TN", "de", "en", "es", "fi", "fr", "it", "ja", "ko", "pt", "ru", "tr", "zh-CN", "zh-HK", "zh-TW"]>, z.ZodBoolean]>>;
|
||||
summary: z.ZodOptional<z.ZodBoolean>;
|
||||
readability: z.ZodOptional<z.ZodBoolean>;
|
||||
sourceContent: z.ZodOptional<z.ZodBoolean>;
|
||||
|
|
@ -741,7 +741,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
webhooks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -760,7 +760,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
webhooks?: string[] | undefined;
|
||||
}, {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -791,7 +791,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -822,7 +822,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -856,7 +856,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -890,7 +890,7 @@ declare const actionsOpenAPISchema: z.ZodObject<z.objectUtil.extendShape<Omit<{
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -7233,7 +7233,7 @@ declare const auth: {
|
|||
signInSocial: {
|
||||
<C extends [{
|
||||
body: {
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk";
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick";
|
||||
scopes?: string[] | undefined;
|
||||
idToken?: {
|
||||
token: string;
|
||||
|
|
@ -7303,7 +7303,7 @@ declare const auth: {
|
|||
callbackURL: zod.ZodOptional<zod.ZodString>;
|
||||
newUserCallbackURL: zod.ZodOptional<zod.ZodString>;
|
||||
errorCallbackURL: zod.ZodOptional<zod.ZodString>;
|
||||
provider: zod.ZodEnum<["github", ...("apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk")[]]>;
|
||||
provider: zod.ZodEnum<["github", ...("apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick")[]]>;
|
||||
disableRedirect: zod.ZodOptional<zod.ZodBoolean>;
|
||||
idToken: zod.ZodOptional<zod.ZodObject<{
|
||||
token: zod.ZodString;
|
||||
|
|
@ -7327,7 +7327,7 @@ declare const auth: {
|
|||
scopes: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
|
||||
requestSignUp: zod.ZodOptional<zod.ZodBoolean>;
|
||||
}, "strip", zod.ZodTypeAny, {
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk";
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick";
|
||||
scopes?: string[] | undefined;
|
||||
idToken?: {
|
||||
token: string;
|
||||
|
|
@ -7342,7 +7342,7 @@ declare const auth: {
|
|||
newUserCallbackURL?: string | undefined;
|
||||
disableRedirect?: boolean | undefined;
|
||||
}, {
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk";
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick";
|
||||
scopes?: string[] | undefined;
|
||||
idToken?: {
|
||||
token: string;
|
||||
|
|
@ -9244,7 +9244,7 @@ declare const auth: {
|
|||
linkSocialAccount: {
|
||||
<C extends [{
|
||||
body: {
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk";
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick";
|
||||
callbackURL?: string | undefined;
|
||||
};
|
||||
headers: HeadersInit;
|
||||
|
|
@ -9275,12 +9275,12 @@ declare const auth: {
|
|||
requireHeaders: true;
|
||||
body: zod.ZodObject<{
|
||||
callbackURL: zod.ZodOptional<zod.ZodString>;
|
||||
provider: zod.ZodEnum<["github", ...("apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk")[]]>;
|
||||
provider: zod.ZodEnum<["github", ...("apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick")[]]>;
|
||||
}, "strip", zod.ZodTypeAny, {
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk";
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick";
|
||||
callbackURL?: string | undefined;
|
||||
}, {
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk";
|
||||
provider: "apple" | "discord" | "facebook" | "github" | "google" | "microsoft" | "spotify" | "twitch" | "twitter" | "dropbox" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "vk" | "kick";
|
||||
callbackURL?: string | undefined;
|
||||
}>;
|
||||
use: ((inputContext: {
|
||||
|
|
@ -9431,6 +9431,21 @@ declare const auth: {
|
|||
provider: {
|
||||
type: string;
|
||||
};
|
||||
createdAt: {
|
||||
type: string;
|
||||
};
|
||||
updatedAt: {
|
||||
type: string;
|
||||
};
|
||||
accountId: {
|
||||
type: string;
|
||||
};
|
||||
scopes: {
|
||||
type: string;
|
||||
items: {
|
||||
type: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -9504,6 +9519,7 @@ declare const auth: {
|
|||
<C extends [{
|
||||
body: {
|
||||
providerId: string;
|
||||
accountId: string;
|
||||
};
|
||||
method?: "POST" | undefined;
|
||||
query?: Record<string, any> | undefined;
|
||||
|
|
@ -9530,10 +9546,13 @@ declare const auth: {
|
|||
method: "POST";
|
||||
body: zod.ZodObject<{
|
||||
providerId: zod.ZodString;
|
||||
accountId: zod.ZodString;
|
||||
}, "strip", zod.ZodTypeAny, {
|
||||
providerId: string;
|
||||
accountId: string;
|
||||
}, {
|
||||
providerId: string;
|
||||
accountId: string;
|
||||
}>;
|
||||
use: ((inputContext: {
|
||||
body?: any;
|
||||
|
|
@ -12918,7 +12937,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -12961,7 +12980,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
}[][];
|
||||
result: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -12995,7 +13014,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
input: {
|
||||
query: {
|
||||
id: string;
|
||||
language: "en" | "ja" | "zh-CN" | "zh-TW";
|
||||
language: "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW";
|
||||
fields: string;
|
||||
part?: string | undefined;
|
||||
};
|
||||
|
|
@ -13018,7 +13037,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
input: {
|
||||
query: {
|
||||
id: string;
|
||||
language?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
language?: "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
};
|
||||
};
|
||||
output: {
|
||||
|
|
@ -13424,7 +13443,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
} | undefined;
|
||||
settings?: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
@ -13691,7 +13710,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
} | undefined;
|
||||
settings?: {
|
||||
disabled?: boolean | undefined;
|
||||
translation?: "en" | "ja" | "zh-CN" | "zh-TW" | undefined;
|
||||
translation?: boolean | "ar-DZ" | "ar-IQ" | "ar-KW" | "ar-MA" | "ar-SA" | "ar-TN" | "de" | "en" | "es" | "fi" | "fr" | "it" | "ja" | "ko" | "pt" | "ru" | "tr" | "zh-CN" | "zh-HK" | "zh-TW" | undefined;
|
||||
summary?: boolean | undefined;
|
||||
readability?: boolean | undefined;
|
||||
sourceContent?: boolean | undefined;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export * from "./constants"
|
||||
export * from "./env"
|
||||
export type { AppType } from "./hono"
|
||||
export * from "./language"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export interface GeneralSettings {
|
||||
appLaunchOnStartup: boolean
|
||||
language: string
|
||||
translationLanguage: string
|
||||
actionLanguage: string
|
||||
startupScreen: "subscription" | "timeline"
|
||||
dataPersist: boolean
|
||||
sendAnonymousData: boolean
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
import type { z } from "zod"
|
||||
|
||||
import type { languageSchema } from "./hono"
|
||||
|
||||
export const LANGUAGE_MAP: Record<
|
||||
z.infer<typeof languageSchema>,
|
||||
{
|
||||
label: string
|
||||
value: string
|
||||
code?: string
|
||||
}
|
||||
> =
|
||||
/// keep-sorted
|
||||
{
|
||||
"ar-DZ": {
|
||||
label: "Arabic (Algeria)",
|
||||
value: "ar-DZ",
|
||||
},
|
||||
"ar-IQ": {
|
||||
label: "Arabic (Iraq)",
|
||||
value: "ar-IQ",
|
||||
},
|
||||
"ar-KW": {
|
||||
label: "Arabic (Kuwait)",
|
||||
value: "ar-KW",
|
||||
},
|
||||
"ar-MA": {
|
||||
label: "Arabic (Morocco)",
|
||||
value: "ar-MA",
|
||||
},
|
||||
"ar-SA": {
|
||||
label: "Arabic (Saudi Arabia)",
|
||||
value: "ar-SA",
|
||||
},
|
||||
"ar-TN": {
|
||||
label: "Arabic (Tunisia)",
|
||||
value: "ar-TN",
|
||||
},
|
||||
"zh-CN": {
|
||||
label: "Simplified Chinese",
|
||||
value: "zh-CN",
|
||||
code: "cmn",
|
||||
},
|
||||
"zh-HK": {
|
||||
label: "Traditional Chinese (Hong Kong)",
|
||||
value: "zh-HK",
|
||||
},
|
||||
"zh-TW": {
|
||||
label: "Traditional Chinese (Taiwan)",
|
||||
value: "zh-TW",
|
||||
},
|
||||
de: {
|
||||
label: "German",
|
||||
value: "de",
|
||||
code: "deu",
|
||||
},
|
||||
en: {
|
||||
label: "English",
|
||||
value: "en",
|
||||
code: "eng",
|
||||
},
|
||||
es: {
|
||||
label: "Spanish",
|
||||
value: "es",
|
||||
code: "spa",
|
||||
},
|
||||
fi: {
|
||||
label: "Finnish",
|
||||
value: "fi",
|
||||
code: "fin",
|
||||
},
|
||||
fr: {
|
||||
label: "French",
|
||||
value: "fr",
|
||||
code: "fra",
|
||||
},
|
||||
it: {
|
||||
label: "Italian",
|
||||
value: "it",
|
||||
code: "ita",
|
||||
},
|
||||
ja: {
|
||||
label: "Japanese",
|
||||
value: "ja",
|
||||
code: "jpn",
|
||||
},
|
||||
ko: {
|
||||
label: "Korean",
|
||||
value: "ko",
|
||||
code: "kor",
|
||||
},
|
||||
pt: {
|
||||
label: "Portuguese",
|
||||
value: "pt",
|
||||
code: "por",
|
||||
},
|
||||
ru: {
|
||||
label: "Russian",
|
||||
value: "ru",
|
||||
code: "rus",
|
||||
},
|
||||
tr: {
|
||||
label: "Turkish",
|
||||
value: "tr",
|
||||
code: "tur",
|
||||
},
|
||||
}
|
||||
Loading…
Reference in New Issue