import React, { useMemo, useRef, useState } from 'react' import { getFlatResources, getGroupedMissingTranslations, getMissingTranslationCount, type MissingTranslation, type Resources, SUPPORTED_LANGUAGES, type SupportedLanguageKeys, } from './TranslationTools.models' import { PageHeader } from '../PageHeader/PageHeader' import Button from '../Button/Button' import { capitalize } from '../../services/HelperServiceTyped' import { type ConfigItemType, type GroupColorType, } from '../TableComponents/StandardTable.models' import EmptyState from '../EmptyState/EmptyState' import StandardTable from '../TableComponents/StandardTable' import Switch from '../Switch/Switch' import { toast } from '../Toast/Toast' import styles from './_translation-tools.module.scss' import ScrollingContainer from '../ScrollingContainer/ScrollingContainer' import { c } from '../../translations/LibraryTranslationService' const TranslationTools = ({ languagesToCheck, resources, hideReturnToAppButton, }: { languagesToCheck: SupportedLanguageKeys[] resources: Resources hideReturnToAppButton?: boolean }): React.JSX.Element => { const [isAIPrompt, setIsAIPrompt] = useState(false) const groupedMissingTranslations = useMemo( () => getGroupedMissingTranslations({ resources, languagesToCheck }), [languagesToCheck, resources], ) const totalMissingTranslations = useMemo( () => getMissingTranslationCount(groupedMissingTranslations), [groupedMissingTranslations], ) const flatResources = useMemo(() => getFlatResources(resources), [resources]) interface Translation { englishValue: string language: string key: string } interface Module { [moduleName: string]: Translation[] } interface LanguageData { [languageCode: string]: Module } function getTotalCounts(data: LanguageData): { [languageCode: string]: number } { const counts: { [languageCode: string]: number } = {} for (const languageCode in data) { if (Object.prototype.hasOwnProperty.call(data, languageCode)) { let totalCount = 0 const modules = data[languageCode] for (const moduleName in modules) { if (Object.prototype.hasOwnProperty.call(modules, moduleName)) { totalCount += modules[moduleName].length } } counts[languageCode] = totalCount } } return counts } const totalCounts = getTotalCounts(groupedMissingTranslations) const TranslationCard = ({ language, modules, }: { language: SupportedLanguageKeys modules: Record }): React.JSX.Element => { const textRef = useRef(null) const copyToClipboard = () => { if (textRef.current) { navigator.clipboard.writeText(textRef.current.innerText).then( () => { toast({ message: c('textCopiedToClipboard'), type: 'success' }) }, (err) => { toast({ message: c('failedToCopyText', { error: err, }), type: 'error', }) }, ) } } type Modules = { [key: string]: Translation[] } type TransformedTranslation = Translation & { module: string } function transformData(data: Modules): TransformedTranslation[] { const result: TransformedTranslation[] = [] Object.keys(data).forEach((moduleKey) => { const translations = data[moduleKey] const transformedTranslations = translations.map((translation) => ({ module: moduleKey, ...translation, })) result.push(...transformedTranslations) }) return result } const data = transformData(modules) const tableConfig: ConfigItemType< TransformedTranslation, Record >[] = [ { label: 'Translation Key', name: 'key', cell: { children: (d): React.JSX.Element => { return
{d.key}
}, }, noSort: true, }, { label: 'English Value', name: 'englishValue', cell: { children: (d): React.JSX.Element => { return
{d.englishValue}
}, }, noSort: true, }, ] const groups = Object.keys(modules).map((module) => ({ groupHeader: capitalize(module), type: 'gray' as GroupColorType, check: (translation: TransformedTranslation) => translation.module === module, })) return (
{SUPPORTED_LANGUAGES[language].language} ({language}) -{' '} {totalCounts[language]}
{!isAIPrompt ? ( ) : Object.entries(modules).length > 0 ? ( {isAIPrompt ? (
Translate all of these values to{' '} {SUPPORTED_LANGUAGES[language].language}. Keep the keys the same.
```
) : null} {Object.entries(modules).map( ([moduleKey, translations], index) => (
{!isAIPrompt && (
{moduleKey}
)} {translations.map((translation, index) => (
{`"${translation?.key}": "${translation?.englishValue}",`}
))} {index !== Object.entries(modules).length - 1 &&
}
), )} {isAIPrompt ? <>``` : null}
) : ( )}
) } return (
(element as HTMLDivElement)?.click(), }, ], initialDisplay: true, show: true, }} rightSectionChildren={
setIsAIPrompt(!isAIPrompt)} checked={isAIPrompt} formLabelProps={{ label: 'AI Prompts', }} disabled={totalMissingTranslations === 0} /> {!hideReturnToAppButton ? ( <> ) : null}
} /> {/* Height: 100vh - page padding - header */}
{Object.entries(groupedMissingTranslations).map( ([language, modules]) => ( ), )}
) } export default TranslationTools