feat: ai tranlation for entry content
This commit is contained in:
parent
2dbf026a5b
commit
fbeb00ec6e
|
|
@ -3,11 +3,10 @@ import { views } from "@renderer/lib/constants"
|
|||
import { FeedViewType } from "@renderer/lib/enum"
|
||||
import { showNativeMenu } from "@renderer/lib/native-menu"
|
||||
import { cn } from "@renderer/lib/utils"
|
||||
import type { EntryModel, SupportedLanguages } from "@renderer/models"
|
||||
import type { EntryModel } from "@renderer/models"
|
||||
import { Queries } from "@renderer/queries"
|
||||
import { feedActions, useFeedStore } from "@renderer/store"
|
||||
import { useEntry } from "@renderer/store/entry/hooks"
|
||||
import { franc } from "franc-min"
|
||||
import type { FC } from "react"
|
||||
import { memo, useCallback } from "react"
|
||||
|
||||
|
|
@ -20,26 +19,6 @@ import { SocialMediaItem } from "./social-media-item"
|
|||
import type { UniversalItemProps } from "./types"
|
||||
import { VideoItem } from "./video-item"
|
||||
|
||||
const LanguageMap: Record<
|
||||
SupportedLanguages,
|
||||
{
|
||||
code: string
|
||||
}
|
||||
> = {
|
||||
"en": {
|
||||
code: "eng",
|
||||
},
|
||||
"ja": {
|
||||
code: "jpn",
|
||||
},
|
||||
"zh-CN": {
|
||||
code: "cmn",
|
||||
},
|
||||
"zh-TW": {
|
||||
code: "cmn",
|
||||
},
|
||||
}
|
||||
|
||||
interface EntryItemProps {
|
||||
entryId: string
|
||||
view?: number
|
||||
|
|
@ -50,33 +29,14 @@ function EntryItemImpl({ entry, view }: { entry: EntryModel, view?: number }) {
|
|||
entry,
|
||||
})
|
||||
|
||||
let fields =
|
||||
entry.settings?.translation && view !== undefined ?
|
||||
views[view!].translation.split(",") :
|
||||
[]
|
||||
|
||||
fields = fields.filter((field) => {
|
||||
if (entry.settings?.translation && entry.entries[field]) {
|
||||
const sourceLanguage = franc(entry.entries[field])
|
||||
|
||||
if (sourceLanguage === LanguageMap[entry.settings?.translation].code) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
const translation = useBizQuery(
|
||||
Queries.ai.translation({
|
||||
id: entry.entries.id,
|
||||
entry,
|
||||
view,
|
||||
language: entry.settings?.translation,
|
||||
fields: fields?.join(",") || "title",
|
||||
}),
|
||||
{
|
||||
enabled: !!entry.settings?.translation && !!fields?.length,
|
||||
enabled: !!entry.settings?.translation,
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { useEntry, useFeedStore } from "@renderer/store"
|
|||
import { m } from "framer-motion"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
import { EntryTranslation } from "../entry-column/translation"
|
||||
import { LoadingCircle } from "../ui/loading"
|
||||
import { EntryShare } from "./share"
|
||||
|
||||
|
|
@ -51,6 +52,17 @@ function EntryContentRender({ entryId }: { entryId: string }) {
|
|||
}
|
||||
}, [entry?.entries.content])
|
||||
|
||||
const translation = useBizQuery(
|
||||
Queries.ai.translation({
|
||||
entry: entry!,
|
||||
language: entry?.settings?.translation,
|
||||
extraFields: ["title"],
|
||||
}),
|
||||
{
|
||||
enabled: !!entry?.settings?.translation,
|
||||
},
|
||||
)
|
||||
|
||||
if (!entry) return null
|
||||
|
||||
return (
|
||||
|
|
@ -72,7 +84,7 @@ function EntryContentRender({ entryId }: { entryId: string }) {
|
|||
rel="noreferrer"
|
||||
>
|
||||
<div className="select-text break-words text-3xl font-bold">
|
||||
{entry.entries.title}
|
||||
<EntryTranslation source={entry.entries.title} target={translation.data?.title} />
|
||||
</div>
|
||||
<div className="mt-2 text-[13px] font-medium text-zinc-500">
|
||||
{entry.feeds?.title}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,78 @@
|
|||
import { apiClient } from "@renderer/lib/api-fetch"
|
||||
import { views } from "@renderer/lib/constants"
|
||||
import { defineQuery } from "@renderer/lib/defineQuery"
|
||||
import type { SupportedLanguages } from "@renderer/models"
|
||||
import type { EntryModel, SupportedLanguages } from "@renderer/models"
|
||||
import { franc } from "franc-min"
|
||||
|
||||
const LanguageMap: Record<
|
||||
SupportedLanguages,
|
||||
{
|
||||
code: string
|
||||
}
|
||||
> = {
|
||||
"en": {
|
||||
code: "eng",
|
||||
},
|
||||
"ja": {
|
||||
code: "jpn",
|
||||
},
|
||||
"zh-CN": {
|
||||
code: "cmn",
|
||||
},
|
||||
"zh-TW": {
|
||||
code: "cmn",
|
||||
},
|
||||
}
|
||||
|
||||
export const ai = {
|
||||
translation: ({
|
||||
id,
|
||||
entry,
|
||||
view,
|
||||
language,
|
||||
fields,
|
||||
extraFields,
|
||||
}: {
|
||||
id: string
|
||||
entry: EntryModel
|
||||
view?: number
|
||||
language?: SupportedLanguages
|
||||
fields: string
|
||||
extraFields?: string[]
|
||||
}) =>
|
||||
defineQuery(["translation", id, language], async () => {
|
||||
defineQuery(["translation", entry.entries.id, language], async () => {
|
||||
if (!language) {
|
||||
return null
|
||||
}
|
||||
const res = await apiClient.ai.translation.$get({
|
||||
query: {
|
||||
id,
|
||||
language: language as SupportedLanguages,
|
||||
fields,
|
||||
},
|
||||
let fields =
|
||||
entry.settings?.translation && view !== undefined ?
|
||||
views[view!].translation.split(",") :
|
||||
[]
|
||||
if (extraFields) {
|
||||
fields = [...fields, ...extraFields]
|
||||
}
|
||||
|
||||
fields = fields.filter((field) => {
|
||||
if (entry.settings?.translation && entry.entries[field]) {
|
||||
const sourceLanguage = franc(entry.entries[field])
|
||||
|
||||
if (sourceLanguage === LanguageMap[entry.settings?.translation].code) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
return res.data
|
||||
|
||||
if (fields.length > 0) {
|
||||
const res = await apiClient.ai.translation.$get({
|
||||
query: {
|
||||
id: entry.entries.id,
|
||||
language: language as SupportedLanguages,
|
||||
fields: fields?.join(",") || "title",
|
||||
},
|
||||
})
|
||||
return res.data
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue