@manifest-editor/translation 2.0.3-next.0.3782be7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["M2M100_LANGUAGES: M2M100Language[]","defaultTranslationContentFilters: TranslationContentFilters","settings","supported: string[]","ctx: CollectContext","ctx: LanguageDetectionContext","progress: TranslationLanguageProgress","getVaultResource","toReferences","isTextualBody","entries: AnnotationBodyResourceEntry[]","languageMatches","createTargetLanguageGroups","CompactLanguageSelect","TranslationFiltersMenu","groups: LanguageOptionGroup[]","translated: string[]","tokens: HtmlToken[]","match: RegExpExecArray | null","stack: string[]","writable: TranslationOccurrence[]","existing: TranslationOccurrence[]","stale: TranslationOccurrence[]","entries: TextualBodyEntry[]","hashString","settings","retainedClient: TranslationWorkerClient | null","retainedWorkerUrl: string | undefined","writeContext: TranslationWriteContext","createEmptyResult","skippedTask","translationText: string | null","throwIfAborted","result","detected: DetectedCanvasLanguage[]","translationsPanel: LayoutPanel","settings","vault","filterTabs: Array<{\n key: FilterKey;\n label: string;\n count: number;\n title?: string;\n }>","groups: LanguageOptionGroup[]","statusDotConfig: Record<TranslationStatus, { dot: string; label: string; text: string }>","leftPanels: LayoutPanel[]","backgroundActions: BackgroundActionDefinition[]"],"sources":["../src/languages.ts","../src/options.ts","../src/collection.ts","../src/config-modal.tsx","../src/html.ts","../src/runtime/browser/client.ts","../src/results.tsx","../src/writeback.ts","../src/background-action.tsx","../src/language-tags-background-action.ts","../src/sidebar.tsx","../src/index.ts"],"sourcesContent":["export type M2M100Language = {\n code: string;\n label: string;\n};\n\nexport type LanguageProgressSummary = {\n total: number;\n existing: number;\n suggested?: number;\n};\n\nexport const M2M100_LANGUAGES: M2M100Language[] = [\n { code: \"af\", label: \"Afrikaans\" },\n { code: \"am\", label: \"Amharic\" },\n { code: \"ar\", label: \"Arabic\" },\n { code: \"ast\", label: \"Asturian\" },\n { code: \"az\", label: \"Azerbaijani\" },\n { code: \"ba\", label: \"Bashkir\" },\n { code: \"be\", label: \"Belarusian\" },\n { code: \"bg\", label: \"Bulgarian\" },\n { code: \"bn\", label: \"Bengali\" },\n { code: \"br\", label: \"Breton\" },\n { code: \"bs\", label: \"Bosnian\" },\n { code: \"ca\", label: \"Catalan; Valencian\" },\n { code: \"ceb\", label: \"Cebuano\" },\n { code: \"cs\", label: \"Czech\" },\n { code: \"cy\", label: \"Welsh\" },\n { code: \"da\", label: \"Danish\" },\n { code: \"de\", label: \"German\" },\n { code: \"el\", label: \"Greek\" },\n { code: \"en\", label: \"English\" },\n { code: \"es\", label: \"Spanish\" },\n { code: \"et\", label: \"Estonian\" },\n { code: \"fa\", label: \"Persian\" },\n { code: \"ff\", label: \"Fulah\" },\n { code: \"fi\", label: \"Finnish\" },\n { code: \"fr\", label: \"French\" },\n { code: \"fy\", label: \"Western Frisian\" },\n { code: \"ga\", label: \"Irish\" },\n { code: \"gd\", label: \"Gaelic; Scottish Gaelic\" },\n { code: \"gl\", label: \"Galician\" },\n { code: \"gu\", label: \"Gujarati\" },\n { code: \"ha\", label: \"Hausa\" },\n { code: \"he\", label: \"Hebrew\" },\n { code: \"hi\", label: \"Hindi\" },\n { code: \"hr\", label: \"Croatian\" },\n { code: \"ht\", label: \"Haitian; Haitian Creole\" },\n { code: \"hu\", label: \"Hungarian\" },\n { code: \"hy\", label: \"Armenian\" },\n { code: \"id\", label: \"Indonesian\" },\n { code: \"ig\", label: \"Igbo\" },\n { code: \"ilo\", label: \"Iloko\" },\n { code: \"is\", label: \"Icelandic\" },\n { code: \"it\", label: \"Italian\" },\n { code: \"ja\", label: \"Japanese\" },\n { code: \"jv\", label: \"Javanese\" },\n { code: \"ka\", label: \"Georgian\" },\n { code: \"kk\", label: \"Kazakh\" },\n { code: \"km\", label: \"Central Khmer\" },\n { code: \"kn\", label: \"Kannada\" },\n { code: \"ko\", label: \"Korean\" },\n { code: \"lb\", label: \"Luxembourgish; Letzeburgesch\" },\n { code: \"lg\", label: \"Ganda\" },\n { code: \"ln\", label: \"Lingala\" },\n { code: \"lo\", label: \"Lao\" },\n { code: \"lt\", label: \"Lithuanian\" },\n { code: \"lv\", label: \"Latvian\" },\n { code: \"mg\", label: \"Malagasy\" },\n { code: \"mk\", label: \"Macedonian\" },\n { code: \"ml\", label: \"Malayalam\" },\n { code: \"mn\", label: \"Mongolian\" },\n { code: \"mr\", label: \"Marathi\" },\n { code: \"ms\", label: \"Malay\" },\n { code: \"my\", label: \"Burmese\" },\n { code: \"ne\", label: \"Nepali\" },\n { code: \"nl\", label: \"Dutch; Flemish\" },\n { code: \"no\", label: \"Norwegian\" },\n { code: \"ns\", label: \"Northern Sotho\" },\n { code: \"oc\", label: \"Occitan\" },\n { code: \"or\", label: \"Oriya\" },\n { code: \"pa\", label: \"Panjabi; Punjabi\" },\n { code: \"pl\", label: \"Polish\" },\n { code: \"ps\", label: \"Pushto; Pashto\" },\n { code: \"pt\", label: \"Portuguese\" },\n { code: \"ro\", label: \"Romanian; Moldavian; Moldovan\" },\n { code: \"ru\", label: \"Russian\" },\n { code: \"sd\", label: \"Sindhi\" },\n { code: \"si\", label: \"Sinhala; Sinhalese\" },\n { code: \"sk\", label: \"Slovak\" },\n { code: \"sl\", label: \"Slovenian\" },\n { code: \"so\", label: \"Somali\" },\n { code: \"sq\", label: \"Albanian\" },\n { code: \"sr\", label: \"Serbian\" },\n { code: \"ss\", label: \"Swati\" },\n { code: \"su\", label: \"Sundanese\" },\n { code: \"sv\", label: \"Swedish\" },\n { code: \"sw\", label: \"Swahili\" },\n { code: \"ta\", label: \"Tamil\" },\n { code: \"th\", label: \"Thai\" },\n { code: \"tl\", label: \"Tagalog\" },\n { code: \"tn\", label: \"Tswana\" },\n { code: \"tr\", label: \"Turkish\" },\n { code: \"uk\", label: \"Ukrainian\" },\n { code: \"ur\", label: \"Urdu\" },\n { code: \"uz\", label: \"Uzbek\" },\n { code: \"vi\", label: \"Vietnamese\" },\n { code: \"wo\", label: \"Wolof\" },\n { code: \"xh\", label: \"Xhosa\" },\n { code: \"yi\", label: \"Yiddish\" },\n { code: \"yo\", label: \"Yoruba\" },\n { code: \"zh\", label: \"Chinese\" },\n { code: \"zu\", label: \"Zulu\" },\n];\n\nconst supportedLanguageCodes = new Set(\n M2M100_LANGUAGES.map((language) => language.code),\n);\n\nexport function isSupportedM2M100Language(\n code: string | null | undefined,\n): boolean {\n return !!code && supportedLanguageCodes.has(code);\n}\n\nexport function getLanguageLabel(code: string) {\n return (\n M2M100_LANGUAGES.find((language) => language.code === code)?.label || code\n );\n}\n\nexport function getLanguageProgressLabel(progress: LanguageProgressSummary) {\n if (!progress.total) {\n return \"0\";\n }\n\n const done = progress.existing + (progress.suggested || 0);\n return `${Math.round((done / progress.total) * 100)}%`;\n}\n","import type { Config } from \"@manifest-editor/shell\";\nimport { isSupportedM2M100Language } from \"./languages\";\nimport type {\n TranslationContentFilters,\n TranslationPluginSettings,\n TranslationRunOptions,\n TranslationRuntimePreference,\n} from \"./types\";\n\nconst defaultSourceLanguage = \"en\";\nconst defaultTargetLanguage = \"nl\";\nexport const TRANSLATION_NONE_LANGUAGE = \"none\";\n\nexport const defaultTranslationContentFilters: TranslationContentFilters = {\n annotationBodies: true,\n canvasLabels: true,\n};\n\nexport function getDefaultRunOptions(\n config?: Partial<Config> | null,\n settings: TranslationPluginSettings = {},\n): TranslationRunOptions {\n const availableLanguages = getSupportedAvailableLanguages(config);\n const sourceLanguage =\n resolveSourceLanguage(settings.defaultSourceLanguage) ||\n resolveSupportedLanguage(config?.i18n?.defaultLanguage) ||\n availableLanguages[0] ||\n defaultSourceLanguage;\n const modelSourceLanguage =\n resolveSupportedLanguage(settings.defaultSourceLanguage) ||\n resolveSupportedLanguage(config?.i18n?.defaultLanguage) ||\n availableLanguages[0] ||\n defaultSourceLanguage;\n const targetLanguage =\n resolveSupportedLanguage(settings.defaultTargetLanguage, modelSourceLanguage) ||\n availableLanguages.find((language) => language !== modelSourceLanguage) ||\n (modelSourceLanguage === defaultTargetLanguage\n ? defaultSourceLanguage\n : defaultTargetLanguage);\n\n return normaliseRunOptions({\n sourceLanguage,\n modelSourceLanguage,\n targetLanguage,\n runtime: settings.runtimePreference,\n writePolicy: \"fill-missing\",\n });\n}\n\nexport function normaliseRunOptions(\n options: Partial<TranslationRunOptions> = {},\n): TranslationRunOptions {\n const sourceLanguage =\n resolveSourceLanguage(options.sourceLanguage) || defaultSourceLanguage;\n const modelSourceLanguage = getModelSourceLanguage(sourceLanguage, options);\n const targetLanguage =\n resolveSupportedLanguage(options.targetLanguage, modelSourceLanguage) ||\n (modelSourceLanguage === defaultTargetLanguage\n ? defaultSourceLanguage\n : defaultTargetLanguage);\n\n return {\n sourceLanguage,\n modelSourceLanguage,\n targetLanguage,\n runtime: normaliseRuntimePreference(options.runtime),\n writePolicy: \"fill-missing\",\n contentFilters: normaliseContentFilters(options.contentFilters),\n currentResourceOnly: options.currentResourceOnly === true,\n };\n}\n\nexport function getSupportedAvailableLanguages(\n config?: Partial<Config> | null,\n): string[] {\n const configured = config?.i18n?.availableLanguages || [];\n const supported: string[] = [];\n\n for (const language of configured) {\n const resolved = resolveSupportedLanguage(language);\n if (resolved && !supported.includes(resolved)) {\n supported.push(resolved);\n }\n }\n\n return supported;\n}\n\nexport function resolveSupportedLanguage(\n language: unknown,\n disallow?: string,\n): string | null {\n if (typeof language !== \"string\") {\n return null;\n }\n\n const normalised = normaliseLanguageCode(language);\n if (!normalised || normalised === disallow) {\n return null;\n }\n\n if (isSupportedM2M100Language(normalised)) {\n return normalised;\n }\n\n const baseLanguage = normalised.split(\"-\")[0] || \"\";\n if (\n baseLanguage !== normalised &&\n baseLanguage !== disallow &&\n isSupportedM2M100Language(baseLanguage)\n ) {\n return baseLanguage;\n }\n\n return null;\n}\n\nexport function resolveSourceLanguage(language: unknown): string | null {\n if (isNoLanguageCode(language)) {\n return TRANSLATION_NONE_LANGUAGE;\n }\n\n return resolveSupportedLanguage(language);\n}\n\nexport function getModelSourceLanguage(\n sourceLanguage: unknown,\n options: Partial<TranslationRunOptions> = {},\n) {\n return (\n resolveSupportedLanguage(sourceLanguage) ||\n resolveSupportedLanguage(options.modelSourceLanguage) ||\n defaultSourceLanguage\n );\n}\n\nexport function isNoLanguageCode(language: unknown) {\n return typeof language === \"string\" && normaliseLanguageCode(language) === TRANSLATION_NONE_LANGUAGE;\n}\n\nexport function normaliseLanguageCode(language: string) {\n return language.trim().replace(/_/g, \"-\").toLowerCase();\n}\n\nfunction normaliseRuntimePreference(\n value: unknown,\n): TranslationRuntimePreference {\n return value === \"webgpu\" || value === \"wasm\" || value === \"auto\"\n ? value\n : \"auto\";\n}\n\nfunction normaliseContentFilters(value: unknown): TranslationContentFilters {\n const filters =\n value && typeof value === \"object\"\n ? (value as Partial<TranslationContentFilters>)\n : {};\n\n return {\n annotationBodies:\n typeof filters.annotationBodies === \"boolean\"\n ? filters.annotationBodies\n : defaultTranslationContentFilters.annotationBodies,\n canvasLabels:\n typeof filters.canvasLabels === \"boolean\"\n ? filters.canvasLabels\n : defaultTranslationContentFilters.canvasLabels,\n };\n}\n","import { getAvailableLanguagesFromResource } from \"@iiif/helpers/i18n\";\nimport type { Vault } from \"@iiif/helpers/vault\";\nimport type { InternationalString, Reference } from \"@iiif/presentation-3\";\nimport type {\n LanguageMapLike,\n TranslationOccurrence,\n TranslationPath,\n TranslationResourceRef,\n TranslationRunOptions,\n TranslationStatus,\n TranslationTarget,\n TranslationValueFormat,\n} from \"./types\";\nimport { normaliseLanguageCode, resolveSourceLanguage, resolveSupportedLanguage } from \"./options\";\n\ntype CollectContext = {\n vault: Vault;\n options: TranslationRunOptions;\n occurrences: TranslationOccurrence[];\n visited: Set<string>;\n};\n\ntype SourceEntry = {\n sourceMapLanguage: string;\n sourceIndex: number;\n sourceText: string;\n};\n\ntype AnnotationBodyResourceEntry = {\n ref: Reference<\"ContentResource\">;\n resource: any;\n choice?: Reference<\"ContentResource\">;\n};\n\nexport type DetectedManifestLanguage = {\n language: string;\n count: number;\n iiifLanguages: string[];\n};\n\nexport type TranslationLanguageProgress = {\n language: string;\n total: number;\n missing: number;\n existing: number;\n suggested: number;\n skipped: number;\n stale: number;\n};\n\ntype LanguageDetectionContext = {\n vault: Vault;\n languages: Map<string, DetectedManifestLanguage>;\n visited: Set<string>;\n};\n\nexport function collectTranslationTargets(\n vault: Vault,\n root: Reference,\n options: TranslationRunOptions,\n): TranslationTarget[] {\n const ctx: CollectContext = {\n vault,\n options,\n occurrences: [],\n visited: new Set(),\n };\n\n walkResource(ctx, root);\n\n const byKey = new Map<string, TranslationTarget>();\n for (const occurrence of ctx.occurrences) {\n const normalisedSourceText = normaliseTranslationText(\n occurrence.sourceText,\n );\n if (!normalisedSourceText) {\n continue;\n }\n\n const key = createTranslationTargetKey(\n normalisedSourceText,\n occurrence.sourceLanguage,\n occurrence.targetLanguage,\n occurrence.valueFormat,\n );\n const existing = byKey.get(key);\n\n if (existing) {\n existing.occurrences.push(occurrence);\n existing.status = mergeStatus(existing.status, occurrence.status);\n continue;\n }\n\n byKey.set(key, {\n key,\n sourceLanguage: occurrence.sourceLanguage,\n targetLanguage: occurrence.targetLanguage,\n sourceText: occurrence.sourceText,\n normalisedSourceText,\n valueFormat: occurrence.valueFormat,\n occurrences: [occurrence],\n status: occurrence.status,\n });\n }\n\n return Array.from(byKey.values()).sort((a, b) => {\n const status = statusOrder(a.status) - statusOrder(b.status);\n if (status !== 0) return status;\n return a.sourceText.localeCompare(b.sourceText);\n });\n}\n\nexport function collectDetectedManifestLanguages(\n vault: Vault,\n root: Reference,\n): DetectedManifestLanguage[] {\n const ctx: LanguageDetectionContext = {\n vault,\n languages: new Map(),\n visited: new Set(),\n };\n\n walkDetectedLanguageResource(ctx, root);\n\n return Array.from(ctx.languages.values()).sort((a, b) =>\n getLanguageSortLabel(a).localeCompare(getLanguageSortLabel(b)),\n );\n}\n\nexport function collectTranslationLanguageProgress(\n vault: Vault,\n root: Reference,\n options: TranslationRunOptions,\n languages = collectDetectedManifestLanguages(vault, root).map(\n (item) => item.language,\n ),\n): TranslationLanguageProgress[] {\n return languages.filter((language) => !!resolveSupportedLanguage(language)).map((language) => {\n const progress: TranslationLanguageProgress = {\n language,\n total: 0,\n missing: 0,\n existing: 0,\n suggested: 0,\n skipped: 0,\n stale: 0,\n };\n\n for (const target of collectTranslationTargets(vault, root, {\n ...options,\n targetLanguage: language,\n })) {\n progress.total += 1;\n progress[target.status] += 1;\n }\n\n return progress;\n });\n}\n\nexport function normaliseTranslationText(value: string) {\n return value.replace(/\\s+/g, \" \").trim();\n}\n\nexport function fingerprintTranslationText(value: string) {\n return normaliseTranslationText(value);\n}\n\nexport function createTranslationTargetKey(\n sourceText: string,\n sourceLanguage: string,\n targetLanguage: string,\n valueFormat: TranslationValueFormat,\n) {\n return `${sourceLanguage}:${targetLanguage}:${valueFormat}:${sourceText.toLowerCase()}`;\n}\n\nexport function getLanguageMapSourceEntries(\n value: LanguageMapLike,\n sourceLanguage: string,\n): SourceEntry[] {\n if (!value) {\n return [];\n }\n\n if (typeof value === \"string\") {\n return value.trim()\n ? [\n {\n sourceMapLanguage: sourceLanguage,\n sourceIndex: 0,\n sourceText: value,\n },\n ]\n : [];\n }\n\n const directValues = getLanguageValues(value, sourceLanguage);\n if (directValues.length) {\n return directValues\n .map((sourceText, sourceIndex) => ({\n sourceMapLanguage: sourceLanguage,\n sourceIndex,\n sourceText,\n }))\n .filter((entry) => normaliseTranslationText(entry.sourceText));\n }\n\n const resolvedSourceLanguage = resolveSupportedLanguage(sourceLanguage);\n if (resolvedSourceLanguage) {\n const matchedLanguage = Object.keys(value).find(\n (language) =>\n language !== sourceLanguage &&\n resolveSupportedLanguage(language) === resolvedSourceLanguage,\n );\n\n if (matchedLanguage) {\n return getLanguageValues(value, matchedLanguage)\n .map((sourceText, sourceIndex) => ({\n sourceMapLanguage: matchedLanguage,\n sourceIndex,\n sourceText,\n }))\n .filter((entry) => normaliseTranslationText(entry.sourceText));\n }\n }\n\n const noLanguageValues = getLanguageValues(value, \"none\");\n return noLanguageValues\n .map((sourceText, sourceIndex) => ({\n sourceMapLanguage: \"none\",\n sourceIndex,\n sourceText,\n }))\n .filter((entry) => normaliseTranslationText(entry.sourceText));\n}\n\nexport function getLanguageValueAt(\n value: LanguageMapLike,\n language: string,\n index: number,\n) {\n if (!value) {\n return \"\";\n }\n\n if (typeof value === \"string\") {\n return language === \"none\" || index === 0 ? value : \"\";\n }\n\n return getLanguageValues(value, language)[index] || \"\";\n}\n\nexport function getLanguageValues(\n value: InternationalString,\n language: string,\n) {\n const values = value[language];\n if (!Array.isArray(values)) {\n return [];\n }\n\n return values.filter((item): item is string => typeof item === \"string\");\n}\n\nexport function getLanguageMapTargetText(\n value: LanguageMapLike,\n targetLanguage: string,\n sourceIndex: number,\n) {\n const exactValue = getLanguageValueAt(value, targetLanguage, sourceIndex);\n if (normaliseTranslationText(exactValue)) {\n return exactValue;\n }\n\n if (!value || typeof value === \"string\") {\n return \"\";\n }\n\n const resolvedTargetLanguage = resolveSupportedLanguage(targetLanguage);\n if (resolvedTargetLanguage) {\n for (const language of Object.keys(value)) {\n if (\n language === targetLanguage ||\n resolveSupportedLanguage(language) !== resolvedTargetLanguage\n ) {\n continue;\n }\n\n const valueAtIndex = getLanguageValueAt(value, language, sourceIndex);\n if (normaliseTranslationText(valueAtIndex)) {\n return valueAtIndex;\n }\n }\n }\n\n return (\n getLanguageValues(value, targetLanguage).find((item) =>\n normaliseTranslationText(item),\n ) || \"\"\n );\n}\n\nexport function isHtmlTranslationValue(value: string): boolean {\n return /<\\/?[a-z][\\s\\S]*>/i.test(value);\n}\n\nfunction walkResource(ctx: CollectContext, ref: Reference | null | undefined) {\n if (!ref?.id || !ref.type) {\n return;\n }\n\n const key = `${ref.type}:${ref.id}`;\n if (ctx.visited.has(key)) {\n return;\n }\n ctx.visited.add(key);\n\n const resource = getVaultResource(ctx.vault, ref);\n if (!resource) {\n return;\n }\n\n collectResourceLanguageMaps(ctx, resource);\n collectMetadata(ctx, resource);\n collectRequiredStatement(ctx, resource);\n\n for (const provider of toReferences(resource.provider, \"Agent\")) {\n walkResource(ctx, provider);\n }\n\n switch (resource.type) {\n case \"Manifest\":\n for (const item of toReferences(resource.items, \"Canvas\")) {\n walkResource(ctx, item);\n }\n for (const item of toReferences(resource.structures, \"Range\")) {\n walkResource(ctx, item);\n }\n break;\n case \"Canvas\":\n for (const page of [\n ...toReferences(resource.items, \"AnnotationPage\"),\n ...toReferences(resource.annotations, \"AnnotationPage\"),\n ]) {\n walkResource(ctx, page);\n }\n break;\n case \"Range\":\n for (const item of toReferences(resource.items)) {\n walkResource(ctx, item);\n }\n break;\n case \"AnnotationPage\":\n for (const item of toReferences(resource.items, \"Annotation\")) {\n walkResource(ctx, item);\n }\n break;\n case \"Annotation\":\n collectAnnotationBodies(ctx, resource);\n break;\n }\n}\n\nfunction walkDetectedLanguageResource(\n ctx: LanguageDetectionContext,\n ref: Reference | null | undefined,\n) {\n if (!ref?.id || !ref.type) {\n return;\n }\n\n const key = `${ref.type}:${ref.id}`;\n if (ctx.visited.has(key)) {\n return;\n }\n ctx.visited.add(key);\n\n const resource = getVaultResource(ctx.vault, ref);\n if (!resource) {\n return;\n }\n\n collectDetectedResourceLanguages(ctx, resource);\n\n for (const provider of toReferences(resource.provider, \"Agent\")) {\n walkDetectedLanguageResource(ctx, provider);\n }\n\n switch (resource.type) {\n case \"Manifest\":\n for (const item of toReferences(resource.items, \"Canvas\")) {\n walkDetectedLanguageResource(ctx, item);\n }\n for (const item of toReferences(resource.structures, \"Range\")) {\n walkDetectedLanguageResource(ctx, item);\n }\n break;\n case \"Canvas\":\n for (const page of [\n ...toReferences(resource.items, \"AnnotationPage\"),\n ...toReferences(resource.annotations, \"AnnotationPage\"),\n ]) {\n walkDetectedLanguageResource(ctx, page);\n }\n break;\n case \"Range\":\n for (const item of toReferences(resource.items)) {\n walkDetectedLanguageResource(ctx, item);\n }\n break;\n case \"AnnotationPage\":\n for (const item of toReferences(resource.items, \"Annotation\")) {\n walkDetectedLanguageResource(ctx, item);\n }\n break;\n case \"Annotation\":\n for (const body of toReferences(resource.body, \"ContentResource\")) {\n walkDetectedLanguageResource(ctx, body);\n }\n break;\n case \"Choice\":\n for (const item of toReferences(resource.items, \"ContentResource\")) {\n walkDetectedLanguageResource(ctx, item);\n }\n break;\n }\n}\n\nfunction collectDetectedResourceLanguages(ctx: LanguageDetectionContext, resource: any) {\n for (const language of getAvailableLanguagesFromResourceSafe(resource)) {\n if (typeof language === \"string\") {\n addDetectedLanguage(ctx, language, 1);\n }\n }\n}\n\nfunction getAvailableLanguagesFromResourceSafe(resource: any): unknown[] {\n const languages = new Set<string>();\n\n try {\n for (const language of getAvailableLanguagesFromResource(resource)) {\n if (typeof language === \"string\") {\n languages.add(language);\n }\n }\n } catch {\n // The local fallback below covers resource shapes that the helper cannot inspect.\n }\n\n for (const language of getFallbackAvailableLanguages(resource)) {\n languages.add(language);\n }\n\n return Array.from(languages);\n}\n\nfunction getFallbackAvailableLanguages(resource: any): string[] {\n const languages = new Set<string>();\n\n addLanguageMapLanguages(languages, resource?.label);\n addLanguageMapLanguages(languages, resource?.summary);\n\n if (typeof resource?.language === \"string\") {\n languages.add(resource.language);\n } else if (Array.isArray(resource?.language)) {\n for (const language of resource.language) {\n if (typeof language === \"string\") {\n languages.add(language);\n }\n }\n }\n\n const requiredStatement = resource?.requiredStatement;\n if (requiredStatement && !Array.isArray(requiredStatement)) {\n addLanguageMapLanguages(languages, requiredStatement.label);\n addLanguageMapLanguages(languages, requiredStatement.value);\n }\n\n if (Array.isArray(resource?.metadata)) {\n for (const item of resource.metadata) {\n addLanguageMapLanguages(languages, item?.label);\n addLanguageMapLanguages(languages, item?.value);\n }\n }\n\n return Array.from(languages);\n}\n\nfunction addLanguageMapLanguages(languages: Set<string>, value: LanguageMapLike) {\n if (!value || typeof value === \"string\") {\n return;\n }\n\n for (const [language, values] of Object.entries(value)) {\n if (Array.isArray(values) && values.some((item) => typeof item === \"string\" && normaliseTranslationText(item))) {\n languages.add(language);\n }\n }\n}\n\nfunction addDetectedLanguage(\n ctx: LanguageDetectionContext,\n rawLanguage: string,\n count: number,\n) {\n const language = resolveSourceLanguage(rawLanguage);\n if (!language) {\n return;\n }\n\n const normalisedRawLanguage = normaliseLanguageCode(rawLanguage);\n const existing = ctx.languages.get(language);\n if (existing) {\n existing.count += count;\n if (!existing.iiifLanguages.includes(normalisedRawLanguage)) {\n existing.iiifLanguages.push(normalisedRawLanguage);\n }\n return;\n }\n\n ctx.languages.set(language, {\n language,\n count,\n iiifLanguages: [normalisedRawLanguage],\n });\n}\n\nfunction collectResourceLanguageMaps(\n ctx: CollectContext,\n resource: any,\n refOverride?: TranslationResourceRef,\n) {\n const ref = refOverride || toResourceRef(resource);\n addLanguageMapOccurrences(ctx, {\n path: { kind: \"resource-language-map\", resource: ref, property: \"label\" },\n resource: ref,\n propertyLabel: \"Label\",\n value: resource.label,\n });\n addLanguageMapOccurrences(ctx, {\n path: { kind: \"resource-language-map\", resource: ref, property: \"summary\" },\n resource: ref,\n propertyLabel: \"Summary\",\n value: resource.summary,\n });\n}\n\nfunction collectMetadata(\n ctx: CollectContext,\n resource: any,\n refOverride?: TranslationResourceRef,\n) {\n const metadata = Array.isArray(resource.metadata) ? resource.metadata : [];\n const ref = refOverride || toResourceRef(resource);\n\n metadata.forEach((item: any, metadataIndex: number) => {\n addLanguageMapOccurrences(ctx, {\n path: {\n kind: \"metadata-language-map\",\n resource: ref,\n metadataIndex,\n field: \"label\",\n },\n resource: ref,\n propertyLabel: `Metadata ${metadataIndex + 1} label`,\n value: item?.label,\n });\n addLanguageMapOccurrences(ctx, {\n path: {\n kind: \"metadata-language-map\",\n resource: ref,\n metadataIndex,\n field: \"value\",\n },\n resource: ref,\n propertyLabel: `Metadata ${metadataIndex + 1} value`,\n value: item?.value,\n });\n });\n}\n\nfunction collectRequiredStatement(\n ctx: CollectContext,\n resource: any,\n refOverride?: TranslationResourceRef,\n) {\n const requiredStatement = resource.requiredStatement;\n if (!requiredStatement) {\n return;\n }\n\n const ref = refOverride || toResourceRef(resource);\n addLanguageMapOccurrences(ctx, {\n path: {\n kind: \"required-statement-language-map\",\n resource: ref,\n field: \"label\",\n },\n resource: ref,\n propertyLabel: \"Required statement label\",\n value: requiredStatement.label,\n });\n addLanguageMapOccurrences(ctx, {\n path: {\n kind: \"required-statement-language-map\",\n resource: ref,\n field: \"value\",\n },\n resource: ref,\n propertyLabel: \"Required statement value\",\n value: requiredStatement.value,\n });\n}\n\nfunction collectAnnotationBodies(ctx: CollectContext, annotation: any) {\n const annotationRef = {\n id: annotation.id,\n type: \"Annotation\",\n } as Reference<\"Annotation\">;\n const bodies = collectAnnotationBodyResources(ctx.vault, annotation);\n\n for (const { ref, resource } of bodies) {\n const resourceRef = {\n ...ref,\n label: getResourceDisplayLabel(resource, resource.id || ref.id),\n };\n collectResourceLanguageMaps(ctx, resource, resourceRef);\n collectMetadata(ctx, resource, resourceRef);\n collectRequiredStatement(ctx, resource, resourceRef);\n }\n\n if (ctx.options.contentFilters?.annotationBodies === false) {\n return;\n }\n\n const textualBodies = bodies.filter((entry) => isTextualBody(entry.resource));\n\n for (const { ref: bodyRef, resource: body, choice } of textualBodies) {\n if (!isSourceTextualBody(body, ctx.options.sourceLanguage)) {\n continue;\n }\n\n const sourceText = typeof body.value === \"string\" ? body.value : \"\";\n if (!normaliseTranslationText(sourceText)) {\n continue;\n }\n\n const targetBody = findTextualBodyEntryForLanguage(\n textualBodies.filter((entry) =>\n isSameTextualBodyContainer(choice, entry),\n ),\n ctx.options.targetLanguage,\n );\n const targetText =\n typeof targetBody?.resource.value === \"string\"\n ? targetBody.resource.value\n : \"\";\n ctx.occurrences.push({\n id: createOccurrenceId({\n kind: \"textual-body\",\n annotation: annotationRef,\n body: bodyRef,\n choice,\n targetBody: targetBody\n ? ({\n id: targetBody.ref.id,\n type: \"ContentResource\",\n } as Reference<\"ContentResource\">)\n : undefined,\n }),\n path: {\n kind: \"textual-body\",\n annotation: annotationRef,\n body: bodyRef,\n choice,\n targetBody: targetBody\n ? ({\n id: targetBody.ref.id,\n type: \"ContentResource\",\n } as Reference<\"ContentResource\">)\n : undefined,\n },\n resource: {\n id: body.id || bodyRef.id,\n type: \"ContentResource\",\n label: getResourceDisplayLabel(body, body.id || bodyRef.id),\n },\n propertyLabel: \"Annotation body\",\n sourceLanguage: ctx.options.sourceLanguage,\n sourceMapLanguage: getTextualBodyLanguage(\n body.language,\n ctx.options.sourceLanguage,\n ),\n targetLanguage: ctx.options.targetLanguage,\n sourceIndex: 0,\n sourceText,\n targetText,\n valueFormat:\n body.format === \"text/html\" || isHtmlTranslationValue(sourceText)\n ? \"html\"\n : \"text\",\n sourceFingerprint: fingerprintTranslationText(sourceText),\n status: normaliseTranslationText(targetText) ? \"existing\" : \"missing\",\n });\n }\n}\n\nfunction addLanguageMapOccurrences(\n ctx: CollectContext,\n input: {\n path: TranslationPath;\n resource: TranslationResourceRef;\n propertyLabel: string;\n value: LanguageMapLike;\n },\n) {\n if (\n input.path.kind === \"resource-language-map\" &&\n input.path.resource.type === \"Canvas\" &&\n input.path.property === \"label\" &&\n ctx.options.contentFilters?.canvasLabels === false\n ) {\n return;\n }\n\n const entries = getLanguageMapSourceEntries(\n input.value,\n ctx.options.sourceLanguage,\n );\n\n for (const entry of entries) {\n const targetText = getLanguageMapTargetText(\n input.value,\n ctx.options.targetLanguage,\n entry.sourceIndex,\n );\n ctx.occurrences.push({\n id: createOccurrenceId(\n input.path,\n entry.sourceMapLanguage,\n entry.sourceIndex,\n ),\n path: input.path,\n resource: input.resource,\n propertyLabel: input.propertyLabel,\n sourceLanguage: ctx.options.sourceLanguage,\n sourceMapLanguage: entry.sourceMapLanguage,\n targetLanguage: ctx.options.targetLanguage,\n sourceIndex: entry.sourceIndex,\n sourceText: entry.sourceText,\n targetText,\n valueFormat: isHtmlTranslationValue(entry.sourceText) ? \"html\" : \"text\",\n sourceFingerprint: fingerprintTranslationText(entry.sourceText),\n status: normaliseTranslationText(targetText) ? \"existing\" : \"missing\",\n });\n }\n}\n\nfunction createOccurrenceId(\n path: TranslationPath,\n sourceMapLanguage = \"text\",\n sourceIndex = 0,\n) {\n switch (path.kind) {\n case \"resource-language-map\":\n return `${path.resource.type}:${path.resource.id}:${path.property}:${sourceMapLanguage}:${sourceIndex}`;\n case \"metadata-language-map\":\n return `${path.resource.type}:${path.resource.id}:metadata:${path.metadataIndex}:${path.field}:${sourceMapLanguage}:${sourceIndex}`;\n case \"required-statement-language-map\":\n return `${path.resource.type}:${path.resource.id}:requiredStatement:${path.field}:${sourceMapLanguage}:${sourceIndex}`;\n case \"textual-body\":\n return `${path.annotation.id}:body:${path.choice?.id || \"annotation\"}:${path.body.id}`;\n }\n}\n\nfunction collectAnnotationBodyResources(\n vault: Vault,\n annotation: any,\n): AnnotationBodyResourceEntry[] {\n const entries: AnnotationBodyResourceEntry[] = [];\n for (const ref of toReferences(annotation.body, \"ContentResource\")) {\n collectAnnotationBodyResource(\n vault,\n ref as Reference<\"ContentResource\">,\n entries,\n );\n }\n return entries;\n}\n\nfunction collectAnnotationBodyResource(\n vault: Vault,\n ref: Reference<\"ContentResource\">,\n entries: AnnotationBodyResourceEntry[],\n choice?: Reference<\"ContentResource\">,\n) {\n const resource = getVaultResource(vault, ref);\n if (!resource) {\n return;\n }\n\n entries.push({ ref, resource, choice });\n\n if (resource.type !== \"Choice\") {\n return;\n }\n\n for (const itemRef of toReferences(resource.items, \"ContentResource\")) {\n collectAnnotationBodyResource(\n vault,\n itemRef as Reference<\"ContentResource\">,\n entries,\n ref,\n );\n }\n}\n\nfunction findTextualBodyEntryForLanguage(\n bodies: AnnotationBodyResourceEntry[],\n language: string,\n) {\n return bodies.find(({ resource: body }) => {\n if (!isTextualBody(body)) {\n return false;\n }\n\n if (!normaliseTranslationText(String(body.value || \"\"))) {\n return false;\n }\n\n return languageMatches(body.language, language);\n });\n}\n\nfunction isSameTextualBodyContainer(\n choice: Reference<\"ContentResource\"> | undefined,\n b: AnnotationBodyResourceEntry,\n) {\n return (choice?.id || \"\") === (b.choice?.id || \"\");\n}\n\nfunction isSourceTextualBody(body: any, sourceLanguage: string) {\n if (!isTextualBody(body) || typeof body.value !== \"string\") {\n return false;\n }\n\n if (!body.language) {\n return true;\n }\n\n return languageMatches(body.language, sourceLanguage);\n}\n\nfunction isTextualBody(body: any) {\n return body?.type === \"TextualBody\" || body?.type === \"Text\";\n}\n\nfunction languageMatches(value: unknown, language: string) {\n const matchesLanguage = (item: unknown) => {\n if (item === language) {\n return true;\n }\n\n return (\n typeof item === \"string\" &&\n resolveSupportedLanguage(item) === resolveSupportedLanguage(language)\n );\n };\n\n if (Array.isArray(value)) {\n return value.some(matchesLanguage);\n }\n\n return matchesLanguage(value);\n}\n\nfunction getTextualBodyLanguage(value: unknown, fallback: string) {\n if (Array.isArray(value)) {\n return typeof value[0] === \"string\" ? value[0] : fallback;\n }\n\n return typeof value === \"string\" ? value : fallback;\n}\n\nfunction toReferences(value: unknown, fallbackType?: string): Reference[] {\n const values = Array.isArray(value) ? value : value ? [value] : [];\n return values\n .map((item: any) => {\n if (!item?.id) {\n return null;\n }\n\n const type =\n fallbackType === \"ContentResource\" &&\n (item.type === \"TextualBody\" || item.type === \"Text\")\n ? fallbackType\n : item.type || fallbackType;\n\n return {\n id: item.id,\n type,\n } as Reference;\n })\n .filter((item): item is Reference => !!item?.id && !!item.type);\n}\n\nfunction getVaultResource(vault: Vault, ref: Reference): any {\n const resource = vault.get(ref as any, { skipSelfReturn: false } as any);\n return resource && typeof resource === \"object\" ? resource : null;\n}\n\nfunction toResourceRef(resource: any): TranslationResourceRef {\n return {\n id: resource.id,\n type: resource.type,\n label: getResourceDisplayLabel(resource, resource.id || resource.type),\n };\n}\n\nfunction getResourceDisplayLabel(resource: any, fallback: string) {\n if (!resource?.label) {\n return fallback;\n }\n\n if (typeof resource.label === \"string\") {\n return resource.label;\n }\n\n const english = resource.label.en?.find?.((value: string) => value?.trim());\n if (english) {\n return english;\n }\n\n for (const language of Object.keys(resource.label)) {\n const value = resource.label[language]?.find?.((item: string) =>\n item?.trim(),\n );\n if (value) {\n return value;\n }\n }\n\n return fallback;\n}\n\nfunction mergeStatus(\n current: TranslationStatus,\n next: TranslationStatus,\n): TranslationStatus {\n if (current === \"missing\" || next === \"missing\") {\n return \"missing\";\n }\n\n if (current === \"stale\" || next === \"stale\") {\n return \"stale\";\n }\n\n if (current === \"skipped\" || next === \"skipped\") {\n return \"skipped\";\n }\n\n if (current === \"suggested\" || next === \"suggested\") {\n return \"suggested\";\n }\n\n return \"existing\";\n}\n\nfunction statusOrder(status: TranslationStatus) {\n switch (status) {\n case \"missing\":\n return 0;\n case \"stale\":\n return 1;\n case \"skipped\":\n return 2;\n case \"suggested\":\n return 3;\n case \"existing\":\n return 4;\n }\n}\n\nfunction getLanguageSortLabel(language: DetectedManifestLanguage) {\n return language.language;\n}\n","import { Modal } from \"@manifest-editor/components\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type {\n DetectedManifestLanguage,\n TranslationLanguageProgress,\n} from \"./collection\";\nimport { TRANSLATION_MODEL_ID } from \"./constants\";\nimport {\n getLanguageLabel,\n getLanguageProgressLabel,\n M2M100_LANGUAGES,\n} from \"./languages\";\nimport { getModelSourceLanguage, normaliseRunOptions } from \"./options\";\nimport type {\n TranslationContentFilters,\n TranslationResourceRef,\n TranslationRunOptions,\n TranslationTarget,\n} from \"./types\";\n\nexport const TRANSLATION_CONFIG_EVENT = \"@manifest-editor/translation:config\";\n\nexport type TranslationConfigRequest = {\n actionId: string;\n instanceKey: string;\n defaults: TranslationRunOptions;\n availableLanguages: string[];\n detectedLanguages?: DetectedManifestLanguage[];\n currentResource?: TranslationResourceRef;\n getTargets?: (options: TranslationRunOptions) => TranslationTarget[];\n getTargetLanguageProgress?: (\n options: TranslationRunOptions,\n ) => TranslationLanguageProgress[];\n targets: TranslationTarget[];\n signal?: AbortSignal;\n resolve: (options: TranslationRunOptions | false) => void;\n};\n\ntype LanguageOption = {\n value: string;\n label: string;\n};\n\ntype LanguageOptionGroup = {\n label: string;\n options: LanguageOption[];\n};\n\nexport function requestTranslationConfig(\n request: Omit<TranslationConfigRequest, \"resolve\">,\n): Promise<TranslationRunOptions | false> {\n return new Promise((resolve) => {\n if (request.signal?.aborted || typeof window === \"undefined\") {\n resolve(false);\n return;\n }\n\n let settled = false;\n const settle = (options: TranslationRunOptions | false) => {\n if (settled) {\n return;\n }\n\n settled = true;\n request.signal?.removeEventListener(\"abort\", handleAbort);\n resolve(options);\n };\n const handleAbort = () => settle(false);\n\n request.signal?.addEventListener(\"abort\", handleAbort, { once: true });\n window.dispatchEvent(\n new CustomEvent<TranslationConfigRequest>(TRANSLATION_CONFIG_EVENT, {\n detail: { ...request, resolve: settle },\n }),\n );\n });\n}\n\nexport function renderTranslationConfigModal(actionId: string) {\n return <TranslationConfigModal actionId={actionId} />;\n}\n\nfunction TranslationConfigModal({ actionId }: { actionId: string }) {\n const [request, setRequest] = useState<TranslationConfigRequest | null>(null);\n const [options, setOptions] = useState<TranslationRunOptions>(\n normaliseRunOptions({}),\n );\n\n useEffect(() => {\n const listener = (event: Event) => {\n const detail = (event as CustomEvent<TranslationConfigRequest>).detail;\n if (detail?.actionId === actionId) {\n setRequest(detail);\n setOptions(normaliseRunOptions(detail.defaults));\n }\n };\n\n window.addEventListener(TRANSLATION_CONFIG_EVENT, listener);\n return () => window.removeEventListener(TRANSLATION_CONFIG_EVENT, listener);\n }, [actionId]);\n\n useEffect(() => {\n if (!request?.signal) {\n return;\n }\n\n if (request.signal.aborted) {\n setRequest(null);\n return;\n }\n\n const handleAbort = () => setRequest(null);\n request.signal.addEventListener(\"abort\", handleAbort, { once: true });\n return () => request.signal?.removeEventListener(\"abort\", handleAbort);\n }, [request]);\n\n const detectedLanguages = request?.detectedLanguages || [];\n const detectedLanguageCodes = useMemo(\n () => detectedLanguages.map((language) => language.language),\n [detectedLanguages],\n );\n const detectedLanguageKey = detectedLanguageCodes.join(\"|\");\n\n useEffect(() => {\n if (\n !detectedLanguageCodes.length ||\n detectedLanguageCodes.includes(options.sourceLanguage)\n ) {\n return;\n }\n\n setOptions((current) => {\n if (detectedLanguageCodes.includes(current.sourceLanguage)) {\n return current;\n }\n\n return normaliseRunOptions({\n ...current,\n sourceLanguage: detectedLanguageCodes[0],\n });\n });\n }, [detectedLanguageKey, options.sourceLanguage]);\n\n const currentTargets = useMemo(\n () => request?.getTargets?.(options) || request?.targets || [],\n [request, options],\n );\n const missingTargets = useMemo(\n () => currentTargets.filter((target) => target.status === \"missing\").length,\n [currentTargets],\n );\n const targetLanguageProgress = useMemo(\n () => request?.getTargetLanguageProgress?.(options) || [],\n [request, options],\n );\n const sourceLanguageGroups = useMemo(\n () => [\n {\n label: \"Detected in manifest\",\n options: detectedLanguages.map((language) => ({\n value: language.language,\n label: getLanguageLabel(language.language),\n })),\n },\n ],\n [detectedLanguages],\n );\n const targetLanguageGroups = useMemo(\n () => createTargetLanguageGroups(targetLanguageProgress),\n [targetLanguageProgress],\n );\n const updateContentFilter = (\n filter: keyof TranslationContentFilters,\n enabled: boolean,\n ) => {\n setOptions((current) =>\n normaliseRunOptions({\n ...current,\n contentFilters: {\n ...current.contentFilters,\n [filter]: enabled,\n },\n }),\n );\n };\n\n if (!request) {\n return null;\n }\n\n const close = (value: TranslationRunOptions | false) => {\n request.resolve(value === false ? false : normaliseRunOptions(value));\n setRequest(null);\n };\n\n const sourceMatchesTarget =\n getModelSourceLanguage(options.sourceLanguage, options) ===\n options.targetLanguage;\n const currentResourceOnly = options.currentResourceOnly === true && !!request.currentResource;\n const disabled =\n detectedLanguageCodes.length === 0 ||\n sourceMatchesTarget ||\n missingTargets === 0;\n\n return (\n <Modal\n title=\"Run translations\"\n onClose={() => close(false)}\n className=\"max-w-xl\"\n actions={\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n className=\"rounded border border-zinc-200 bg-white px-2.5 py-1.5 text-xs font-medium text-zinc-600 hover:border-zinc-300\"\n onClick={() => close(false)}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"rounded border border-me-primary-500 bg-me-primary-500 px-2.5 py-1.5 text-xs font-medium text-white disabled:cursor-not-allowed disabled:opacity-40\"\n disabled={disabled}\n onClick={() => close(options)}\n >\n Run translation\n </button>\n </div>\n }\n >\n <div className=\"flex flex-col gap-3 p-3 text-sm text-zinc-700\">\n <div className=\"flex flex-col gap-2 border-b border-zinc-100 pb-3\">\n <div className=\"grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-end gap-1.5 sm:grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)_7rem]\">\n <CompactLanguageSelect\n label=\"From\"\n value={options.sourceLanguage}\n groups={sourceLanguageGroups}\n emptyLabel=\"No detected languages\"\n onChange={(sourceLanguage) =>\n setOptions((current) =>\n normaliseRunOptions({ ...current, sourceLanguage }),\n )\n }\n />\n <span className=\"mb-[7px] text-zinc-300 select-none\">→</span>\n <CompactLanguageSelect\n label=\"To\"\n value={options.targetLanguage}\n groups={targetLanguageGroups}\n onChange={(targetLanguage) =>\n setOptions((current) =>\n normaliseRunOptions({ ...current, targetLanguage }),\n )\n }\n />\n <label className=\"col-span-3 grid shrink-0 gap-1 sm:col-span-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-zinc-400\">Mode</span>\n <select\n className=\"rounded border border-zinc-200 bg-white py-[5px] px-2 text-xs text-zinc-700 focus:border-me-primary-500 focus:outline-none focus:ring-2 focus:ring-me-primary-500/20\"\n value={options.runtime}\n onChange={(event) =>\n setOptions((current) =>\n normaliseRunOptions({\n ...current,\n runtime: event.target.value as any,\n }),\n )\n }\n >\n <option value=\"auto\">Auto</option>\n <option value=\"webgpu\">WebGPU</option>\n <option value=\"wasm\">WASM</option>\n </select>\n </label>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <label\n className={`flex items-center gap-2 text-xs ${\n request.currentResource ? \"text-zinc-600\" : \"text-zinc-300\"\n }`}\n title={request.currentResource?.label || request.currentResource?.id}\n >\n <input\n type=\"checkbox\"\n className=\"h-3.5 w-3.5 rounded border-zinc-300\"\n checked={currentResourceOnly}\n disabled={!request.currentResource}\n onChange={(event) =>\n setOptions((current) =>\n normaliseRunOptions({\n ...current,\n currentResourceOnly: event.currentTarget.checked,\n }),\n )\n }\n />\n Current resource\n </label>\n <TranslationFiltersMenu\n filters={options.contentFilters}\n onChange={updateContentFilter}\n />\n </div>\n </div>\n\n {detectedLanguageCodes.length === 0 ? (\n <div className=\"rounded border border-amber-200 bg-amber-50 px-2.5 py-2 text-xs text-amber-800\">\n No supported IIIF languages were detected in this manifest.\n </div>\n ) : null}\n\n {sourceMatchesTarget ? (\n <div className=\"rounded border border-amber-200 bg-amber-50 px-2.5 py-2 text-xs text-amber-800\">\n Select different source and target languages.\n </div>\n ) : null}\n\n <div className=\"rounded border border-zinc-200 bg-zinc-50 px-2.5 py-2\">\n <div className=\"text-xs text-zinc-500\">\n {missingTargets > 0 ? (\n <>\n <span className=\"font-semibold text-amber-600\">{missingTargets}</span> missing\n </>\n ) : (\n <span className=\"text-zinc-400\">No missing strings</span>\n )}\n {currentTargets.length > 0 ? (\n <>\n <span className=\"text-zinc-300\"> · </span>\n <span>{currentTargets.length}</span> total\n </>\n ) : null}\n </div>\n <div className=\"mt-1 text-xs text-zinc-500\">\n Missing target-language values will be filled using {TRANSLATION_MODEL_ID}. Existing target values are left\n unchanged.\n </div>\n </div>\n </div>\n </Modal>\n );\n}\n\nfunction TranslationFiltersMenu({\n filters,\n onChange,\n}: {\n filters: TranslationContentFilters;\n onChange: (filter: keyof TranslationContentFilters, enabled: boolean) => void;\n}) {\n return (\n <details className=\"relative shrink-0\">\n <summary className=\"cursor-pointer list-none rounded border border-zinc-200 bg-white px-2.5 py-1.5 text-xs font-medium text-zinc-600 hover:border-zinc-300\">\n Filters\n </summary>\n <div className=\"absolute right-0 z-20 mt-1 grid w-48 gap-2 rounded border border-zinc-200 bg-white p-2.5 text-xs text-zinc-700 shadow-lg\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n className=\"h-3.5 w-3.5 rounded border-zinc-300\"\n checked={filters.annotationBodies}\n onChange={(event) =>\n onChange(\"annotationBodies\", event.currentTarget.checked)\n }\n />\n Annotation bodies\n </label>\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n className=\"h-3.5 w-3.5 rounded border-zinc-300\"\n checked={filters.canvasLabels}\n onChange={(event) =>\n onChange(\"canvasLabels\", event.currentTarget.checked)\n }\n />\n Canvas labels\n </label>\n </div>\n </details>\n );\n}\n\nfunction createTargetLanguageGroups(\n progress: TranslationLanguageProgress[],\n): LanguageOptionGroup[] {\n const detectedLanguageCodes = new Set(progress.map((item) => item.language));\n const groups: LanguageOptionGroup[] = [];\n\n if (progress.length) {\n groups.push({\n label: \"Detected in manifest\",\n options: progress.map((item) => ({\n value: item.language,\n label: `${getLanguageLabel(item.language)} (${getLanguageProgressLabel(item)})`,\n })),\n });\n }\n\n groups.push({\n label: \"All languages\",\n options: M2M100_LANGUAGES.filter(\n (language) => !detectedLanguageCodes.has(language.code),\n ).map((language) => ({\n value: language.code,\n label: language.label,\n })),\n });\n\n return groups;\n}\n\nfunction CompactLanguageSelect({\n label,\n value,\n groups,\n emptyLabel = \"No languages available\",\n onChange,\n}: {\n label: string;\n value: string;\n groups: LanguageOptionGroup[];\n emptyLabel?: string;\n onChange: (language: string) => void;\n}) {\n const hasOptions = groups.some((group) => group.options.length);\n const hasValue = groups.some((group) =>\n group.options.some((option) => option.value === value),\n );\n\n return (\n <label className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-zinc-400\">{label}</span>\n <select\n className=\"w-full rounded border border-zinc-200 bg-white py-[5px] px-2 text-xs text-zinc-800 focus:border-me-primary-500 focus:outline-none focus:ring-2 focus:ring-me-primary-500/20\"\n value={value}\n disabled={!hasOptions}\n onChange={(event) => onChange(event.target.value)}\n >\n {!hasValue ? (\n <option value={value} disabled>\n {hasOptions ? getLanguageLabel(value) : emptyLabel}\n </option>\n ) : null}\n {groups.map((group) =>\n group.options.length ? (\n <optgroup key={group.label} label={group.label}>\n {group.options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </optgroup>\n ) : null,\n )}\n </select>\n </label>\n );\n}\n","type HtmlToken =\n | {\n type: \"tag\";\n value: string;\n }\n | {\n type: \"text\";\n value: string;\n };\n\nconst voidTags = new Set([\"br\", \"hr\", \"img\", \"input\", \"meta\", \"link\", \"area\", \"base\", \"col\", \"embed\", \"param\", \"source\", \"track\", \"wbr\"]);\n\nexport async function translatePreservingSimpleHtml(\n value: string,\n translateText: (text: string) => Promise<string>,\n): Promise<string | null> {\n const tokens = tokenizeSimpleHtml(value);\n if (!tokens || !isBalancedSimpleHtml(tokens)) {\n return null;\n }\n\n const translated: string[] = [];\n for (const token of tokens) {\n if (token.type === \"tag\") {\n translated.push(token.value);\n continue;\n }\n\n if (!token.value.trim()) {\n translated.push(token.value);\n continue;\n }\n\n const leading = token.value.match(/^\\s*/)?.[0] || \"\";\n const trailing = token.value.match(/\\s*$/)?.[0] || \"\";\n const text = token.value.trim();\n translated.push(`${leading}${await translateText(text)}${trailing}`);\n }\n\n return translated.join(\"\");\n}\n\nfunction tokenizeSimpleHtml(value: string): HtmlToken[] | null {\n const tokens: HtmlToken[] = [];\n const tagPattern = /<\\/?[^>]+>/g;\n let cursor = 0;\n let match: RegExpExecArray | null;\n\n while ((match = tagPattern.exec(value))) {\n if (match.index > cursor) {\n const text = value.slice(cursor, match.index);\n if (/[<>]/.test(text)) {\n return null;\n }\n tokens.push({ type: \"text\", value: text });\n }\n\n const tag = match[0];\n if (!/^<\\/?[A-Za-z][A-Za-z0-9:-]*(\\s+[^<>]*)?\\/?>$/.test(tag)) {\n return null;\n }\n tokens.push({ type: \"tag\", value: tag });\n cursor = match.index + tag.length;\n }\n\n if (cursor < value.length) {\n const text = value.slice(cursor);\n if (/[<>]/.test(text)) {\n return null;\n }\n tokens.push({ type: \"text\", value: text });\n }\n\n return tokens.length ? tokens : null;\n}\n\nfunction isBalancedSimpleHtml(tokens: HtmlToken[]) {\n const stack: string[] = [];\n\n for (const token of tokens) {\n if (token.type !== \"tag\") {\n continue;\n }\n\n const close = token.value.match(/^<\\/\\s*([A-Za-z][A-Za-z0-9:-]*)\\s*>$/);\n if (close) {\n const expected = stack.pop();\n if (expected !== close[1].toLowerCase()) {\n return false;\n }\n continue;\n }\n\n const open = token.value.match(/^<\\s*([A-Za-z][A-Za-z0-9:-]*)/);\n if (!open) {\n return false;\n }\n\n const tagName = open[1].toLowerCase();\n if (token.value.endsWith(\"/>\") || voidTags.has(tagName)) {\n continue;\n }\n\n stack.push(tagName);\n }\n\n return stack.length === 0;\n}\n","import {\n createDisposeRequest,\n createPreloadRequest,\n createTranslateRequest,\n type TranslationWorkerCommand,\n type TranslationWorkerResponse,\n} from \"../protocol\";\nimport type {\n TranslationEvent,\n TranslationPreloadRequest,\n TranslationTextRequest,\n TranslationTextResult,\n} from \"../types\";\nimport type { TranslationWorkerClient } from \"./client.types\";\n\ntype PendingRequest = {\n command: TranslationWorkerCommand;\n resolve: (value: unknown) => void;\n reject: (reason?: unknown) => void;\n};\n\nexport interface CreateTranslationWorkerClientOptions {\n worker?: Worker;\n workerUrl?: string | URL;\n}\n\nfunction randomRequestId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n\n return `translation-${Date.now()}-${Math.random().toString(16).slice(2)}`;\n}\n\nexport function createTranslationWorkerClient(\n options: CreateTranslationWorkerClientOptions = {},\n): TranslationWorkerClient {\n const worker = options.worker ?? createTranslationWorker(options.workerUrl);\n const listeners = new Set<(event: TranslationEvent) => void>();\n const pendingRequests = new Map<string, PendingRequest>();\n let terminated = false;\n\n const emit = (event: TranslationEvent) => {\n for (const listener of listeners) {\n listener(event);\n }\n };\n\n const failAllPending = (reason: unknown) => {\n for (const request of pendingRequests.values()) {\n request.reject(reason);\n }\n pendingRequests.clear();\n };\n\n worker.addEventListener(\"message\", (message: MessageEvent<TranslationWorkerResponse>) => {\n const payload = message.data;\n\n if (payload.kind === \"event\") {\n emit(payload.payload);\n return;\n }\n\n const pendingRequest = pendingRequests.get(payload.requestId);\n if (!pendingRequest) {\n return;\n }\n\n pendingRequests.delete(payload.requestId);\n\n if (payload.kind === \"error\") {\n const error = new Error(payload.payload.message);\n error.name = payload.payload.code;\n pendingRequest.reject(error);\n return;\n }\n\n pendingRequest.resolve(payload.payload);\n });\n\n worker.addEventListener(\"error\", (event) => {\n const error = new Error(event.message || \"The translation worker crashed.\");\n error.name = \"worker_failed\";\n emit({\n type: \"error\",\n code: \"worker_failed\",\n message: error.message,\n recoverable: false,\n });\n failAllPending(error);\n });\n\n const send = <T>(command: TranslationWorkerCommand, request: object): Promise<T> => {\n if (terminated) {\n return Promise.reject(new Error(\"The translation worker client has been terminated.\"));\n }\n\n const requestId = randomRequestId();\n const envelope =\n command === \"translate\"\n ? createTranslateRequest(requestId, (request as { payload: TranslationTextRequest }).payload)\n : command === \"dispose\"\n ? createDisposeRequest(requestId)\n : createPreloadRequest(requestId, (request as { payload: TranslationPreloadRequest }).payload);\n\n return new Promise<T>((resolve, reject) => {\n pendingRequests.set(requestId, {\n command,\n resolve: (value: unknown) => resolve(value as T),\n reject,\n });\n worker.postMessage(envelope);\n });\n };\n\n return {\n async preload(request) {\n await send<void>(\"preload\", { payload: request });\n },\n translate(request) {\n return send<TranslationTextResult>(\"translate\", { payload: request });\n },\n onEvent(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n terminate() {\n if (terminated) {\n return;\n }\n\n terminated = true;\n worker.postMessage(createDisposeRequest(randomRequestId()));\n worker.terminate();\n failAllPending(new Error(\"The translation worker client has been terminated.\"));\n },\n };\n}\n\nfunction createTranslationWorker(workerUrl?: string | URL) {\n try {\n return new Worker(resolveTranslationWorkerUrl(workerUrl), {\n type: \"module\",\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Unable to start the translation worker. If you are using @manifest-editor/translation from a bundled package, provide a public workerUrl or pass a Worker instance. ${message}`,\n );\n }\n}\n\nfunction resolveTranslationWorkerUrl(workerUrl?: string | URL) {\n if (workerUrl instanceof URL) {\n return workerUrl;\n }\n\n if (workerUrl) {\n return new URL(workerUrl, globalThis.location?.href || import.meta.url);\n }\n\n return new URL(getDefaultTranslationWorkerPath(), import.meta.url);\n}\n\nfunction getDefaultTranslationWorkerPath() {\n return \"./translation-worker.js\";\n}\n","import { Modal } from \"@manifest-editor/components\";\nimport { useEffect, useState } from \"react\";\nimport type { TranslationActionResult } from \"./types\";\n\nconst resultsEventName = \"@manifest-editor/translation:results\";\n\ntype TranslationResultsEvent = {\n actionId: string;\n result?: TranslationActionResult;\n};\n\nexport function openTranslationResults(actionId: string, result: unknown) {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(\n new CustomEvent<TranslationResultsEvent>(resultsEventName, {\n detail: {\n actionId,\n result: result as TranslationActionResult | undefined,\n },\n }),\n );\n}\n\nexport function renderTranslationResults(actionId: string) {\n return <TranslationResultsModal actionId={actionId} />;\n}\n\nfunction TranslationResultsModal({ actionId }: { actionId: string }) {\n const [activeResult, setActiveResult] = useState<TranslationActionResult | null>(null);\n\n useEffect(() => {\n const listener = (event: Event) => {\n const detail = (event as CustomEvent<TranslationResultsEvent>).detail;\n if (detail?.actionId === actionId && detail.result) {\n setActiveResult(detail.result);\n }\n };\n\n window.addEventListener(resultsEventName, listener);\n return () => window.removeEventListener(resultsEventName, listener);\n }, [actionId]);\n\n if (!activeResult) {\n return null;\n }\n\n return (\n <Modal title=\"Translation results\" onClose={() => setActiveResult(null)} className=\"max-w-4xl\">\n <div className=\"flex min-h-0 flex-col gap-4 p-4 text-sm text-zinc-700\">\n <div className=\"grid grid-cols-3 gap-2 sm:grid-cols-6\">\n <ResultStat label=\"Strings\" value={activeResult.total} />\n <ResultStat label=\"Translated\" value={activeResult.translated} />\n <ResultStat label=\"Applied\" value={activeResult.applied} />\n <ResultStat label=\"Existing\" value={activeResult.existing} />\n <ResultStat label=\"Stale\" value={activeResult.stale} />\n <ResultStat label=\"Skipped\" value={activeResult.skipped + activeResult.errors} />\n </div>\n\n {activeResult.translations.length ? (\n <div className=\"rounded border border-zinc-200\">\n <div className=\"border-b border-zinc-200 bg-zinc-50 px-3 py-2 font-medium\">Translated strings</div>\n <div className=\"max-h-64 overflow-auto\">\n {activeResult.translations.map((item) => (\n <div key={item.key} className=\"grid gap-1.5 border-b border-zinc-100 px-3 py-2.5 last:border-0\">\n <div className=\"border-l-2 border-zinc-200 pl-2.5 text-[11px] italic leading-relaxed text-zinc-400 line-clamp-2\">{item.sourceText}</div>\n <div className=\"text-xs font-medium text-zinc-900 line-clamp-2\">{item.translationText}</div>\n <div className=\"text-[11px] text-zinc-400\">{item.applied} occurrence{item.applied === 1 ? \"\" : \"s\"}</div>\n </div>\n ))}\n </div>\n </div>\n ) : null}\n\n {activeResult.skippedTargets.length ? (\n <div className=\"rounded border border-zinc-200\">\n <div className=\"border-b border-zinc-200 bg-zinc-50 px-3 py-2 font-medium\">Skipped strings</div>\n <div className=\"max-h-56 overflow-auto\">\n {activeResult.skippedTargets.map((item) => (\n <div key={`${item.key}-${item.reason}`} className=\"grid gap-1 border-b border-zinc-100 px-3 py-2 last:border-0\">\n <div className=\"line-clamp-2 font-medium text-zinc-900\">{item.sourceText}</div>\n <div className=\"text-zinc-500\">{item.reason}</div>\n </div>\n ))}\n </div>\n </div>\n ) : null}\n </div>\n </Modal>\n );\n}\n\nfunction ResultStat({ label, value }: { label: string; value: number }) {\n return (\n <div className=\"rounded border border-zinc-200 bg-zinc-50 px-2.5 py-2\">\n <div className=\"text-base font-semibold text-zinc-900\">{value}</div>\n <div className=\"text-[10px] uppercase tracking-wide text-zinc-400\">{label}</div>\n </div>\n );\n}\n","import {\n addReference,\n batchActions,\n importEntities,\n} from \"@iiif/helpers/vault/actions\";\nimport type { Vault } from \"@iiif/helpers/vault\";\nimport type { InternationalString, Reference } from \"@iiif/presentation-3\";\nimport {\n fingerprintTranslationText,\n getLanguageMapTargetText,\n getLanguageValueAt,\n normaliseTranslationText,\n} from \"./collection\";\nimport { resolveSupportedLanguage } from \"./options\";\nimport type {\n LanguageMapLike,\n TranslationOccurrence,\n TranslationPath,\n TranslationTarget,\n} from \"./types\";\n\ntype TextualBodyEntry = {\n ref: Reference<\"ContentResource\">;\n resource: any;\n choice?: Reference<\"ContentResource\">;\n};\n\nexport type TranslationWriteContext = {\n vault: Vault;\n};\n\nexport type WritableOccurrenceCheck = {\n writable: TranslationOccurrence[];\n existing: TranslationOccurrence[];\n stale: TranslationOccurrence[];\n};\n\nexport function getWritableOccurrences(\n ctx: TranslationWriteContext,\n target: TranslationTarget,\n): WritableOccurrenceCheck {\n const writable: TranslationOccurrence[] = [];\n const existing: TranslationOccurrence[] = [];\n const stale: TranslationOccurrence[] = [];\n\n for (const occurrence of target.occurrences) {\n const currentSource = readOccurrenceSourceText(ctx.vault, occurrence);\n if (\n fingerprintTranslationText(currentSource) !== occurrence.sourceFingerprint\n ) {\n stale.push(occurrence);\n continue;\n }\n\n const currentTarget = readOccurrenceExistingTargetText(\n ctx.vault,\n occurrence,\n );\n if (normaliseTranslationText(currentTarget)) {\n existing.push(occurrence);\n continue;\n }\n\n writable.push(occurrence);\n }\n\n return { writable, existing, stale };\n}\n\nexport function writeTranslationForOccurrence(\n ctx: TranslationWriteContext,\n occurrence: TranslationOccurrence,\n translationText: string,\n) {\n const text = translationText.trim();\n if (!text) {\n return false;\n }\n\n switch (occurrence.path.kind) {\n case \"resource-language-map\":\n writeResourceLanguageMap(\n ctx.vault,\n occurrence.path.resource,\n occurrence.path.property,\n occurrence,\n text,\n );\n return true;\n case \"metadata-language-map\":\n writeMetadataLanguageMap(ctx.vault, occurrence.path, occurrence, text);\n return true;\n case \"required-statement-language-map\":\n writeRequiredStatementLanguageMap(\n ctx.vault,\n occurrence.path,\n occurrence,\n text,\n );\n return true;\n case \"textual-body\":\n writeTextualBodyTranslation(ctx.vault, occurrence, text);\n return true;\n }\n}\n\nexport function readOccurrenceSourceText(\n vault: Vault,\n occurrence: TranslationOccurrence,\n) {\n if (occurrence.path.kind === \"textual-body\") {\n const body = getVaultResource(vault, occurrence.path.body);\n return typeof body?.value === \"string\" ? body.value : \"\";\n }\n\n return getLanguageValueAt(\n getLanguageMapForPath(vault, occurrence.path),\n occurrence.sourceMapLanguage,\n occurrence.sourceIndex,\n );\n}\n\nexport function readOccurrenceTargetText(\n vault: Vault,\n occurrence: TranslationOccurrence,\n) {\n if (occurrence.path.kind === \"textual-body\") {\n const targetBody = getTargetTextualBody(vault, occurrence);\n return typeof targetBody?.value === \"string\" ? targetBody.value : \"\";\n }\n\n return getLanguageValueAt(\n getLanguageMapForPath(vault, occurrence.path),\n occurrence.targetLanguage,\n occurrence.sourceIndex,\n );\n}\n\nfunction writeResourceLanguageMap(\n vault: Vault,\n resource: Reference,\n property: \"label\" | \"summary\",\n occurrence: TranslationOccurrence,\n translationText: string,\n) {\n const currentResource = getVaultResource(vault, resource);\n const next = setLanguageMapIndexedValue(\n currentResource?.[property],\n occurrence.sourceMapLanguage,\n occurrence.sourceText,\n occurrence.targetLanguage,\n occurrence.sourceIndex,\n translationText,\n );\n\n vault.modifyEntityField(resource as any, property, next);\n}\n\nfunction writeMetadataLanguageMap(\n vault: Vault,\n path: Extract<TranslationPath, { kind: \"metadata-language-map\" }>,\n occurrence: TranslationOccurrence,\n translationText: string,\n) {\n const resource = getVaultResource(vault, path.resource);\n const metadata = Array.isArray(resource?.metadata)\n ? [...resource.metadata]\n : [];\n const currentItem = metadata[path.metadataIndex] || { label: {}, value: {} };\n metadata[path.metadataIndex] = {\n ...currentItem,\n [path.field]: setLanguageMapIndexedValue(\n currentItem[path.field],\n occurrence.sourceMapLanguage,\n occurrence.sourceText,\n occurrence.targetLanguage,\n occurrence.sourceIndex,\n translationText,\n ),\n };\n\n vault.modifyEntityField(path.resource as any, \"metadata\", metadata);\n}\n\nfunction writeRequiredStatementLanguageMap(\n vault: Vault,\n path: Extract<TranslationPath, { kind: \"required-statement-language-map\" }>,\n occurrence: TranslationOccurrence,\n translationText: string,\n) {\n const resource = getVaultResource(vault, path.resource);\n const requiredStatement = resource?.requiredStatement || {};\n const next = {\n label: { none: [\"\"] },\n value: { none: [\"\"] },\n ...requiredStatement,\n [path.field]: setLanguageMapIndexedValue(\n requiredStatement[path.field],\n occurrence.sourceMapLanguage,\n occurrence.sourceText,\n occurrence.targetLanguage,\n occurrence.sourceIndex,\n translationText,\n ),\n };\n\n vault.modifyEntityField(path.resource as any, \"requiredStatement\", next);\n}\n\nfunction writeTextualBodyTranslation(\n vault: Vault,\n occurrence: TranslationOccurrence,\n translationText: string,\n) {\n if (occurrence.path.kind !== \"textual-body\") {\n return;\n }\n\n const targetBody = getTargetTextualBody(vault, occurrence);\n if (targetBody?.id) {\n vault.modifyEntityField(\n { id: targetBody.id, type: \"ContentResource\" } as any,\n \"value\",\n translationText,\n );\n vault.modifyEntityField(\n { id: targetBody.id, type: \"ContentResource\" } as any,\n \"language\",\n occurrence.targetLanguage,\n );\n return;\n }\n\n const sourceBody = getVaultResource(vault, occurrence.path.body);\n const bodyId = createTranslatedBodyId(occurrence);\n const bodyReference = {\n id: bodyId,\n type: \"ContentResource\",\n };\n\n if (occurrence.path.choice) {\n vault.dispatch(\n importEntities({\n entities: {\n ContentResource: {\n [bodyId]: {\n id: bodyId,\n type: \"TextualBody\",\n format:\n sourceBody?.format ||\n (occurrence.valueFormat === \"html\"\n ? \"text/html\"\n : \"text/plain\"),\n value: translationText,\n language: occurrence.targetLanguage,\n },\n },\n },\n }),\n );\n\n const choice = getVaultResource(vault, occurrence.path.choice);\n const items = Array.isArray(choice?.items) ? choice.items : [];\n vault.modifyEntityField(occurrence.path.choice as any, \"items\", [\n ...items,\n bodyReference,\n ]);\n return;\n }\n\n vault.dispatch(\n batchActions({\n actions: [\n importEntities({\n entities: {\n ContentResource: {\n [bodyId]: {\n id: bodyId,\n type: \"TextualBody\",\n format:\n sourceBody?.format ||\n (occurrence.valueFormat === \"html\"\n ? \"text/html\"\n : \"text/plain\"),\n value: translationText,\n language: occurrence.targetLanguage,\n },\n },\n },\n }),\n addReference({\n id: occurrence.path.annotation.id,\n type: \"Annotation\",\n key: \"body\",\n reference: bodyReference,\n }),\n ],\n }),\n );\n}\n\nfunction getLanguageMapForPath(\n vault: Vault,\n path: TranslationPath,\n): LanguageMapLike {\n if (path.kind === \"textual-body\") {\n return null;\n }\n\n const resource = getVaultResource(vault, path.resource);\n if (!resource) {\n return null;\n }\n\n switch (path.kind) {\n case \"resource-language-map\":\n return resource[path.property];\n case \"metadata-language-map\":\n return resource.metadata?.[path.metadataIndex]?.[path.field];\n case \"required-statement-language-map\":\n return resource.requiredStatement?.[path.field];\n }\n}\n\nfunction readOccurrenceExistingTargetText(\n vault: Vault,\n occurrence: TranslationOccurrence,\n) {\n if (occurrence.path.kind === \"textual-body\") {\n return readOccurrenceTargetText(vault, occurrence);\n }\n\n const languageMap = getLanguageMapForPath(vault, occurrence.path);\n return getLanguageMapTargetText(\n languageMap,\n occurrence.targetLanguage,\n occurrence.sourceIndex,\n );\n}\n\nfunction setLanguageMapIndexedValue(\n value: LanguageMapLike,\n sourceLanguage: string,\n sourceText: string,\n targetLanguage: string,\n sourceIndex: number,\n translationText: string,\n): InternationalString {\n const next = normaliseLanguageMap(value, sourceLanguage, sourceText);\n const targetValues = [...(next[targetLanguage] || [])];\n while (targetValues.length <= sourceIndex) {\n targetValues.push(\"\");\n }\n targetValues[sourceIndex] = translationText;\n next[targetLanguage] = targetValues;\n return next;\n}\n\nfunction normaliseLanguageMap(\n value: LanguageMapLike,\n sourceLanguage: string,\n sourceText: string,\n): InternationalString {\n if (!value) {\n return {\n [sourceLanguage]: [sourceText],\n };\n }\n\n if (typeof value === \"string\") {\n return {\n [sourceLanguage]: [value],\n };\n }\n\n return Object.fromEntries(\n Object.entries(value).map(([language, values]) => [\n language,\n Array.isArray(values) ? [...values] : [],\n ]),\n ) as InternationalString;\n}\n\nfunction getTargetTextualBody(vault: Vault, occurrence: TranslationOccurrence) {\n if (occurrence.path.kind !== \"textual-body\") {\n return null;\n }\n\n if (occurrence.path.targetBody) {\n const body = getVaultResource(vault, occurrence.path.targetBody);\n if (body) {\n return body;\n }\n }\n\n const sourceBodyId = occurrence.path.body.id;\n const annotation = getVaultResource(vault, occurrence.path.annotation);\n const choiceId = occurrence.path.choice?.id || \"\";\n const bodies = collectTextualBodyEntries(vault, annotation).filter(\n (entry) => (entry.choice?.id || \"\") === choiceId,\n );\n\n return (\n bodies.find(({ resource: body, ref }) => {\n if (ref.id === sourceBodyId || body?.id === sourceBodyId) {\n return false;\n }\n\n if (body?.type !== \"TextualBody\" && body?.type !== \"Text\") {\n return false;\n }\n\n return languageMatches(body.language, occurrence.targetLanguage);\n })?.resource || null\n );\n}\n\nfunction collectTextualBodyEntries(vault: Vault, annotation: any) {\n const entries: TextualBodyEntry[] = [];\n for (const ref of toReferences(annotation?.body, \"ContentResource\")) {\n collectTextualBodyEntry(\n vault,\n ref as Reference<\"ContentResource\">,\n entries,\n );\n }\n return entries.filter(({ resource }) => isTextualBody(resource));\n}\n\nfunction collectTextualBodyEntry(\n vault: Vault,\n ref: Reference<\"ContentResource\">,\n entries: TextualBodyEntry[],\n choice?: Reference<\"ContentResource\">,\n) {\n const resource = getVaultResource(vault, ref);\n if (!resource) {\n return;\n }\n\n entries.push({ ref, resource, choice });\n\n if (resource.type !== \"Choice\") {\n return;\n }\n\n for (const itemRef of toReferences(resource.items, \"ContentResource\")) {\n collectTextualBodyEntry(\n vault,\n itemRef as Reference<\"ContentResource\">,\n entries,\n ref,\n );\n }\n}\n\nfunction isTextualBody(body: any) {\n return body?.type === \"TextualBody\" || body?.type === \"Text\";\n}\n\nfunction toReferences(value: unknown, fallbackType?: string): Reference[] {\n const values = Array.isArray(value) ? value : value ? [value] : [];\n return values\n .map((item: any) => {\n if (!item?.id) {\n return null;\n }\n\n const type =\n fallbackType === \"ContentResource\" &&\n (item.type === \"TextualBody\" || item.type === \"Text\")\n ? fallbackType\n : item.type || fallbackType;\n\n return {\n id: item.id,\n type,\n } as Reference;\n })\n .filter((item): item is Reference => !!item?.id && !!item.type);\n}\n\nfunction createTranslatedBodyId(occurrence: TranslationOccurrence) {\n const annotationId =\n occurrence.path.kind === \"textual-body\"\n ? occurrence.path.annotation.id\n : occurrence.resource.id;\n const bodyId =\n occurrence.path.kind === \"textual-body\"\n ? occurrence.path.body.id\n : occurrence.id;\n return `${trimTrailingSlash(annotationId)}/translation/${encodeURIComponent(occurrence.targetLanguage)}/${hashString(bodyId)}`;\n}\n\nfunction languageMatches(value: unknown, language: string) {\n const matchesLanguage = (item: unknown) => {\n if (item === language) {\n return true;\n }\n\n return (\n typeof item === \"string\" &&\n resolveSupportedLanguage(item) === resolveSupportedLanguage(language)\n );\n };\n\n if (Array.isArray(value)) {\n return value.some(matchesLanguage);\n }\n\n return matchesLanguage(value);\n}\n\nfunction getVaultResource(vault: Vault, ref: Reference | undefined): any {\n if (!ref?.id || !ref.type) {\n return null;\n }\n\n const resource = vault.get(ref as any, { skipSelfReturn: false } as any);\n return resource && typeof resource === \"object\" ? resource : null;\n}\n\nfunction trimTrailingSlash(id: string) {\n return id.endsWith(\"/\") ? id.slice(0, -1) : id;\n}\n\nfunction hashString(value: string) {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 33) ^ value.charCodeAt(index);\n }\n return (hash >>> 0).toString(36);\n}\n","import type {\n BackgroundActionDefinition,\n BackgroundActionPlan,\n BackgroundActionRunContext,\n BackgroundActionTask,\n BackgroundActionTarget,\n} from \"@manifest-editor/shell\";\nimport {\n collectDetectedManifestLanguages,\n collectTranslationLanguageProgress,\n collectTranslationTargets,\n} from \"./collection\";\nimport {\n renderTranslationConfigModal,\n requestTranslationConfig,\n} from \"./config-modal\";\nimport { TRANSLATION_ACTION_ID, TRANSLATION_PLUGIN_ID } from \"./constants\";\nimport { translatePreservingSimpleHtml } from \"./html\";\nimport {\n getDefaultRunOptions,\n getModelSourceLanguage,\n getSupportedAvailableLanguages,\n normaliseRunOptions,\n} from \"./options\";\nimport {\n createTranslationWorkerClient,\n type TranslationEvent,\n type TranslationWorkerClient,\n} from \"./runtime\";\nimport { openTranslationResults, renderTranslationResults } from \"./results\";\nimport type {\n TranslationActionResult,\n TranslationPluginSettings,\n TranslationResourceRef,\n TranslationRunOptions,\n TranslationTarget,\n TranslationTaskResult,\n} from \"./types\";\nimport {\n getWritableOccurrences,\n writeTranslationForOccurrence,\n type TranslationWriteContext,\n} from \"./writeback\";\n\nexport type TranslationPlanData = {\n options: TranslationRunOptions;\n totalTargets: number;\n};\n\nexport type TranslationActionDependencies = {\n createClient?: (\n settings?: TranslationPluginSettings,\n ) => TranslationWorkerClient;\n collectTargets?: typeof collectTranslationTargets;\n requestConfig?: (\n ctx: BackgroundActionRunContext,\n targets: TranslationTarget[],\n defaults: TranslationRunOptions,\n ) => Promise<TranslationRunOptions | false>;\n translateHtml?: typeof translatePreservingSimpleHtml;\n};\n\nconst queuedOptions = new Map<string, TranslationRunOptions>();\n\nexport function queueTranslationRunOptions(\n instanceKey: string,\n options: Partial<TranslationRunOptions>,\n) {\n queuedOptions.set(instanceKey, normaliseRunOptions(options));\n}\n\nexport function createTranslationBackgroundAction(\n dependencies: TranslationActionDependencies = {},\n): BackgroundActionDefinition {\n const createClient =\n dependencies.createClient ||\n ((settings?: TranslationPluginSettings) =>\n createTranslationWorkerClient({\n workerUrl:\n typeof settings?.workerUrl === \"string\" && settings.workerUrl.trim()\n ? settings.workerUrl\n : undefined,\n }));\n const collectTargets =\n dependencies.collectTargets || collectTranslationTargets;\n const requestConfig = dependencies.requestConfig || defaultRequestConfig;\n const translateHtml =\n dependencies.translateHtml || translatePreservingSimpleHtml;\n let retainedClient: TranslationWorkerClient | null = null;\n let retainedWorkerUrl: string | undefined;\n\n const getEffectiveWorkerUrl = (settings?: TranslationPluginSettings) =>\n typeof settings?.workerUrl === \"string\" && settings.workerUrl.trim()\n ? settings.workerUrl.trim()\n : undefined;\n\n const terminateClient = (\n client: TranslationWorkerClient | null = retainedClient,\n ) => {\n if (!client) {\n return;\n }\n\n client.terminate();\n if (retainedClient === client) {\n retainedClient = null;\n retainedWorkerUrl = undefined;\n }\n };\n\n const getClient = (settings?: TranslationPluginSettings) => {\n const workerUrl = getEffectiveWorkerUrl(settings);\n\n if (retainedClient && retainedWorkerUrl !== workerUrl) {\n terminateClient(retainedClient);\n }\n\n if (!retainedClient) {\n retainedClient = createClient(settings);\n retainedWorkerUrl = workerUrl;\n }\n\n return retainedClient;\n };\n\n return {\n id: TRANSLATION_ACTION_ID,\n label: \"Run translation\",\n summary: \"Translate missing manifest strings with M2M100\",\n section: \"Translations\",\n order: 30,\n resourceTypes: [\"Manifest\"],\n resumable: true,\n render: (ctx) => (\n <>\n {renderTranslationConfigModal(ctx.definition.id)}\n {renderTranslationResults(ctx.definition.id)}\n </>\n ),\n onResults: (ctx) =>\n openTranslationResults(ctx.definition.id, ctx.instance?.result),\n supports: (ctx) => {\n const manifest = ctx.vault.get(ctx.target as any) as any;\n return manifest?.type === \"Manifest\";\n },\n prepare: async (ctx) => {\n const settings = ctx.plugins.getSettings<TranslationPluginSettings>(\n TRANSLATION_PLUGIN_ID,\n );\n const defaults = getDefaultRunOptions(ctx.config, settings);\n const previewTargets = collectTargets(\n ctx.vault,\n getTranslationScope(ctx, defaults),\n defaults,\n );\n const options =\n queuedOptions.get(ctx.instanceKey) ||\n (await requestConfig(ctx, previewTargets, defaults));\n queuedOptions.delete(ctx.instanceKey);\n\n if (options === false) {\n return false;\n }\n\n const normalisedOptions = normaliseRunOptions(options);\n const targets = collectTargets(\n ctx.vault,\n getTranslationScope(ctx, normalisedOptions),\n normalisedOptions,\n );\n return createTranslationPlan(targets, normalisedOptions);\n },\n run: async (ctx) => {\n const planData = getPlanData(ctx.plan);\n const options = normaliseRunOptions(\n planData?.options || getDefaultRunOptions(ctx.config),\n );\n const tasks = ctx.tasks.getAll();\n const pendingTasks = ctx.tasks.getPending();\n const writeContext: TranslationWriteContext = { vault: ctx.vault };\n\n ctx.setActionLabel(\"Running translation\");\n\n if (!tasks.length) {\n ctx.setActionStatus(\"running\", \"No translatable strings found\");\n ctx.setActionProgress({ current: 0, total: 0, label: \"No strings\" });\n return createEmptyResult(0);\n }\n\n if (pendingTasks.length) {\n const settings = ctx.plugins.getSettings<TranslationPluginSettings>(\n TRANSLATION_PLUGIN_ID,\n );\n const client = getClient(settings);\n const unsubscribe = client.onEvent((event) =>\n handleTranslationEvent(ctx, event),\n );\n const abort = () => terminateClient(client);\n\n ctx.signal.addEventListener(\"abort\", abort, { once: true });\n\n try {\n throwIfAborted(ctx.signal);\n ctx.setActionStatus(\"running\", \"Loading translation model\");\n await client.preload({ runtime: options.runtime });\n\n await ctx.tasks.runEach(\n async (task, { index, total }) => {\n throwIfAborted(ctx.signal);\n const target = task.input as TranslationTarget | undefined;\n if (!target) {\n return skippedTask(\n \"Missing translation target\",\n task.id,\n \"\",\n 0,\n 0,\n );\n }\n\n ctx.appendActionLog(`Translating ${index + 1}/${total}`, \"info\", {\n key: target.key,\n sourceLanguage: target.sourceLanguage,\n targetLanguage: target.targetLanguage,\n });\n\n const writable = getWritableOccurrences(writeContext, target);\n if (!writable.writable.length) {\n return skippedTask(\n getSkipReason(\n writable.existing.length,\n writable.stale.length,\n ),\n target.key,\n target.sourceText,\n writable.existing.length,\n writable.stale.length,\n );\n }\n\n let translationText: string | null;\n try {\n translationText = await translateTargetText(\n client,\n target,\n options,\n translateHtml,\n );\n } catch (error) {\n if (isFatalTranslationError(error)) {\n terminateClient(client);\n }\n throw error;\n }\n\n if (!translationText) {\n return skippedTask(\n \"HTML could not be parsed for safe translation\",\n target.key,\n target.sourceText,\n writable.existing.length,\n writable.stale.length,\n );\n }\n\n let applied = 0;\n let existing = writable.existing.length;\n let stale = writable.stale.length;\n\n for (const occurrence of writable.writable) {\n const latest = getWritableOccurrences(writeContext, {\n ...target,\n occurrences: [occurrence],\n });\n if (latest.stale.length) {\n stale += latest.stale.length;\n continue;\n }\n if (latest.existing.length) {\n existing += latest.existing.length;\n continue;\n }\n\n if (\n writeTranslationForOccurrence(\n writeContext,\n occurrence,\n translationText,\n )\n ) {\n applied += 1;\n }\n }\n\n if (!applied) {\n return skippedTask(\n \"No missing occurrences remained\",\n target.key,\n target.sourceText,\n existing,\n stale,\n );\n }\n\n return {\n taskStatus: \"complete\",\n statusText: `Translated ${applied} occurrence${applied === 1 ? \"\" : \"s\"}`,\n result: {\n type: \"translated\",\n key: target.key,\n sourceText: target.sourceText,\n translationText,\n applied,\n existing,\n stale,\n } satisfies TranslationTaskResult,\n };\n },\n {\n progressLabel: (_task, index, total) =>\n `Translating strings ${index + 1}/${total}`,\n },\n );\n } catch (error) {\n terminateClient(client);\n throw error;\n } finally {\n ctx.signal.removeEventListener(\"abort\", abort);\n unsubscribe();\n }\n }\n\n const result = aggregateTranslationResult(\n planData?.totalTargets || tasks.length,\n ctx.tasks.getAll(),\n );\n ctx.setActionStatus(\"running\", `Applied ${result.applied} translations`);\n ctx.setActionProgress({\n current: result.total,\n total: result.total,\n label: \"Translations complete\",\n });\n\n return result;\n },\n };\n}\n\nexport function createTranslationPlan(\n targets: TranslationTarget[],\n options: TranslationRunOptions,\n): BackgroundActionPlan {\n return {\n version: 1,\n data: {\n options: normaliseRunOptions(options),\n totalTargets: targets.length,\n } satisfies TranslationPlanData,\n tasks: targets.map((target) => {\n const existingOccurrences = target.occurrences.filter(\n (occurrence) => occurrence.status === \"existing\",\n ).length;\n const skipped = target.status !== \"missing\";\n\n return {\n id: target.key,\n label: getTaskLabel(target),\n target: toBackgroundActionTarget(target),\n input: target,\n status: skipped ? \"skipped\" : \"queued\",\n statusText: skipped ? \"Target language already exists\" : undefined,\n result: skipped\n ? ({\n type: \"skipped\",\n key: target.key,\n sourceText: target.sourceText,\n reason: \"Target language already exists\",\n existing: existingOccurrences,\n stale: 0,\n } satisfies TranslationTaskResult)\n : undefined,\n completedAt: skipped ? Date.now() : undefined,\n };\n }),\n };\n}\n\nfunction getTranslationScope(\n ctx: BackgroundActionRunContext,\n options: TranslationRunOptions,\n): TranslationResourceRef {\n if (options.currentResourceOnly && ctx.currentCanvas) {\n return {\n id: ctx.currentCanvas.id,\n type: ctx.currentCanvas.type,\n label: ctx.currentCanvas.label,\n };\n }\n\n return ctx.target;\n}\n\nasync function defaultRequestConfig(\n ctx: BackgroundActionRunContext,\n targets: TranslationTarget[],\n defaults: TranslationRunOptions,\n) {\n const detectedLanguages = collectDetectedManifestLanguages(\n ctx.vault,\n ctx.target,\n );\n const detectedLanguageCodes = detectedLanguages.map(\n (language) => language.language,\n );\n\n return requestTranslationConfig({\n actionId: ctx.definition.id,\n instanceKey: ctx.instanceKey,\n defaults,\n targets,\n availableLanguages: getSupportedAvailableLanguages(ctx.config),\n detectedLanguages,\n currentResource: ctx.currentCanvas\n ? {\n id: ctx.currentCanvas.id,\n type: ctx.currentCanvas.type,\n label: ctx.currentCanvas.label,\n }\n : undefined,\n getTargets: (options) =>\n collectTranslationTargets(\n ctx.vault,\n getTranslationScope(ctx, normaliseRunOptions(options)),\n normaliseRunOptions(options),\n ),\n getTargetLanguageProgress: (options) =>\n collectTranslationLanguageProgress(\n ctx.vault,\n getTranslationScope(ctx, normaliseRunOptions(options)),\n normaliseRunOptions(options),\n detectedLanguageCodes,\n ),\n signal: ctx.signal,\n });\n}\n\nfunction getPlanData(\n plan: BackgroundActionPlan | undefined,\n): TranslationPlanData | null {\n const data = plan?.data as TranslationPlanData | undefined;\n if (!data?.options) {\n return null;\n }\n\n return data;\n}\n\nasync function translateTargetText(\n client: TranslationWorkerClient,\n target: TranslationTarget,\n options: TranslationRunOptions,\n translateHtml: typeof translatePreservingSimpleHtml,\n) {\n const translate = async (text: string) => {\n const result = await client.translate({\n text,\n sourceLanguage: getModelSourceLanguage(target.sourceLanguage, options),\n targetLanguage: target.targetLanguage,\n runtime: options.runtime,\n });\n return result.text;\n };\n\n if (target.valueFormat === \"html\") {\n return translateHtml(target.sourceText, translate);\n }\n\n return translate(target.sourceText);\n}\n\nfunction skippedTask(\n reason: string,\n key: string,\n sourceText: string,\n existing: number,\n stale: number,\n) {\n return {\n taskStatus: \"skipped\" as const,\n statusText: reason,\n result: {\n type: \"skipped\",\n key,\n sourceText,\n reason,\n existing,\n stale,\n } satisfies TranslationTaskResult,\n };\n}\n\nfunction aggregateTranslationResult(\n total: number,\n tasks: BackgroundActionTask[],\n): TranslationActionResult {\n const result = createEmptyResult(total);\n\n for (const task of tasks) {\n const taskResult = task.result as TranslationTaskResult | undefined;\n if (taskResult?.type === \"translated\") {\n result.translated += 1;\n result.applied += taskResult.applied;\n result.existing += taskResult.existing;\n result.stale += taskResult.stale;\n result.translations.push({\n key: taskResult.key,\n sourceText: taskResult.sourceText,\n translationText: taskResult.translationText,\n applied: taskResult.applied,\n });\n continue;\n }\n\n if (taskResult?.type === \"skipped\") {\n result.skipped += 1;\n result.existing += taskResult.existing || 0;\n result.stale += taskResult.stale || 0;\n result.skippedTargets.push({\n key: taskResult.key,\n sourceText: taskResult.sourceText,\n reason: taskResult.reason,\n });\n continue;\n }\n\n if (task.status === \"error\") {\n result.errors += 1;\n result.skippedTargets.push({\n key: task.id,\n sourceText: task.label,\n reason: task.error?.message || \"Translation failed\",\n });\n }\n }\n\n return result;\n}\n\nfunction createEmptyResult(total: number): TranslationActionResult {\n return {\n total,\n translated: 0,\n applied: 0,\n skipped: 0,\n existing: 0,\n stale: 0,\n errors: 0,\n translations: [],\n skippedTargets: [],\n };\n}\n\nfunction getSkipReason(existing: number, stale: number) {\n if (stale && existing) {\n return \"Source changed or target translation already exists\";\n }\n if (stale) {\n return \"Source changed after the translation run was prepared\";\n }\n if (existing) {\n return \"Target language already exists\";\n }\n return \"No writable occurrences\";\n}\n\nfunction handleTranslationEvent(\n ctx: BackgroundActionRunContext,\n event: TranslationEvent,\n) {\n switch (event.type) {\n case \"model-progress\":\n ctx.setActionStatus(\n \"running\",\n `Loading model ${Math.round(event.progress)}% (${formatBytes(event.loaded)} / ${formatBytes(event.total)})`,\n );\n break;\n case \"model-ready\":\n ctx.setActionStatus(\n \"running\",\n `Model ready (${event.runtime.toUpperCase()})`,\n );\n break;\n case \"runtime-fallback\":\n ctx.appendActionLog(\n \"Falling back to WASM translation runtime\",\n \"warn\",\n event,\n );\n ctx.setActionStatus(\"running\", \"WebGPU unavailable; using WASM\");\n break;\n case \"translation-start\":\n ctx.setActionStatus(\n \"running\",\n `Translating ${event.sourceLanguage} to ${event.targetLanguage}`,\n );\n break;\n case \"translation-complete\":\n ctx.setActionStatus(\n \"running\",\n `Translated ${event.result.text.length} characters`,\n );\n break;\n case \"error\":\n if (!ctx.signal.aborted) {\n ctx.setActionStatus(\"running\", event.message);\n }\n break;\n }\n}\n\nfunction toBackgroundActionTarget(\n target: TranslationTarget,\n): BackgroundActionTarget {\n const occurrence = target.occurrences[0];\n const resource = occurrence?.resource;\n const label = resource?.label || target.sourceText || \"Translation string\";\n\n return {\n id: resource?.id || target.key,\n type: resource?.type || \"Manifest\",\n label,\n scope: resource?.type === \"Canvas\" ? \"canvas\" : \"root\",\n };\n}\n\nfunction getTaskLabel(target: TranslationTarget) {\n const text =\n target.normalisedSourceText || target.sourceText || \"Translation string\";\n return text.length > 80 ? `${text.slice(0, 77)}...` : text;\n}\n\nfunction throwIfAborted(signal: AbortSignal) {\n if (signal.aborted) {\n throw new Error(\"Translation cancelled.\");\n }\n}\n\nfunction isFatalTranslationError(error: unknown) {\n return (\n error instanceof Error &&\n (error.name === \"model_load_failed\" || error.name === \"worker_failed\")\n );\n}\n\nfunction formatBytes(value: number) {\n if (!value) {\n return \"0 MB\";\n }\n\n return `${Math.round(value / 1024 / 1024)} MB`;\n}\n","import { getAvailableLanguagesFromResource } from \"@iiif/helpers/i18n\";\nimport type {\n BackgroundActionDefinition,\n BackgroundActionPlan,\n BackgroundActionRunContext,\n BackgroundActionTask,\n ManifestEditorTag,\n} from \"@manifest-editor/shell\";\nimport { TRANSLATION_LANGUAGE_TAG_ACTION_ID } from \"./constants\";\nimport { resolveSourceLanguage } from \"./options\";\n\nexport const TRANSLATION_LANGUAGE_TAG_TYPE = \"language\";\n\nexport type CanvasLanguageTagResult = {\n canvasId: string;\n canvasLabel: string;\n language: string;\n label: string;\n count: number;\n detectedLanguages: string[];\n};\n\nexport type CanvasLanguageTagSkip = {\n canvasId: string;\n canvasLabel: string;\n reason: string;\n};\n\nexport type TranslationLanguageTagActionResult = {\n total: number;\n tagged: number;\n skipped: number;\n counts: Record<string, number>;\n tags: CanvasLanguageTagResult[];\n skippedCanvases: CanvasLanguageTagSkip[];\n};\n\ntype CanvasLanguageTagTaskInput = {\n canvasId: string;\n canvasLabel: string;\n};\n\ntype CanvasLanguageTagTaskResult =\n | {\n type: \"tagged\";\n tag: CanvasLanguageTagResult;\n }\n | {\n type: \"skipped\";\n skip: CanvasLanguageTagSkip;\n };\n\ntype DetectedCanvasLanguage = {\n language: string;\n count: number;\n iiifLanguages: string[];\n};\n\nconst LANGUAGE_TAG_PALETTE = [\n { backgroundColor: \"#1d4ed8\", textColor: \"#ffffff\" },\n { backgroundColor: \"#047857\", textColor: \"#ffffff\" },\n { backgroundColor: \"#b45309\", textColor: \"#ffffff\" },\n { backgroundColor: \"#7c3aed\", textColor: \"#ffffff\" },\n { backgroundColor: \"#be123c\", textColor: \"#ffffff\" },\n { backgroundColor: \"#0f766e\", textColor: \"#ffffff\" },\n { backgroundColor: \"#4338ca\", textColor: \"#ffffff\" },\n { backgroundColor: \"#a16207\", textColor: \"#ffffff\" },\n];\n\nexport function createTranslationLanguageTagsBackgroundAction(): BackgroundActionDefinition {\n return {\n id: TRANSLATION_LANGUAGE_TAG_ACTION_ID,\n label: \"Tag with languages\",\n summary: \"Tag each canvas with its detected language\",\n section: \"Translations\",\n order: 35,\n resourceTypes: [\"Manifest\"],\n resumable: true,\n supports: (ctx) => {\n const manifest = ctx.vault.get(ctx.target as any) as any;\n return manifest?.type === \"Manifest\" && !!manifest?.items?.length;\n },\n prepare: (ctx) => createLanguageTagPlan(getManifestCanvases(ctx)),\n run: async (ctx) => {\n const tasks = ctx.tasks.getAll();\n const pendingTasks = ctx.tasks.getPending();\n\n ctx.setActionLabel(\"Tagging canvas languages\");\n\n if (!tasks.length) {\n const result = createEmptyResult(0);\n ctx.setActionStatus(\"running\", \"No canvases to tag\");\n ctx.setActionProgress({\n current: 0,\n total: 0,\n label: \"No canvases\",\n });\n ctx.setResult(result);\n ctx.setResultsAvailable(false);\n return;\n }\n\n if (pendingTasks.length) {\n ctx.canvasProgress.setStatuses(\n pendingTasks\n .map((task) => task.target)\n .filter(\n (target): target is NonNullable<BackgroundActionTask[\"target\"]> => !!target && target.type === \"Canvas\",\n ),\n \"queued\",\n );\n\n await ctx.tasks.runEach(\n async (task, { index, total }) => {\n throwIfAborted(ctx.signal);\n\n const input = task.input as CanvasLanguageTagTaskInput | undefined;\n const canvasId = task.target?.id || input?.canvasId || task.id;\n const canvas = getCanvasById(ctx, canvasId);\n const canvasLabel = getCanvasLabel(canvas, input?.canvasLabel || canvasId);\n\n ctx.appendActionLog(`Tagging language ${index + 1}/${total}`, \"info\", {\n canvasId,\n current: index + 1,\n total,\n });\n\n if (!canvas) {\n const skip = {\n canvasId,\n canvasLabel,\n reason: \"Canvas not found\",\n };\n ctx.appendActionLog(\"Skipped language tag\", \"warn\", skip);\n return skippedTask(skip);\n }\n\n const detected = getCanvasAvailableLanguages(ctx, canvas);\n const primary = selectPrimaryDetectedLanguage(detected);\n\n if (!primary) {\n ctx.tags.removeTag({ id: canvasId, type: \"Canvas\" }, TRANSLATION_LANGUAGE_TAG_TYPE);\n const skip = {\n canvasId,\n canvasLabel,\n reason: \"No supported language detected\",\n };\n ctx.appendActionLog(\"Skipped language tag\", \"warn\", skip);\n return skippedTask(skip);\n }\n\n const tag = createLanguageTag(primary.language);\n ctx.tags.upsertTag({ id: canvasId, type: \"Canvas\" }, tag);\n\n const result = {\n canvasId,\n canvasLabel,\n language: primary.language,\n label: tag.label,\n count: primary.count,\n detectedLanguages: detected.map((language) => language.language),\n };\n\n ctx.appendActionLog(\"Tagged canvas language\", \"info\", {\n canvasId,\n language: primary.language,\n label: tag.label,\n });\n\n return {\n taskStatus: \"complete\",\n statusText: `Tagged as ${tag.label}`,\n result: {\n type: \"tagged\",\n tag: result,\n } satisfies CanvasLanguageTagTaskResult,\n };\n },\n {\n progressLabel: (_task, index, total) => `Tagging languages ${index + 1}/${total}`,\n },\n );\n }\n\n const result = aggregateLanguageTagResult(ctx.tasks.getAll());\n ctx.setActionStatus(\"running\", `Tagged ${result.tagged}/${result.total} canvases`);\n ctx.setActionProgress({\n current: result.total,\n total: result.total,\n label: \"Language tagging complete\",\n });\n ctx.appendActionLog(\"Language tagging complete\", \"info\", {\n total: result.total,\n tagged: result.tagged,\n skipped: result.skipped,\n counts: result.counts,\n });\n ctx.setResult(result);\n ctx.setResultsAvailable(false);\n },\n };\n}\n\nexport function createLanguageTag(language: string): ManifestEditorTag {\n const colours = getLanguageTagColours(language);\n return {\n type: TRANSLATION_LANGUAGE_TAG_TYPE,\n id: language,\n label: language,\n backgroundColor: colours.backgroundColor,\n textColor: colours.textColor,\n };\n}\n\nexport function selectPrimaryDetectedLanguage(languages: DetectedCanvasLanguage[]): DetectedCanvasLanguage | null {\n return languages[0] || null;\n}\n\nfunction createLanguageTagPlan(canvases: any[]): BackgroundActionPlan {\n return {\n version: 1,\n tasks: canvases.map((canvas, index) => {\n const canvasId = canvas?.id || `canvas-${index + 1}`;\n const canvasLabel = getCanvasLabel(canvas, canvasId);\n return {\n id: `canvas:${canvasId}`,\n label: canvasLabel,\n target: {\n id: canvasId,\n type: \"Canvas\",\n label: canvasLabel,\n scope: \"canvas\",\n },\n input: {\n canvasId,\n canvasLabel,\n } satisfies CanvasLanguageTagTaskInput,\n status: \"queued\",\n };\n }),\n };\n}\n\nfunction skippedTask(skip: CanvasLanguageTagSkip) {\n return {\n taskStatus: \"skipped\" as const,\n statusText: skip.reason,\n result: {\n type: \"skipped\",\n skip,\n } satisfies CanvasLanguageTagTaskResult,\n };\n}\n\nfunction createEmptyResult(total: number): TranslationLanguageTagActionResult {\n return {\n total,\n tagged: 0,\n skipped: 0,\n counts: {},\n tags: [],\n skippedCanvases: [],\n };\n}\n\nfunction aggregateLanguageTagResult(tasks: BackgroundActionTask[]): TranslationLanguageTagActionResult {\n const result = createEmptyResult(tasks.length);\n\n for (const task of tasks) {\n const taskResult = task.result as CanvasLanguageTagTaskResult | undefined;\n if (taskResult?.type === \"tagged\") {\n result.tags.push(taskResult.tag);\n result.counts[taskResult.tag.language] = (result.counts[taskResult.tag.language] || 0) + 1;\n continue;\n }\n\n if (taskResult?.type === \"skipped\") {\n result.skippedCanvases.push(taskResult.skip);\n continue;\n }\n\n if (task.status === \"error\") {\n result.skippedCanvases.push({\n canvasId: task.target?.id || task.id,\n canvasLabel: task.label || task.target?.id || task.id,\n reason: task.error?.message || \"Language tagging failed\",\n });\n }\n }\n\n result.tagged = result.tags.length;\n result.skipped = result.skippedCanvases.length;\n return result;\n}\n\nfunction getManifestCanvases(ctx: BackgroundActionRunContext) {\n const manifest = ctx.vault.get(ctx.target as any) as any;\n return manifest?.items ? (ctx.vault.get(manifest.items) || []).filter(Boolean) : [];\n}\n\nfunction getCanvasById(ctx: BackgroundActionRunContext, canvasId: string) {\n return ctx.vault.get({ id: canvasId, type: \"Canvas\" } as any) as any;\n}\n\nfunction getCanvasAvailableLanguages(ctx: BackgroundActionRunContext, canvas: any): DetectedCanvasLanguage[] {\n const resource = getCanvasPresentationResource(ctx, canvas) || canvas;\n const languages = getAvailableCanvasLanguages(resource);\n const detected: DetectedCanvasLanguage[] = [];\n const seen = new Set<string>();\n\n for (const language of languages) {\n const rawLanguage = typeof language === \"string\" ? language : \"\";\n const resolved = resolveSourceLanguage(rawLanguage);\n if (!resolved || seen.has(resolved)) {\n continue;\n }\n\n seen.add(resolved);\n detected.push({\n language: resolved,\n count: 1,\n iiifLanguages: [rawLanguage],\n });\n }\n\n return sortDetectedCanvasLanguages(detected, resource);\n}\n\nfunction getAvailableCanvasLanguages(resource: any) {\n const languages = new Set<string>();\n\n for (const language of getAvailableLanguagesFromResource(resource as any)) {\n if (typeof language === \"string\") {\n languages.add(language);\n }\n }\n\n addLanguageMapLanguageCodes(languages, resource?.label);\n addLanguageMapLanguageCodes(languages, resource?.summary);\n\n const requiredStatement = resource?.requiredStatement;\n if (requiredStatement && !Array.isArray(requiredStatement)) {\n addLanguageMapLanguageCodes(languages, requiredStatement.label);\n addLanguageMapLanguageCodes(languages, requiredStatement.value);\n }\n\n if (Array.isArray(resource?.metadata)) {\n for (const item of resource.metadata) {\n addLanguageMapLanguageCodes(languages, item?.label);\n addLanguageMapLanguageCodes(languages, item?.value);\n }\n }\n\n return Array.from(languages);\n}\n\nfunction getCanvasPresentationResource(ctx: BackgroundActionRunContext, canvas: any) {\n if (!canvas?.id) {\n return null;\n }\n\n try {\n return ctx.vault.toPresentation3({ id: canvas.id, type: \"Canvas\" } as any);\n } catch {\n return null;\n }\n}\n\nfunction sortDetectedCanvasLanguages(detected: DetectedCanvasLanguage[], resource: any) {\n if (detected.length < 2 || hasNestedCanvasContent(resource)) {\n return detected;\n }\n\n const scores = scoreOwnLanguageMaps(resource);\n\n const scored = detected.map((language) => ({\n ...language,\n count: scores.get(language.language) || language.count,\n }));\n\n return scored.sort((a, b) => {\n const score = (scores.get(b.language) || 0) - (scores.get(a.language) || 0);\n if (score !== 0) {\n return score;\n }\n\n return (\n detected.findIndex((language) => language.language === a.language) -\n detected.findIndex((language) => language.language === b.language)\n );\n });\n}\n\nfunction hasNestedCanvasContent(resource: any) {\n return !!(\n (Array.isArray(resource?.items) && resource.items.length) ||\n (Array.isArray(resource?.annotations) && resource.annotations.length)\n );\n}\n\nfunction scoreOwnLanguageMaps(resource: any) {\n const scores = new Map<string, number>();\n\n addLanguageMapScores(scores, resource?.label);\n addLanguageMapScores(scores, resource?.summary);\n\n const requiredStatement = resource?.requiredStatement;\n if (requiredStatement && !Array.isArray(requiredStatement)) {\n addLanguageMapScores(scores, requiredStatement.label);\n addLanguageMapScores(scores, requiredStatement.value);\n }\n\n if (Array.isArray(resource?.metadata)) {\n for (const item of resource.metadata) {\n addLanguageMapScores(scores, item?.label);\n addLanguageMapScores(scores, item?.value);\n }\n }\n\n return scores;\n}\n\nfunction addLanguageMapScores(scores: Map<string, number>, value: unknown) {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return;\n }\n\n for (const [language, values] of Object.entries(value)) {\n const resolved = resolveSourceLanguage(language);\n if (!resolved || !Array.isArray(values)) {\n continue;\n }\n\n const count = values.filter((item) => typeof item === \"string\" && item.trim()).length;\n if (count) {\n scores.set(resolved, (scores.get(resolved) || 0) + count);\n }\n }\n}\n\nfunction addLanguageMapLanguageCodes(languages: Set<string>, value: unknown) {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return;\n }\n\n for (const [language, values] of Object.entries(value)) {\n if (Array.isArray(values) && values.some((item) => typeof item === \"string\" && item.trim())) {\n languages.add(language);\n }\n }\n}\n\nfunction getCanvasLabel(canvas: any, fallback: string) {\n const label = canvas?.label;\n if (!label) {\n return fallback;\n }\n\n if (typeof label === \"string\") {\n return label;\n }\n\n const englishLabel = Array.isArray(label.en) ? label.en[0] : undefined;\n if (englishLabel) {\n return englishLabel;\n }\n\n const firstLanguage = Object.keys(label)[0];\n const firstValue = firstLanguage && Array.isArray(label[firstLanguage]) ? label[firstLanguage][0] : undefined;\n return firstValue || fallback;\n}\n\nfunction getLanguageTagColours(language: string) {\n const index = Math.abs(hashString(language)) % LANGUAGE_TAG_PALETTE.length;\n return LANGUAGE_TAG_PALETTE[index] || LANGUAGE_TAG_PALETTE[0]!;\n}\n\nfunction hashString(value: string) {\n let hash = 0;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash << 5) - hash + value.charCodeAt(index);\n hash |= 0;\n }\n return hash;\n}\n\nfunction throwIfAborted(signal: AbortSignal) {\n if (signal.aborted) {\n throw new Error(\"Language tagging cancelled.\");\n }\n}\n","import type { Reference } from \"@iiif/presentation-3\";\nimport { Sidebar, SidebarContent, SidebarHeader } from \"@manifest-editor/components\";\nimport {\n type LayoutPanel,\n runBackgroundAction,\n useAppResource,\n useAvailableBackgroundActions,\n useBackgroundActionsStoreApi,\n useConfig,\n useEditingResource,\n useEditingResourceStack,\n usePluginRuntimeApi,\n} from \"@manifest-editor/shell\";\nimport { type SVGProps, useEffect, useMemo, useState } from \"react\";\nimport { useVault, useVaultSelector } from \"react-iiif-vault\";\nimport { queueTranslationRunOptions } from \"./background-action\";\nimport {\n collectDetectedManifestLanguages,\n collectTranslationLanguageProgress,\n collectTranslationTargets,\n type TranslationLanguageProgress,\n} from \"./collection\";\nimport {\n TRANSLATION_ACTION_ID,\n TRANSLATION_PLUGIN_ID,\n TRANSLATIONS_LEFT_PANEL_ID,\n} from \"./constants\";\nimport { getLanguageLabel, getLanguageProgressLabel, M2M100_LANGUAGES } from \"./languages\";\nimport {\n getDefaultRunOptions,\n getModelSourceLanguage,\n isNoLanguageCode,\n normaliseRunOptions,\n resolveSupportedLanguage,\n} from \"./options\";\nimport type {\n TranslationContentFilters,\n TranslationOccurrence,\n TranslationPluginSettings,\n TranslationRunOptions,\n TranslationStatus,\n TranslationTarget,\n} from \"./types\";\nimport { writeTranslationForOccurrence } from \"./writeback\";\n\nexport const translationsPanel: LayoutPanel = {\n id: TRANSLATIONS_LEFT_PANEL_ID,\n label: \"Translations\",\n icon: <TranslationsIcon />,\n render: () => <TranslationsPanel />,\n};\n\nexport function TranslationsIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n d=\"M12.87 15.07l-2.54-2.51l.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v1.99h11.17A15.9 15.9 0 0 1 9 11.35A15.34 15.34 0 0 1 6.69 8h-2c.7 1.56 1.66 3.02 2.81 4.28l-5.09 5.02L3.83 18L9 12.9l3.22 3.22l.65-1.05M18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12m-2.62 7l1.62-4.33L19.12 17h-3.24z\"\n />\n </svg>\n );\n}\n\ntype FilterKey = \"all\" | \"current\" | \"missing\" | \"existing\" | \"stale\";\ntype LanguageOption = {\n value: string;\n label: string;\n};\ntype LanguageOptionGroup = {\n label: string;\n options: LanguageOption[];\n};\n\nfunction TranslationsPanel() {\n const config = useConfig();\n const rootResource = useAppResource();\n const currentResource = useCurrentTranslationResource(rootResource as Reference);\n const plugins = usePluginRuntimeApi();\n const settings = plugins.getSettings<TranslationPluginSettings>(TRANSLATION_PLUGIN_ID);\n const defaults = useMemo(() => getDefaultRunOptions(config, settings), [config, settings]);\n const [options, setOptions] = useState<TranslationRunOptions>(defaults);\n const [activeFilter, setActiveFilter] = useState<FilterKey>(\"missing\");\n\n useEffect(() => {\n setOptions(defaults);\n }, [defaults.sourceLanguage, defaults.targetLanguage, defaults.runtime]);\n\n const detectedLanguages = useVaultSelector(\n (_state, vault) => collectDetectedManifestLanguages(vault, rootResource as any),\n [rootResource.id, rootResource.type],\n );\n const detectedLanguageCodes = useMemo(\n () => detectedLanguages.map((language) => language.language),\n [detectedLanguages],\n );\n const detectedLanguageKey = detectedLanguageCodes.join(\"|\");\n\n useEffect(() => {\n if (!detectedLanguageCodes.length || detectedLanguageCodes.includes(options.sourceLanguage)) {\n return;\n }\n\n setOptions((current) => {\n if (detectedLanguageCodes.includes(current.sourceLanguage)) {\n return current;\n }\n\n return normaliseRunOptions({\n ...current,\n sourceLanguage: detectedLanguageCodes[0],\n });\n });\n }, [detectedLanguageKey, options.sourceLanguage]);\n\n const targets = useVaultSelector(\n (_state, vault) => collectTranslationTargets(vault, rootResource as any, options),\n [\n rootResource.id,\n rootResource.type,\n options.sourceLanguage,\n options.targetLanguage,\n options.runtime,\n options.contentFilters.annotationBodies,\n options.contentFilters.canvasLabels,\n ],\n );\n const currentResourceTargets = useVaultSelector(\n (_state, vault) => collectTranslationTargets(vault, currentResource, options),\n [\n currentResource.id,\n currentResource.type,\n options.sourceLanguage,\n options.targetLanguage,\n options.runtime,\n options.contentFilters.annotationBodies,\n options.contentFilters.canvasLabels,\n ],\n );\n const targetLanguageProgress = useVaultSelector(\n (_state, vault) => collectTranslationLanguageProgress(vault, rootResource as any, options, detectedLanguageCodes),\n [\n rootResource.id,\n rootResource.type,\n options.sourceLanguage,\n options.runtime,\n options.contentFilters.annotationBodies,\n options.contentFilters.canvasLabels,\n detectedLanguageKey,\n ],\n );\n const vault = useVault();\n const action = useTranslationAction();\n const store = useBackgroundActionsStoreApi();\n const sourceLanguageGroups = useMemo(\n () => [\n {\n label: \"Detected in manifest\",\n options: detectedLanguages.map((language) => ({\n value: language.language,\n label: getLanguageLabel(language.language),\n })),\n },\n ],\n [detectedLanguages],\n );\n const targetLanguageGroups = useMemo(\n () => createTargetLanguageGroups(targetLanguageProgress),\n [targetLanguageProgress],\n );\n const unsupportedConfiguredLanguages = useMemo(\n () =>\n (config.i18n?.availableLanguages || []).filter(\n (language) => !resolveSupportedLanguage(language) && !isNoLanguageCode(language),\n ),\n [config.i18n?.availableLanguages],\n );\n const counts = useMemo(() => getStatusCounts(targets), [targets]);\n const currentResourceCounts = useMemo(() => getStatusCounts(currentResourceTargets), [currentResourceTargets]);\n const busy = action?.instance?.status === \"preparing\" || action?.instance?.status === \"running\";\n const sourceMatchesTarget = getModelSourceLanguage(options.sourceLanguage, options) === options.targetLanguage;\n const canRun =\n !!action &&\n !busy &&\n detectedLanguageCodes.length > 0 &&\n !sourceMatchesTarget &&\n counts.missing > 0;\n\n const updateOptions = (patch: Partial<TranslationRunOptions>) => {\n setOptions((current) => normaliseRunOptions({ ...current, ...patch }));\n };\n const updateContentFilter = (filter: keyof TranslationContentFilters, enabled: boolean) => {\n setOptions((current) =>\n normaliseRunOptions({\n ...current,\n contentFilters: {\n ...current.contentFilters,\n [filter]: enabled,\n },\n }),\n );\n };\n\n const runTranslation = () => {\n if (!action || !canRun) return;\n queueTranslationRunOptions(action.instanceKey, options);\n void runBackgroundAction({ store, context: action.context });\n };\n\n const filteredTargets = useMemo(() => {\n if (activeFilter === \"current\") return currentResourceTargets;\n if (activeFilter === \"all\") return targets;\n return targets.filter((t) => t.status === activeFilter);\n }, [targets, currentResourceTargets, activeFilter]);\n\n const filterTabs: Array<{\n key: FilterKey;\n label: string;\n count: number;\n title?: string;\n }> = [\n { key: \"all\", label: \"All\", count: targets.length },\n {\n key: \"current\",\n label: \"Current resource\",\n count: currentResourceCounts.total,\n title: `Current ${currentResource.type.toLowerCase()}`,\n },\n { key: \"missing\", label: \"Missing\", count: counts.missing },\n { key: \"existing\", label: \"Done\", count: counts.existing },\n { key: \"stale\", label: \"Stale\", count: counts.stale },\n ];\n\n return (\n <Sidebar>\n <SidebarHeader title=\"Translations\" />\n <SidebarContent className=\"flex min-h-0 flex-col gap-0 p-0\">\n {/* Controls */}\n <div className=\"flex flex-col gap-2 border-b border-zinc-100 p-3\">\n <div className=\"flex items-end gap-1.5\">\n <CompactLanguageSelect\n label=\"From\"\n value={options.sourceLanguage}\n groups={sourceLanguageGroups}\n emptyLabel=\"No detected languages\"\n onChange={(sourceLanguage) => updateOptions({ sourceLanguage })}\n />\n <span className=\"mb-[7px] text-zinc-300 select-none\">→</span>\n <CompactLanguageSelect\n label=\"To\"\n value={options.targetLanguage}\n groups={targetLanguageGroups}\n onChange={(targetLanguage) => updateOptions({ targetLanguage })}\n />\n <label className=\"grid shrink-0 gap-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-zinc-400\">Mode</span>\n <select\n className=\"rounded border border-zinc-200 bg-white py-[5px] px-2 text-xs text-zinc-700 focus:border-me-primary-500 focus:outline-none focus:ring-2 focus:ring-me-primary-500/20\"\n value={options.runtime}\n onChange={(event) =>\n updateOptions({\n runtime: event.target.value as TranslationRunOptions[\"runtime\"],\n })\n }\n >\n <option value=\"auto\">Auto</option>\n <option value=\"webgpu\">WebGPU</option>\n <option value=\"wasm\">WASM</option>\n </select>\n </label>\n </div>\n\n {unsupportedConfiguredLanguages.length ? (\n <div className=\"rounded border border-amber-200 bg-amber-50 px-2.5 py-2 text-xs text-amber-800\">\n Unsupported languages: {unsupportedConfiguredLanguages.join(\", \")}\n </div>\n ) : null}\n\n {detectedLanguageCodes.length === 0 ? (\n <div className=\"rounded border border-amber-200 bg-amber-50 px-2.5 py-2 text-xs text-amber-800\">\n No supported IIIF languages were detected in this manifest.\n </div>\n ) : null}\n\n {sourceMatchesTarget ? (\n <div className=\"rounded border border-amber-200 bg-amber-50 px-2.5 py-2 text-xs text-amber-800\">\n Choose different source and target languages.\n </div>\n ) : null}\n\n {/* Stats + Run */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"min-w-[7rem] flex-1 text-xs text-zinc-500\">\n {counts.missing > 0 && (\n <>\n <span className=\"font-semibold text-amber-600\">{counts.missing}</span> missing\n </>\n )}\n {counts.missing > 0 && counts.existing > 0 && <span className=\"text-zinc-300\"> · </span>}\n {counts.existing > 0 && (\n <>\n <span className=\"font-semibold text-green-600\">{counts.existing}</span> done\n </>\n )}\n {counts.stale > 0 && (\n <>\n <span className=\"text-zinc-300\"> · </span>\n <span className=\"font-semibold text-red-500\">{counts.stale}</span> stale\n </>\n )}\n {targets.length === 0 && <span className=\"text-zinc-400\">No strings found</span>}\n </div>\n <button\n type=\"button\"\n className=\"flex shrink-0 items-center gap-1.5 rounded border border-me-primary-500 bg-me-primary-500 px-2.5 py-1.5 text-xs font-medium text-white transition-opacity disabled:cursor-not-allowed disabled:opacity-40\"\n disabled={!canRun}\n onClick={runTranslation}\n title={\n canRun ? `Translate ${counts.missing} missing string${counts.missing === 1 ? \"\" : \"s\"}` : undefined\n }\n >\n {busy ? (\n <>\n <SpinnerIcon className=\"h-3 w-3 animate-spin\" />\n Running…\n </>\n ) : (\n <>\n <PlayIcon className=\"h-3 w-3\" />\n Translate\n </>\n )}\n </button>\n <TranslationFiltersMenu filters={options.contentFilters} onChange={updateContentFilter} />\n </div>\n </div>\n\n {/* Filter tabs */}\n {targets.length > 0 && (\n <div className=\"flex shrink-0 overflow-x-auto border-b border-zinc-100 bg-zinc-50/50\">\n {filterTabs\n .filter((tab) => tab.key === \"all\" || tab.key === \"current\" || tab.count > 0)\n .map((tab) => (\n <button\n key={tab.key}\n type=\"button\"\n className={`flex shrink-0 items-center gap-1 whitespace-nowrap px-3 py-2 text-xs font-medium transition-colors ${\n activeFilter === tab.key\n ? \"-mb-px border-b-2 border-me-primary-500 text-me-primary-600\"\n : \"text-zinc-500 hover:text-zinc-700\"\n }`}\n title={tab.title}\n onClick={() => setActiveFilter(tab.key)}\n >\n {tab.label}\n <span className={`text-[10px] ${activeFilter === tab.key ? \"text-me-primary-400\" : \"text-zinc-400\"}`}>\n {tab.count}\n </span>\n </button>\n ))}\n </div>\n )}\n\n {/* Translation list */}\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {filteredTargets.length ? (\n filteredTargets.map((target) => (\n <TranslationTargetRow\n key={target.key}\n target={target}\n onSave={(value) => {\n for (const occurrence of target.occurrences) {\n writeTranslationForOccurrence({ vault }, occurrence, value);\n }\n }}\n />\n ))\n ) : (\n <div className=\"px-4 py-8 text-center text-xs text-zinc-400\">\n {targets.length === 0\n ? \"No translatable strings found.\"\n : activeFilter === \"current\"\n ? \"No current resource strings.\"\n : `No ${activeFilter} strings.`}\n </div>\n )}\n </div>\n </SidebarContent>\n </Sidebar>\n );\n}\n\nfunction useTranslationAction() {\n return useAvailableAction(TRANSLATION_ACTION_ID);\n}\n\nfunction useAvailableAction(actionId: string) {\n const groups = useAvailableBackgroundActions();\n return useMemo(\n () => groups.flatMap((group) => group.actions).find((action) => action.definition.id === actionId) || null,\n [groups, actionId],\n );\n}\n\nfunction useCurrentTranslationResource(rootResource: Reference): Reference {\n const current = useEditingResource();\n const stack = useEditingResourceStack();\n\n return useMemo(() => {\n const resources = [current, ...stack]\n .map((item) => item?.resource?.source)\n .filter((resource): resource is Reference => {\n return !!resource?.id && !!resource.type;\n });\n const canvas = resources.find((resource) => resource.type === \"Canvas\");\n const manifest = resources.find((resource) => resource.type === \"Manifest\");\n const selected = canvas || manifest || rootResource;\n\n return {\n id: selected.id,\n type: selected.type,\n } as Reference;\n }, [current, stack, rootResource]);\n}\n\nfunction TranslationTargetRow({ target, onSave }: { target: TranslationTarget; onSave: (value: string) => void }) {\n const firstOccurrence = target.occurrences[0];\n const targetText = getTargetText(target.occurrences);\n const [draft, setDraft] = useState(targetText);\n const isDone = target.status === \"existing\" || target.status === \"suggested\";\n const [expanded, setExpanded] = useState(!isDone);\n\n useEffect(() => {\n setDraft(targetText);\n }, [targetText]);\n\n const save = () => {\n if (draft.trim() !== targetText.trim()) {\n onSave(draft);\n }\n };\n\n return (\n <div className={`border-b border-zinc-100 last:border-0 ${isDone && !expanded ? \"opacity-60\" : \"\"}`}>\n {/* Header — always visible, click to expand/collapse */}\n <button\n type=\"button\"\n className=\"flex w-full min-w-0 items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-zinc-50/80 focus:outline-none\"\n onClick={() => setExpanded((v) => !v)}\n >\n <div className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-xs font-semibold text-zinc-800\">\n {firstOccurrence?.resource.label || firstOccurrence?.resource.id}\n </span>\n <span className=\"text-[11px] text-zinc-400\">\n {firstOccurrence?.propertyLabel || \"String\"}\n {target.occurrences.length > 1 ? ` · ${target.occurrences.length}×` : \"\"}\n </span>\n </div>\n <StatusDot status={target.status} />\n <ChevronIcon expanded={expanded} />\n </button>\n\n {/* Expandable body */}\n {expanded && (\n <div className=\"px-3 pb-3\">\n {/* Source text — clearly labelled, easy to read */}\n <div className=\"mb-2 rounded border border-zinc-100 bg-zinc-50 px-2.5 py-2 text-xs leading-relaxed text-zinc-700\">\n <div className=\"mb-1 text-[10px] font-semibold uppercase tracking-widest text-me-primary-400\">Source</div>\n {target.sourceText}\n </div>\n <textarea\n className=\"w-full min-h-[2.5rem] [field-sizing:content] rounded border border-zinc-200 bg-white px-2 py-1.5 text-xs text-zinc-900 transition-colors placeholder:text-zinc-300 focus:border-me-primary-500 focus:outline-none focus:ring-2 focus:ring-me-primary-500/20\"\n value={draft}\n placeholder={`${getLanguageLabel(target.targetLanguage)} translation…`}\n onChange={(event) => setDraft(event.target.value)}\n onBlur={save}\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction TranslationFiltersMenu({\n filters,\n onChange,\n}: {\n filters: TranslationContentFilters;\n onChange: (filter: keyof TranslationContentFilters, enabled: boolean) => void;\n}) {\n return (\n <details className=\"relative shrink-0\">\n <summary className=\"cursor-pointer list-none rounded border border-zinc-200 bg-white px-2.5 py-1.5 text-xs font-medium text-zinc-600 hover:border-zinc-300\">\n Filters\n </summary>\n <div className=\"absolute right-0 z-20 mt-1 grid w-48 gap-2 rounded border border-zinc-200 bg-white p-2.5 text-xs text-zinc-700 shadow-lg\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n className=\"h-3.5 w-3.5 rounded border-zinc-300\"\n checked={filters.annotationBodies}\n onChange={(event) => onChange(\"annotationBodies\", event.currentTarget.checked)}\n />\n Annotation bodies\n </label>\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n className=\"h-3.5 w-3.5 rounded border-zinc-300\"\n checked={filters.canvasLabels}\n onChange={(event) => onChange(\"canvasLabels\", event.currentTarget.checked)}\n />\n Canvas labels\n </label>\n </div>\n </details>\n );\n}\n\nfunction createTargetLanguageGroups(progress: TranslationLanguageProgress[]): LanguageOptionGroup[] {\n const detectedLanguageCodes = new Set(progress.map((item) => item.language));\n const groups: LanguageOptionGroup[] = [];\n\n if (progress.length) {\n groups.push({\n label: \"Detected in manifest\",\n options: progress.map((item) => ({\n value: item.language,\n label: `${getLanguageLabel(item.language)} (${getLanguageProgressLabel(item)})`,\n })),\n });\n }\n\n groups.push({\n label: \"All languages\",\n options: M2M100_LANGUAGES.filter((language) => !detectedLanguageCodes.has(language.code)).map((language) => ({\n value: language.code,\n label: language.label,\n })),\n });\n\n return groups;\n}\n\nfunction CompactLanguageSelect({\n label,\n value,\n groups,\n emptyLabel = \"No languages available\",\n onChange,\n}: {\n label: string;\n value: string;\n groups: LanguageOptionGroup[];\n emptyLabel?: string;\n onChange: (language: string) => void;\n}) {\n const hasOptions = groups.some((group) => group.options.length);\n const hasValue = groups.some((group) => group.options.some((option) => option.value === value));\n\n return (\n <label className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-zinc-400\">{label}</span>\n <select\n className=\"w-full rounded border border-zinc-200 bg-white py-[5px] px-2 text-xs text-zinc-800 focus:border-me-primary-500 focus:outline-none focus:ring-2 focus:ring-me-primary-500/20\"\n value={value}\n disabled={!hasOptions}\n onChange={(event) => onChange(event.target.value)}\n >\n {!hasValue ? (\n <option value={value} disabled>\n {hasOptions ? getLanguageLabel(value) : emptyLabel}\n </option>\n ) : null}\n {groups.map((group) =>\n group.options.length ? (\n <optgroup key={group.label} label={group.label}>\n {group.options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </optgroup>\n ) : null,\n )}\n </select>\n </label>\n );\n}\n\nconst statusDotConfig: Record<TranslationStatus, { dot: string; label: string; text: string }> = {\n missing: { dot: \"bg-amber-400\", text: \"text-amber-700\", label: \"Missing\" },\n existing: { dot: \"bg-green-400\", text: \"text-green-700\", label: \"Done\" },\n stale: { dot: \"bg-red-400\", text: \"text-red-600\", label: \"Stale\" },\n suggested: { dot: \"bg-sky-400\", text: \"text-sky-700\", label: \"Suggested\" },\n skipped: { dot: \"bg-zinc-300\", text: \"text-zinc-500\", label: \"Skipped\" },\n};\n\nfunction StatusDot({ status }: { status: TranslationStatus }) {\n const c = statusDotConfig[status] || statusDotConfig.skipped;\n return (\n <span className={`flex shrink-0 items-center gap-1 text-[10px] font-medium ${c.text}`}>\n <span className={`h-1.5 w-1.5 rounded-full ${c.dot}`} />\n {c.label}\n </span>\n );\n}\n\nfunction ChevronIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n className={`h-3.5 w-3.5 shrink-0 text-zinc-300 transition-transform ${expanded ? \"rotate-180\" : \"\"}`}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n );\n}\n\nfunction PlayIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeOpacity=\"0.3\" />\n <path d=\"M12 3a9 9 0 0 1 9 9\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n\nfunction getStatusCounts(targets: TranslationTarget[]) {\n return targets.reduce(\n (counts, target) => {\n counts.total += 1;\n counts[target.status] = (counts[target.status] || 0) + 1;\n return counts;\n },\n {\n total: 0,\n missing: 0,\n existing: 0,\n suggested: 0,\n skipped: 0,\n stale: 0,\n } as Record<TranslationTarget[\"status\"] | \"total\", number>,\n );\n}\n\nfunction getTargetText(occurrences: TranslationOccurrence[]) {\n for (const occurrence of occurrences) {\n if (occurrence.targetText?.trim()) {\n return occurrence.targetText;\n }\n }\n return \"\";\n}\n","import type {\n BackgroundActionDefinition,\n LayoutPanel,\n} from \"@manifest-editor/shell\";\nimport { createTranslationBackgroundAction } from \"./background-action\";\nimport { createTranslationLanguageTagsBackgroundAction } from \"./language-tags-background-action\";\nimport { translationsPanel } from \"./sidebar\";\nexport { default, settings } from \"./plugin\";\n\nexport const leftPanels: LayoutPanel[] = [translationsPanel];\n\nexport const backgroundActions: BackgroundActionDefinition[] = [\n createTranslationBackgroundAction(),\n createTranslationLanguageTagsBackgroundAction(),\n];\n\nexport * from \"./background-action\";\nexport * from \"./collection\";\nexport * from \"./config-modal\";\nexport * from \"./constants\";\nexport * from \"./html\";\nexport * from \"./language-tags-background-action\";\nexport * from \"./languages\";\nexport * from \"./options\";\nexport * from \"./results\";\nexport * from \"./runtime\";\nexport * from \"./sidebar\";\nexport * from \"./types\";\nexport * from \"./writeback\";\n"],"mappings":"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"}
package/dist/lazy.cjs ADDED
@@ -0,0 +1 @@
1
+ require(`./constants-D5kaKQHg.cjs`);const e=require(`./plugin-DcjqyREu.cjs`);var t={default:e.t,settings:e.n,load:()=>Promise.resolve().then(()=>require(`./index.cjs`))};module.exports=t;
@@ -0,0 +1,23 @@
1
+ import { Rt as TranslationPluginSettings, n as index_d_exports } from "./index-B-UTJDqv.cjs";
2
+ import * as _manifest_editor_shell0 from "@manifest-editor/shell";
3
+
4
+ //#region src/lazy.d.ts
5
+ declare const _default: {
6
+ default: {
7
+ id: string;
8
+ label: string;
9
+ description: string;
10
+ author: string;
11
+ official: true;
12
+ defaultEnabled: false;
13
+ tags: string[];
14
+ supports: {
15
+ apps: string[];
16
+ projectTypes: "Manifest"[];
17
+ };
18
+ };
19
+ settings: _manifest_editor_shell0.PluginSettingsDefinition<TranslationPluginSettings>;
20
+ load: () => Promise<typeof index_d_exports>;
21
+ };
22
+ export = _default;
23
+ //# sourceMappingURL=lazy.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy.d.cts","names":[],"sources":["../src/lazy.ts"],"sourcesContent":[],"mappings":""}
package/dist/lazy.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { Rt as TranslationPluginSettings, n as index_d_exports } from "./index-CkK8TiJs.js";
2
+ import * as _manifest_editor_shell0 from "@manifest-editor/shell";
3
+
4
+ //#region src/lazy.d.ts
5
+ declare const _default: {
6
+ default: {
7
+ id: string;
8
+ label: string;
9
+ description: string;
10
+ author: string;
11
+ official: true;
12
+ defaultEnabled: false;
13
+ tags: string[];
14
+ supports: {
15
+ apps: string[];
16
+ projectTypes: "Manifest"[];
17
+ };
18
+ };
19
+ settings: _manifest_editor_shell0.PluginSettingsDefinition<TranslationPluginSettings>;
20
+ load: () => Promise<typeof index_d_exports>;
21
+ };
22
+ //#endregion
23
+ export { _default as default };
24
+ //# sourceMappingURL=lazy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy.d.ts","names":[],"sources":["../src/lazy.ts"],"sourcesContent":[],"mappings":""}
package/dist/lazy.js ADDED
@@ -0,0 +1,2 @@
1
+ import"./constants-2H03x5Ga.js";import{n as e,t}from"./plugin-sM3MrbwG.js";var n={default:t,settings:e,load:()=>import(`./index.js`)};export{n as default};
2
+ //# sourceMappingURL=lazy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy.js","names":["metadata"],"sources":["../src/lazy.ts"],"sourcesContent":["import type { LazyPluginModule } from \"@manifest-editor/shell\";\nimport metadata, { settings } from \"./plugin\";\n\nexport default {\n default: metadata,\n settings,\n load: () => import(\"./index\"),\n} satisfies LazyPluginModule;\n"],"mappings":"2EAGA,IAAA,EAAe,CACb,QAASA,EACT,WACA,SAAY,OAAO,cACpB"}
@@ -0,0 +1 @@
1
+ const e=require(`./constants-D5kaKQHg.cjs`);var t={id:e.o,label:`Translations`,description:`Review manifest strings and fill missing translations with M2M100.`,author:`Digirati`,official:!0,defaultEnabled:!1,tags:[`translation`,`i18n`,`automation`],supports:{apps:[`manifest-editor`],projectTypes:[`Manifest`]}};const n={defaults:{runtimePreference:`auto`},fields:[{id:`defaultSourceLanguage`,label:`Default source language`,type:`text`,description:`Optional M2M100 source language code. Falls back to the editor default language.`,placeholder:`en`},{id:`defaultTargetLanguage`,label:`Default target language`,type:`text`,description:`Optional M2M100 target language code. Falls back to another configured editor language.`,placeholder:`nl`},{id:`runtimePreference`,label:`Runtime preference`,type:`select`,description:`WebGPU is attempted first in Auto mode, then WASM is used as a fallback.`,options:[{label:`Auto`,value:`auto`},{label:`WebGPU`,value:`webgpu`},{label:`WASM`,value:`wasm`}]},{id:`workerUrl`,label:`Worker URL`,type:`text`,description:`Optional public URL for the translation worker when the package is consumed through another bundled package.`,placeholder:`/assets/translation-worker.js`}]};Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return t}});
@@ -0,0 +1,2 @@
1
+ import{o as e}from"./constants-2H03x5Ga.js";var t={id:e,label:`Translations`,description:`Review manifest strings and fill missing translations with M2M100.`,author:`Digirati`,official:!0,defaultEnabled:!1,tags:[`translation`,`i18n`,`automation`],supports:{apps:[`manifest-editor`],projectTypes:[`Manifest`]}};const n={defaults:{runtimePreference:`auto`},fields:[{id:`defaultSourceLanguage`,label:`Default source language`,type:`text`,description:`Optional M2M100 source language code. Falls back to the editor default language.`,placeholder:`en`},{id:`defaultTargetLanguage`,label:`Default target language`,type:`text`,description:`Optional M2M100 target language code. Falls back to another configured editor language.`,placeholder:`nl`},{id:`runtimePreference`,label:`Runtime preference`,type:`select`,description:`WebGPU is attempted first in Auto mode, then WASM is used as a fallback.`,options:[{label:`Auto`,value:`auto`},{label:`WebGPU`,value:`webgpu`},{label:`WASM`,value:`wasm`}]},{id:`workerUrl`,label:`Worker URL`,type:`text`,description:`Optional public URL for the translation worker when the package is consumed through another bundled package.`,placeholder:`/assets/translation-worker.js`}]};export{n,t};
2
+ //# sourceMappingURL=plugin-sM3MrbwG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-sM3MrbwG.js","names":["settings: PluginSettingsDefinition<TranslationPluginSettings>"],"sources":["../src/plugin.ts"],"sourcesContent":["import type { PluginMetadata, PluginSettingsDefinition } from \"@manifest-editor/shell\";\nimport { TRANSLATION_PLUGIN_ID } from \"./constants\";\nimport type { TranslationPluginSettings } from \"./types\";\n\nexport default {\n id: TRANSLATION_PLUGIN_ID,\n label: \"Translations\",\n description: \"Review manifest strings and fill missing translations with M2M100.\",\n author: \"Digirati\",\n official: true,\n defaultEnabled: false,\n tags: [\"translation\", \"i18n\", \"automation\"],\n supports: {\n apps: [\"manifest-editor\"],\n projectTypes: [\"Manifest\"],\n },\n} satisfies PluginMetadata;\n\nexport const settings: PluginSettingsDefinition<TranslationPluginSettings> = {\n defaults: {\n runtimePreference: \"auto\",\n },\n fields: [\n {\n id: \"defaultSourceLanguage\",\n label: \"Default source language\",\n type: \"text\",\n description: \"Optional M2M100 source language code. Falls back to the editor default language.\",\n placeholder: \"en\",\n },\n {\n id: \"defaultTargetLanguage\",\n label: \"Default target language\",\n type: \"text\",\n description: \"Optional M2M100 target language code. Falls back to another configured editor language.\",\n placeholder: \"nl\",\n },\n {\n id: \"runtimePreference\",\n label: \"Runtime preference\",\n type: \"select\",\n description: \"WebGPU is attempted first in Auto mode, then WASM is used as a fallback.\",\n options: [\n { label: \"Auto\", value: \"auto\" },\n { label: \"WebGPU\", value: \"webgpu\" },\n { label: \"WASM\", value: \"wasm\" },\n ],\n },\n {\n id: \"workerUrl\",\n label: \"Worker URL\",\n type: \"text\",\n description: \"Optional public URL for the translation worker when the package is consumed through another bundled package.\",\n placeholder: \"/assets/translation-worker.js\",\n },\n ],\n};\n"],"mappings":"4CAIA,IAAA,EAAe,CACb,GAAI,EACJ,MAAO,eACP,YAAa,qEACb,OAAQ,WACR,SAAU,GACV,eAAgB,GAChB,KAAM,CAAC,cAAe,OAAQ,aAAa,CAC3C,SAAU,CACR,KAAM,CAAC,kBAAkB,CACzB,aAAc,CAAC,WAAW,CAC3B,CACF,CAED,MAAaA,EAAgE,CAC3E,SAAU,CACR,kBAAmB,OACpB,CACD,OAAQ,CACN,CACE,GAAI,wBACJ,MAAO,0BACP,KAAM,OACN,YAAa,mFACb,YAAa,KACd,CACD,CACE,GAAI,wBACJ,MAAO,0BACP,KAAM,OACN,YAAa,0FACb,YAAa,KACd,CACD,CACE,GAAI,oBACJ,MAAO,qBACP,KAAM,SACN,YAAa,2EACb,QAAS,CACP,CAAE,MAAO,OAAQ,MAAO,OAAQ,CAChC,CAAE,MAAO,SAAU,MAAO,SAAU,CACpC,CAAE,MAAO,OAAQ,MAAO,OAAQ,CACjC,CACF,CACD,CACE,GAAI,YACJ,MAAO,aACP,KAAM,OACN,YAAa,+GACb,YAAa,gCACd,CACF,CACF"}
@@ -0,0 +1 @@
1
+ function e(e,t){return{kind:`request`,command:`preload`,requestId:e,payload:t}}function t(e,t){return{kind:`request`,command:`translate`,requestId:e,payload:t}}function n(e){return{kind:`request`,command:`dispose`,requestId:e}}function r(e,t,n){return{kind:`success`,command:e,requestId:t,payload:n}}function i(e,t){return r(`translate`,e,t)}function a(e,t,n){return{kind:`error`,command:e,requestId:t,payload:n}}function o(e){return{kind:`event`,payload:e}}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return e}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return n}});
@@ -0,0 +1,2 @@
1
+ function e(e,t){return{kind:`request`,command:`preload`,requestId:e,payload:t}}function t(e,t){return{kind:`request`,command:`translate`,requestId:e,payload:t}}function n(e){return{kind:`request`,command:`dispose`,requestId:e}}function r(e,t,n){return{kind:`success`,command:e,requestId:t,payload:n}}function i(e,t){return r(`translate`,e,t)}function a(e,t,n){return{kind:`error`,command:e,requestId:t,payload:n}}function o(e){return{kind:`event`,payload:e}}export{r as a,e as i,a as n,t as o,o as r,i as s,n as t};
2
+ //# sourceMappingURL=protocol-znyidDej.js.map