feat: checkLanguage utils
This commit is contained in:
parent
2edebdfcdb
commit
225e470db8
|
|
@ -1,9 +1,8 @@
|
|||
import type { SupportedLanguages } from "@follow/models/types"
|
||||
import { franc } from "franc-min"
|
||||
|
||||
import type { FlatEntryModel } from "~/store/entry"
|
||||
|
||||
import { LanguageMap, translate } from "./translate"
|
||||
import { checkLanguage, translate } from "./translate"
|
||||
|
||||
function textNodesUnder(el: Node) {
|
||||
const children: Node[] = el.nodeType === Node.TEXT_NODE ? [el] : []
|
||||
|
|
@ -17,7 +16,7 @@ function textNodesUnder(el: Node) {
|
|||
return children
|
||||
}
|
||||
|
||||
const tagsToDuplicate = ["h1", "h2", "h3", "h4", "h5", "h6", "p", "li", "blockquote"]
|
||||
const tagsToDuplicate = ["h1", "h2", "h3", "h4", "h5", "h6", "p", "li", "blockquote", "article"]
|
||||
|
||||
export function immersiveTranslate({
|
||||
html,
|
||||
|
|
@ -94,9 +93,14 @@ export function immersiveTranslate({
|
|||
}) as HTMLElement[]
|
||||
|
||||
for (const tag of tags) {
|
||||
const sourceLanguage = franc(tag.textContent ?? "")
|
||||
if (sourceLanguage === LanguageMap[translation].code) {
|
||||
return
|
||||
if (tag.textContent) {
|
||||
const isLanguageMatch = checkLanguage({
|
||||
content: tag.textContent,
|
||||
language: translation,
|
||||
})
|
||||
if (isLanguageMatch) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const children = Array.from(tag.childNodes)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { parseHtml } from "@follow/components/ui/markdown/parse-html.js"
|
||||
import { views } from "@follow/constants"
|
||||
import type { SupportedLanguages } from "@follow/models/types"
|
||||
import { franc } from "franc-min"
|
||||
|
||||
import type { FlatEntryModel } from "~/store/entry"
|
||||
|
||||
|
|
@ -35,6 +36,28 @@ export const LanguageMap: Record<
|
|||
code: "cmn",
|
||||
},
|
||||
}
|
||||
|
||||
export const checkLanguage = ({
|
||||
content,
|
||||
language,
|
||||
}: {
|
||||
content: string
|
||||
language: SupportedLanguages
|
||||
}) => {
|
||||
if (!content) return true
|
||||
const pureContent = parseHtml(content)
|
||||
.toText()
|
||||
.replaceAll(/https?:\/\/\S+|www\.\S+/g, " ")
|
||||
const sourceLanguage = franc(pureContent, {
|
||||
only: [LanguageMap[language].code],
|
||||
})
|
||||
if (sourceLanguage === LanguageMap[language].code) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function translate({
|
||||
entry,
|
||||
view,
|
||||
|
|
@ -55,22 +78,14 @@ export async function translate({
|
|||
if (extraFields) {
|
||||
fields = [...fields, ...extraFields]
|
||||
}
|
||||
const { franc } = await import("franc-min")
|
||||
|
||||
fields = fields.filter((field) => {
|
||||
if (language && entry.entries[field]) {
|
||||
const content = parseHtml(entry.entries[field])
|
||||
.toText()
|
||||
.replaceAll(/https?:\/\/\S+|www\.\S+/g, " ")
|
||||
const sourceLanguage = franc(content, {
|
||||
only: [LanguageMap[language].code],
|
||||
const isLanguageMatch = checkLanguage({
|
||||
content: entry.entries[field],
|
||||
language,
|
||||
})
|
||||
|
||||
if (sourceLanguage === LanguageMap[language].code) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
return !isLanguageMatch
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { ShadowDOM } from "~/components/common/ShadowDOM"
|
|||
import { useInPeekModal } from "~/components/ui/modal/inspire/PeekModal"
|
||||
import { useRouteParamsSelector } from "~/hooks/biz/useRouteParams"
|
||||
import { useAuthQuery } from "~/hooks/common"
|
||||
import { LanguageMap } from "~/lib/translate"
|
||||
import { checkLanguage } from "~/lib/translate"
|
||||
import { WrappedElementProvider } from "~/providers/wrapped-element-provider"
|
||||
import { Queries } from "~/queries"
|
||||
import { useEntry } from "~/store/entry"
|
||||
|
|
@ -108,7 +108,9 @@ export const EntryContent: Component<EntryContentProps> = ({
|
|||
)
|
||||
const customCSS = useUISettingKey("customCSS")
|
||||
const showAITranslation = useShowAITranslation()
|
||||
const translationLanguage = useGeneralSettingSelector((s) => s.translationLanguage)
|
||||
const translationLanguage = useGeneralSettingSelector(
|
||||
(s) => s.translationLanguage,
|
||||
) as SupportedLanguages
|
||||
|
||||
if (!entry) return null
|
||||
|
||||
|
|
@ -120,13 +122,17 @@ export const EntryContent: Component<EntryContentProps> = ({
|
|||
const fullText = html.textContent ?? ""
|
||||
if (!fullText) return
|
||||
|
||||
const { franc } = await import("franc-min")
|
||||
const translation =
|
||||
entry.settings?.translation ?? (showAITranslation ? translationLanguage : undefined)
|
||||
|
||||
const sourceLanguage = franc(fullText)
|
||||
if (translation && sourceLanguage === LanguageMap[translation].code) {
|
||||
return
|
||||
if (translation) {
|
||||
const isLanguageMatch = checkLanguage({
|
||||
content: fullText,
|
||||
language: translation,
|
||||
})
|
||||
if (isLanguageMatch) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const { immersiveTranslate } = await import("~/lib/immersive-translate")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { ShadowDOM } from "~/components/common/ShadowDOM"
|
|||
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
|
||||
import { useRouteParamsSelector } from "~/hooks/biz/useRouteParams"
|
||||
import { useAuthQuery, usePreventOverscrollBounce } from "~/hooks/common"
|
||||
import { LanguageMap } from "~/lib/translate"
|
||||
import { checkLanguage } from "~/lib/translate"
|
||||
import { WrappedElementProvider } from "~/providers/wrapped-element-provider"
|
||||
import { Queries } from "~/queries"
|
||||
import { useEntry } from "~/store/entry"
|
||||
|
|
@ -102,7 +102,9 @@ export const EntryContent: Component<{
|
|||
const [scrollElement, setScrollElement] = useState<HTMLElement | null>(null)
|
||||
|
||||
const showAITranslation = useShowAITranslation()
|
||||
const translationLanguage = useGeneralSettingSelector((s) => s.translationLanguage)
|
||||
const translationLanguage = useGeneralSettingSelector(
|
||||
(s) => s.translationLanguage,
|
||||
) as SupportedLanguages
|
||||
|
||||
if (!entry) return null
|
||||
|
||||
|
|
@ -114,13 +116,17 @@ export const EntryContent: Component<{
|
|||
const fullText = html.textContent ?? ""
|
||||
if (!fullText) return
|
||||
|
||||
const { franc } = await import("franc-min")
|
||||
const translation =
|
||||
entry.settings?.translation ?? (showAITranslation ? translationLanguage : undefined)
|
||||
|
||||
const sourceLanguage = franc(fullText)
|
||||
if (translation && sourceLanguage === LanguageMap[translation].code) {
|
||||
return
|
||||
if (translation) {
|
||||
const isLanguageMatch = checkLanguage({
|
||||
content: fullText,
|
||||
language: translation,
|
||||
})
|
||||
if (isLanguageMatch) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const { immersiveTranslate } = await import("~/lib/immersive-translate")
|
||||
|
|
|
|||
Loading…
Reference in New Issue