sanity-plugin-google-translate
4.0.94.0.10
dist/index.js.map~
dist/index.js.mapModified+1−1
Index: package/dist/index.js.map
===================================================================
--- package/dist/index.js.map
+++ package/dist/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["extractLanguageFromCode","code","length","toLowerCase","languageCode","split","InputProps","ObjectMember","getLanguageFromMember","member","kind","key","split","pop","elementProps","id","htmlDecode","input","doc","DOMParser","parseFromString","documentElement","textContent","Box","Button","Text","Flex","Stack","Tooltip","useToast","useCallback","useState","MemberField","MemberFieldSet","MemberFieldError","set","unset","FieldMember","InputProps","ObjectInputProps","extractLanguageFromCode","getLanguageFromMember","htmlDecode","FieldNameLangPair","GoogleTranslateSchemaOptions","TranslationConfig","collectLanguageFields","members","allLanguageFields","cur","kind","language","name","push","fieldName","fieldLang","memberCur","fieldSet","GoogleTranslateInput","props","$","_c","renderDefault","onChange","value","t0","schemaType","options","apiKey","isTranslating","setIsTranslating","toast","t1","config","content","title","status","baseLanguage","filter","code","url","URL","searchParams","target","source","length","description","toLocaleUpperCase","translations","map","item","fetch","toString","then","_temp","res_0","res","error","message","data","forEach","t2","translatedText","decoded","catch","_temp2","Promise","all","handleTranslation","member","baseMember","find","_temp3","baseFieldValue","field","baseContent","isBaseLanguage","toUpperCase","renderInput","t3","renderField","renderItem","renderPreview","t4","member_0","key","item_0","err","console","json","definePlugin","GoogleTranslateInput","GoogleTranslateSchemaOptions","googleTranslate","name","form","components","input","props","options","schemaType","translate","jsonType","Error","renderDefault"],"sources":["../src/helpers/extractLanguageFromCode.ts","../src/helpers/getLanguageFromMember.ts","../src/helpers/htmlDecode.ts","../src/GoogleTranslateInput.tsx","../src/googleTranslate.tsx"],"sourcesContent":["export function extractLanguageFromCode(code = ``): string {\n if (code.length <= 2) {\n return code.toLowerCase()\n }\n\n const [languageCode] = code.split(/[-_]/)\n return (languageCode ?? code).toLowerCase()\n}\n","import {type InputProps, type ObjectMember} from 'sanity'\n\nexport function getLanguageFromMember(member: InputProps | ObjectMember): string {\n // Member is undefined\n if (!member) {\n return ``\n }\n\n // Member is an object field member\n if ('kind' in member && member.kind === 'field') {\n return member.key.split(`-`).pop() ?? ``\n } else if ('kind' in member) {\n return ``\n }\n\n // Member is an inputProps\n return member?.elementProps?.id.split(`.`).pop() ?? ``\n}\n","export function htmlDecode(input: string): string {\n const doc = new DOMParser().parseFromString(input, 'text/html')\n return doc.documentElement.textContent ?? ``\n}\n","import {Box, Button, Text, Flex, Stack, Tooltip, useToast} from '@sanity/ui'\nimport {useCallback, useState} from 'react'\nimport {MemberField, MemberFieldSet, MemberFieldError, set, unset} from 'sanity'\nimport type {FieldMember, InputProps, ObjectInputProps} from 'sanity'\n\nimport {extractLanguageFromCode} from './helpers/extractLanguageFromCode'\nimport {getLanguageFromMember} from './helpers/getLanguageFromMember'\nimport {htmlDecode} from './helpers/htmlDecode'\nimport type {FieldNameLangPair, GoogleTranslateSchemaOptions, TranslationConfig} from './types'\n\nfunction collectLanguageFields(members: ObjectInputProps['members']): FieldNameLangPair[] {\n const allLanguageFields: FieldNameLangPair[] = []\n\n for (const cur of members) {\n if (cur.kind === 'field') {\n const language = getLanguageFromMember(cur)\n if (language && cur.name) {\n allLanguageFields.push({\n fieldName: cur.name,\n fieldLang: language,\n })\n }\n } else if (cur.kind === 'fieldSet') {\n for (const memberCur of cur.fieldSet.members) {\n if (memberCur.kind === 'field') {\n allLanguageFields.push({\n fieldName: memberCur.name,\n fieldLang: getLanguageFromMember(memberCur),\n })\n }\n }\n }\n }\n\n return allLanguageFields\n}\n\nexport function GoogleTranslateInput(props: ObjectInputProps) {\n const {renderDefault, members, onChange, value} = props\n // oxlint-disable-next-line no-unsafe-type-assertion - plugin-specific object options\n const {apiKey} = (props.schemaType.options ?? {}) as GoogleTranslateSchemaOptions\n\n const [isTranslating, setIsTranslating] = useState(false)\n const toast = useToast()\n\n const handleTranslation = useCallback(\n (config: TranslationConfig) => {\n if (!config?.content) {\n return toast.push({\n title: `No content to translate`,\n status: `warning`,\n })\n }\n\n // Get all unique language field names and codes\n // Maybe this should be recursive, but the recommendation is only to nest 1 level deep\n // TODO: Remove hidden/filtered-out fields as this currently will write to all fields\n let allLanguageFields = collectLanguageFields(members)\n\n // If this isn't a \"translate all\" operation, just target the passed-in language\n if (config.language !== config.baseLanguage) {\n allLanguageFields = allLanguageFields.filter((code) => code.fieldName === config.language)\n }\n\n setIsTranslating(true)\n\n const url = new URL(`https://translation.googleapis.com/language/translate/v2`)\n url.searchParams.set(`key`, apiKey ?? ``)\n url.searchParams.set(`q`, config.content)\n\n // Language code might be a country/language pair like en_US\n const target = extractLanguageFromCode(config.language)\n const source = extractLanguageFromCode(config.baseLanguage)\n url.searchParams.set(`source`, source)\n\n if (allLanguageFields.length === 1 && target === source) {\n return toast.push({\n title: `Bad language pair`,\n status: `warning`,\n description: `Cannot translate from \"${source.toLocaleUpperCase()}\" to \"${target.toLocaleUpperCase()}\"`,\n })\n }\n\n const translations = allLanguageFields.map(async (item) => {\n url.searchParams.set(`target`, item.fieldLang)\n\n if (item.fieldLang === source) {\n return null\n }\n\n return fetch(url.toString())\n .then((res) => res.json())\n .then((res) => {\n if (res.error) {\n toast.push({\n title: `Error`,\n status: `error`,\n description: res.error.message,\n })\n return undefined\n }\n\n toast.push({\n title: `Translation Complete`,\n status: `success`,\n description: `Translated from \"${source.toLocaleUpperCase()}\" to \"${item.fieldLang.toLocaleUpperCase()}\"`,\n })\n\n const {data} = res\n\n if (data?.translations?.length) {\n data.translations.forEach(({translatedText}: {translatedText: string}) => {\n // Convert html entities returned in translation to a string\n const decoded = htmlDecode(translatedText)\n\n // Write translation into the correct language field\n onChange(decoded ? set(decoded, [item.fieldName]) : unset([item.fieldName]))\n })\n }\n\n return undefined\n })\n .catch((err) => {\n console.error(err)\n })\n })\n\n return Promise.all(translations).then(() => setIsTranslating(false))\n },\n [apiKey, members, onChange, toast],\n )\n\n const renderInput = useCallback(\n (member: InputProps) => {\n if (!value) {\n return renderDefault(member)\n }\n\n const language = getLanguageFromMember(member)\n const baseMember = members.find((item): item is FieldMember => item.kind === 'field')\n const baseLanguage = baseMember ? getLanguageFromMember(baseMember) : ``\n const baseFieldValue = baseMember?.field.value\n const baseContent = typeof baseFieldValue === 'string' ? baseFieldValue : ``\n const isBaseLanguage = language === baseLanguage\n\n if (!language) {\n return renderDefault(member)\n }\n\n return (\n <Flex gap={1}>\n <Box flex={1}>{renderDefault(member)}</Box>\n <Tooltip\n content={\n <Box padding={2}>\n {isBaseLanguage ? (\n <Text size={1}>\n Translate all fields from the \"{baseLanguage.toLocaleUpperCase()}\" content\n </Text>\n ) : (\n <Text size={1}>\n Translate the \"{baseLanguage.toLocaleUpperCase()}\" field content to \"\n {language.toLocaleUpperCase()}\"\n </Text>\n )}\n </Box>\n }\n fallbackPlacements={['right', 'left']}\n placement=\"top\"\n portal\n >\n <Button\n mode=\"ghost\"\n disabled={isTranslating || (isBaseLanguage && !member?.value)}\n value={language}\n text={isBaseLanguage ? `Translate All` : `Translate ${language.toUpperCase()}`}\n onClick={() =>\n handleTranslation({\n language,\n baseLanguage,\n content: baseContent,\n })\n }\n />\n </Tooltip>\n </Flex>\n )\n },\n [handleTranslation, isTranslating, members, renderDefault, value],\n )\n\n return (\n <Stack gap={4}>\n {props.members.map((member) => {\n switch (member.kind) {\n case 'field':\n return (\n <MemberField\n key={member.key}\n member={member}\n // @ts-expect-error - MemberField renderInput typings do not match custom callback\n renderInput={renderInput}\n renderPreview={props.renderPreview}\n renderField={props.renderField}\n renderItem={props.renderItem}\n />\n )\n case 'fieldSet':\n return (\n <MemberFieldSet\n key={member.key}\n member={member}\n // @ts-expect-error - MemberFieldSet renderInput typings do not match custom callback\n renderInput={renderInput}\n renderPreview={props.renderPreview}\n renderField={props.renderField}\n renderItem={props.renderItem}\n />\n )\n case 'error':\n return <MemberFieldError key={member.key} member={member} />\n default:\n return null\n }\n })}\n </Stack>\n )\n}\n","import {definePlugin} from 'sanity'\n\nimport {GoogleTranslateInput} from './GoogleTranslateInput'\nimport type {GoogleTranslateSchemaOptions} from './types'\n\nexport const googleTranslate = definePlugin(() => {\n return {\n name: 'sanity-plugin-google-translate',\n form: {\n components: {\n input: (props) => {\n // oxlint-disable-next-line no-unsafe-type-assertion - plugin-specific object options\n const options = props.schemaType.options as GoogleTranslateSchemaOptions | undefined\n\n if (options?.translate) {\n if (props.schemaType.jsonType !== 'object') {\n throw new Error(\n `The translate option is only supported on object type fields, but got ${props.schemaType.jsonType}`,\n )\n }\n\n // @ts-expect-error - form input props are wider than ObjectInputProps\n return <GoogleTranslateInput {...props} />\n }\n\n return props.renderDefault(props)\n },\n },\n },\n }\n})\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["InputProps","ObjectMember","getLanguageFromMember","member","kind","key","split","pop","elementProps","id","htmlDecode","input","doc","DOMParser","parseFromString","documentElement","textContent","Box","Button","Text","Flex","Stack","useToast","Tooltip","useCallback","useState","MemberField","MemberFieldSet","MemberFieldError","set","unset","FieldMember","InputProps","ObjectInputProps","extractLanguageFromCode","getLanguageFromMember","htmlDecode","FieldNameLangPair","GoogleTranslateSchemaOptions","TranslationConfig","collectLanguageFields","members","allLanguageFields","cur","kind","language","name","push","fieldName","fieldLang","memberCur","fieldSet","GoogleTranslateInput","props","$","_c","renderDefault","onChange","value","t0","schemaType","options","apiKey","isTranslating","setIsTranslating","toast","t1","config","content","title","status","baseLanguage","filter","code","url","URL","searchParams","target","source","length","description","toLocaleUpperCase","translations","map","item","fetch","toString","then","_temp","res_0","res","error","message","data","forEach","t2","translatedText","decoded","catch","_temp2","Promise","all","handleTranslation","member","baseMember","find","_temp3","baseFieldValue","field","baseContent","isBaseLanguage","toUpperCase","renderInput","t3","renderField","renderItem","renderPreview","t4","member_0","key","item_0","err","console","json","definePlugin","GoogleTranslateInput","GoogleTranslateSchemaOptions","googleTranslate","name","form","components","input","props","options","schemaType","translate","jsonType","Error","renderDefault"],"sources":["../src/helpers/extractLanguageFromCode.ts","../src/helpers/getLanguageFromMember.ts","../src/helpers/htmlDecode.ts","../src/GoogleTranslateInput.tsx","../src/googleTranslate.tsx"],"sourcesContent":["export function extractLanguageFromCode(code = ``): string {\n if (code.length <= 2) {\n return code.toLowerCase()\n }\n\n const [languageCode] = code.split(/[-_]/)\n return (languageCode ?? code).toLowerCase()\n}\n","import {type InputProps, type ObjectMember} from 'sanity'\n\nexport function getLanguageFromMember(member: InputProps | ObjectMember): string {\n // Member is undefined\n if (!member) {\n return ``\n }\n\n // Member is an object field member\n if ('kind' in member && member.kind === 'field') {\n return member.key.split(`-`).pop() ?? ``\n } else if ('kind' in member) {\n return ``\n }\n\n // Member is an inputProps\n return member?.elementProps?.id.split(`.`).pop() ?? ``\n}\n","export function htmlDecode(input: string): string {\n const doc = new DOMParser().parseFromString(input, 'text/html')\n return doc.documentElement.textContent ?? ``\n}\n","import {Box, Button, Text, Flex, Stack} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {useCallback, useState} from 'react'\nimport {MemberField, MemberFieldSet, MemberFieldError, set, unset} from 'sanity'\nimport type {FieldMember, InputProps, ObjectInputProps} from 'sanity'\n\nimport {extractLanguageFromCode} from './helpers/extractLanguageFromCode'\nimport {getLanguageFromMember} from './helpers/getLanguageFromMember'\nimport {htmlDecode} from './helpers/htmlDecode'\nimport type {FieldNameLangPair, GoogleTranslateSchemaOptions, TranslationConfig} from './types'\n\nfunction collectLanguageFields(members: ObjectInputProps['members']): FieldNameLangPair[] {\n const allLanguageFields: FieldNameLangPair[] = []\n\n for (const cur of members) {\n if (cur.kind === 'field') {\n const language = getLanguageFromMember(cur)\n if (language && cur.name) {\n allLanguageFields.push({\n fieldName: cur.name,\n fieldLang: language,\n })\n }\n } else if (cur.kind === 'fieldSet') {\n for (const memberCur of cur.fieldSet.members) {\n if (memberCur.kind === 'field') {\n allLanguageFields.push({\n fieldName: memberCur.name,\n fieldLang: getLanguageFromMember(memberCur),\n })\n }\n }\n }\n }\n\n return allLanguageFields\n}\n\nexport function GoogleTranslateInput(props: ObjectInputProps) {\n const {renderDefault, members, onChange, value} = props\n // oxlint-disable-next-line no-unsafe-type-assertion - plugin-specific object options\n const {apiKey} = (props.schemaType.options ?? {}) as GoogleTranslateSchemaOptions\n\n const [isTranslating, setIsTranslating] = useState(false)\n const toast = useToast()\n\n const handleTranslation = useCallback(\n (config: TranslationConfig) => {\n if (!config?.content) {\n return toast.push({\n title: `No content to translate`,\n status: `warning`,\n })\n }\n\n // Get all unique language field names and codes\n // Maybe this should be recursive, but the recommendation is only to nest 1 level deep\n // TODO: Remove hidden/filtered-out fields as this currently will write to all fields\n let allLanguageFields = collectLanguageFields(members)\n\n // If this isn't a \"translate all\" operation, just target the passed-in language\n if (config.language !== config.baseLanguage) {\n allLanguageFields = allLanguageFields.filter((code) => code.fieldName === config.language)\n }\n\n setIsTranslating(true)\n\n const url = new URL(`https://translation.googleapis.com/language/translate/v2`)\n url.searchParams.set(`key`, apiKey ?? ``)\n url.searchParams.set(`q`, config.content)\n\n // Language code might be a country/language pair like en_US\n const target = extractLanguageFromCode(config.language)\n const source = extractLanguageFromCode(config.baseLanguage)\n url.searchParams.set(`source`, source)\n\n if (allLanguageFields.length === 1 && target === source) {\n return toast.push({\n title: `Bad language pair`,\n status: `warning`,\n description: `Cannot translate from \"${source.toLocaleUpperCase()}\" to \"${target.toLocaleUpperCase()}\"`,\n })\n }\n\n const translations = allLanguageFields.map(async (item) => {\n url.searchParams.set(`target`, item.fieldLang)\n\n if (item.fieldLang === source) {\n return null\n }\n\n return fetch(url.toString())\n .then((res) => res.json())\n .then((res) => {\n if (res.error) {\n toast.push({\n title: `Error`,\n status: `error`,\n description: res.error.message,\n })\n return undefined\n }\n\n toast.push({\n title: `Translation Complete`,\n status: `success`,\n description: `Translated from \"${source.toLocaleUpperCase()}\" to \"${item.fieldLang.toLocaleUpperCase()}\"`,\n })\n\n const {data} = res\n\n if (data?.translations?.length) {\n data.translations.forEach(({translatedText}: {translatedText: string}) => {\n // Convert html entities returned in translation to a string\n const decoded = htmlDecode(translatedText)\n\n // Write translation into the correct language field\n onChange(decoded ? set(decoded, [item.fieldName]) : unset([item.fieldName]))\n })\n }\n\n return undefined\n })\n .catch((err) => {\n console.error(err)\n })\n })\n\n return Promise.all(translations).then(() => setIsTranslating(false))\n },\n [apiKey, members, onChange, toast],\n )\n\n const renderInput = useCallback(\n (member: InputProps) => {\n if (!value) {\n return renderDefault(member)\n }\n\n const language = getLanguageFromMember(member)\n const baseMember = members.find((item): item is FieldMember => item.kind === 'field')\n const baseLanguage = baseMember ? getLanguageFromMember(baseMember) : ``\n const baseFieldValue = baseMember?.field.value\n const baseContent = typeof baseFieldValue === 'string' ? baseFieldValue : ``\n const isBaseLanguage = language === baseLanguage\n\n if (!language) {\n return renderDefault(member)\n }\n\n return (\n <Flex gap={1}>\n <Box flex={1}>{renderDefault(member)}</Box>\n <Tooltip\n content={\n <Box padding={2}>\n {isBaseLanguage ? (\n <Text size={1}>\n Translate all fields from the \"{baseLanguage.toLocaleUpperCase()}\" content\n </Text>\n ) : (\n <Text size={1}>\n Translate the \"{baseLanguage.toLocaleUpperCase()}\" field content to \"\n {language.toLocaleUpperCase()}\"\n </Text>\n )}\n </Box>\n }\n fallbackPlacements={['right', 'left']}\n placement=\"top\"\n portal\n >\n <Button\n mode=\"ghost\"\n disabled={isTranslating || (isBaseLanguage && !member?.value)}\n value={language}\n text={isBaseLanguage ? `Translate All` : `Translate ${language.toUpperCase()}`}\n onClick={() =>\n handleTranslation({\n language,\n baseLanguage,\n content: baseContent,\n })\n }\n />\n </Tooltip>\n </Flex>\n )\n },\n [handleTranslation, isTranslating, members, renderDefault, value],\n )\n\n return (\n <Stack gap={4}>\n {props.members.map((member) => {\n switch (member.kind) {\n case 'field':\n return (\n <MemberField\n key={member.key}\n member={member}\n // @ts-expect-error - MemberField renderInput typings do not match custom callback\n renderInput={renderInput}\n renderPreview={props.renderPreview}\n renderField={props.renderField}\n renderItem={props.renderItem}\n />\n )\n case 'fieldSet':\n return (\n <MemberFieldSet\n key={member.key}\n member={member}\n // @ts-expect-error - MemberFieldSet renderInput typings do not match custom callback\n renderInput={renderInput}\n renderPreview={props.renderPreview}\n renderField={props.renderField}\n renderItem={props.renderItem}\n />\n )\n case 'error':\n return <MemberFieldError key={member.key} member={member} />\n default:\n return null\n }\n })}\n </Stack>\n )\n}\n","import {definePlugin} from 'sanity'\n\nimport {GoogleTranslateInput} from './GoogleTranslateInput'\nimport type {GoogleTranslateSchemaOptions} from './types'\n\nexport const googleTranslate = definePlugin(() => {\n return {\n name: 'sanity-plugin-google-translate',\n form: {\n components: {\n input: (props) => {\n // oxlint-disable-next-line no-unsafe-type-assertion - plugin-specific object options\n const options = props.schemaType.options as GoogleTranslateSchemaOptions | undefined\n\n if (options?.translate) {\n if (props.schemaType.jsonType !== 'object') {\n throw new Error(\n `The translate option is only supported on object type fields, but got ${props.schemaType.jsonType}`,\n )\n }\n\n // @ts-expect-error - form input props are wider than ObjectInputProps\n return <GoogleTranslateInput {...props} />\n }\n\n return props.renderDefault(props)\n },\n },\n },\n }\n})\n"],"mappings":"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"}
\ No newline at end of file