{"version":3,"file":"useTranslation-BK97Y3Fz.mjs","names":[],"sources":["../src/helper/language.ts","../src/stores/class/transcript/transcriptParams.ts","../src/components/composable/useTranslation.ts"],"sourcesContent":["/**\n * Utility function to retrieve most relevant language for the user\n * @params forceToKnown When set to true (default), will limit language to one\n *                      one of 6 known languages. When set to false, allow all\n *                      languages.\n * @returns The most relevant language\n */\nexport function getLanguage(forceToKnown = true): string {\n    const nameEQ = \"octopus-language=\";\n    const ca = document.cookie.split(\";\");\n\n    let language = \"\";\n    for (const valueCookie of ca) {\n        let c = valueCookie;\n        while (c.startsWith(\" \")) {\n            c = c.substring(1, c.length);\n        }\n        if (0 === c.indexOf(nameEQ)) {\n            language = c.substring(nameEQ.length, c.length);\n            break;\n        }\n    }\n\n    if (0 === language.length) {\n        if (forceToKnown === true) {\n            // Choose best avilable language\n            for (const navigatorLang of navigator.languages) {\n                if (navigatorLang.includes(\"fr\")) {\n                    language = \"fr\";\n                    break;\n                } else if (navigatorLang.includes(\"en\")) {\n                    language = \"en\";\n                    break;\n                } else if (navigatorLang.includes(\"it\")) {\n                    language = \"it\";\n                    break;\n                } else if (navigatorLang.includes(\"sl\")) {\n                    language = \"sl\";\n                    break;\n                } else if (navigatorLang.includes(\"es\")) {\n                    language = \"es\";\n                    break;\n                } else if (navigatorLang.includes(\"de\")) {\n                    language = \"de\";\n                    break;\n                }\n            }\n            if (!language) {\n                language = \"fr\";\n            }\n        } else {\n            language = navigator.language;\n        }\n    }\n\n    return language;\n}\n","export interface TranscriptParams {\n  automation: string; // super, {date}, false \n  ttsParams: TtsParams;\n  modifyPodcast: ModifyPodcastConfig\n  translationConfig: TranslationConfiguration;\n}\nexport interface TtsParams {\n  super: string;\n  style: string;\n  pitch: number;\n  speed: number;\n  voice: string;\n  language: string;\n}\n\nexport interface ModifyPodcastConfig {\n  modifyChaptering: ModifyPodcastEnum;\n  modifyKeywords: ModifyPodcastEnum;\n  modifyDescription: ModifyPodcastEnum;\n  createDescriptionUsingAi: boolean;\n  wordsNumber: number;\n}\n\nexport enum ModifyPodcastEnum {\n  SUPER = \"SUPER\",\n  NO = \"NO\",\n  IF_EMPTY = \"IF_EMPTY\",\n  OVERWRITE=\"OVERWRITE\"\n}\n\nexport interface TranslationConfiguration {\n  createTranslation:{[lang:string]: CreateTranslation};\n  otherLanguage:CreateTranslation; //Cannot be ALWAYS\n}\n\nexport enum CreateTranslation {\n  NEVER = \"NEVER\",\n  ON_DEMAND = \"ON_DEMAND\",\n  ALWAYS = \"ALWAYS\",\n  SUPER=\"SUPER\"\n}\n\nexport function defaultTtsParams(): TtsParams {\n  return {\n    super: \"true\",\n    style: \"neutral\",\n    pitch: 0,\n    speed: 1,\n    voice: \"\",\n    language: \"\"\n  };\n}\n\nexport function defaultModifyPodcastConfig(): ModifyPodcastConfig {\n  return {\n    modifyChaptering: ModifyPodcastEnum.NO,\n    modifyKeywords:ModifyPodcastEnum.NO,\n    modifyDescription:ModifyPodcastEnum.NO,\n    createDescriptionUsingAi: false,\n    wordsNumber: 100,\n  };\n}\n\n/**\n * Create a default object of TranslationConfiguration\n * @param isEmission Optional, if set and true changes default values\n * @returns The object\n */\nexport function defaultTranslationConfig(isEmission?: boolean): TranslationConfiguration {\n  return {\n    createTranslation:{},\n    otherLanguage: isEmission ? CreateTranslation.SUPER : CreateTranslation.NEVER\n  };\n}\n\nexport interface Voice {\n  name: string;\n  locale: string;\n  displayName: string;\n  gender: string;\n  audioExample?: string;\n  styles?: [];\n  provider: string;\n}\nexport interface ProviderTts {\n  name: string;\n  fullName: string;\n  logoPath: string;\n  description: string;\n}\n","import { getLanguage } from \"../../helper/language\";\nimport { transcriptionApi, TranslationState, type PodcastTranslationData } from \"../../api/transcriptionApi\";\nimport { CreateTranslation, defaultTranslationConfig, TranslationConfiguration } from \"../../stores/class/transcript/transcriptParams\";\nimport { podcastApi } from \"../../api/podcastApi\";\nimport { Emission } from \"../../stores/class/general/emission\";\nimport { OrganisationAttributes } from \"@/stores/class/general/organisation\";\nimport { organisationApi } from \"../../api/organisationApi\";\n\nconst DEFAULT_LANGUAGE = 'en';\n\ninterface RelevantLanguages {\n    /** Language which already has a generated translation */\n    ready: string;\n    /** Language that is more relevant but its translation is not yet generated */\n    available?: string;\n}\n\nenum Availability {\n    Available,\n    ToGenerate,\n    Unavailable\n}\n\nexport const useTranslation = () => {\n\n    /**\n     * Convert SRT data to plain text\n     * @param srt The data to convert\n     * @returns The plain text\n     */\n    function convertSrtToPlainText(srt: string): string {\n        const srtPattern =\n            /\\d+\\n[\\d:,]+\\s+-{2}>\\s+[\\d:,]+\\n([\\s\\S]*?(?=\\n{2}|$))/gm;\n        const result: Array<string> = [];\n        let matches: string[];\n        while ((matches = srtPattern.exec(srt)) != null) {\n            result.push(matches[1] + \" \");\n        }\n        return result.join(\"\");\n    }\n\n    function getApplicationConf(language: string, conf: TranslationConfiguration): CreateTranslation {\n        if (language in conf.createTranslation) {\n            return conf.createTranslation[language];\n        }\n\n        return conf.otherLanguage;\n    }\n\n    /**\n     * Retrieve the translation configuration for a given language\n     */\n    function getConfigurationFor(language: string, emissionConf: TranslationConfiguration, orgaConf: TranslationConfiguration): CreateTranslation {\n        const emissionSetting = getApplicationConf(language, emissionConf);\n        if (emissionSetting === CreateTranslation.SUPER) {\n            return getApplicationConf(language, orgaConf);\n        }\n        return emissionSetting;\n    }\n\n    function parseOrDefault(data: string|undefined, isEmission = false): TranslationConfiguration {\n        return data ? JSON.parse(data) : defaultTranslationConfig(isEmission);\n    }\n\n    /**\n     * Indicates wether the language is available (either because generated or\n     * because it can be generated)\n     * @param language The language to check for\n     * @param emission *(optional)* If set, will also check in emission settings\n     * @returns Whether the language is available or not\n     */\n    function getTranslationConfig(language: string, emission: Emission, orgaAttributes: OrganisationAttributes): CreateTranslation {\n        const emissionTranslation = parseOrDefault(emission.annotations?.['translation-config'] as string|undefined, true);\n        const orgTranslation = parseOrDefault(orgaAttributes?.['translation-config']);\n\n        return getConfigurationFor(language, emissionTranslation, orgTranslation);\n    }\n\n    function getLanguageAvailability(language: string, emission: Emission, orgaAttributes: OrganisationAttributes, translationData: PodcastTranslationData): Availability {\n        \n        // 1. If language of podcast == language of browser, use that language\n        if (language === translationData.nativeLanguage) {\n            return Availability.Available;\n        } else {\n            const langConfig = getTranslationConfig(language, emission, orgaAttributes);\n\n            // 2. If the language of the browser is available, use it\n            if (langConfig === CreateTranslation.ALWAYS) {\n                return Availability.Available;\n            }\n            // 2b. If the language is on demand, check if generated\n            else if (langConfig === CreateTranslation.ON_DEMAND) {\n                // Check if translation is already generated\n                if (translationData.translations.find(t => t.language === language && t.state === TranslationState.FINISHED)) {\n                    return Availability.Available;\n                } else {\n                    return Availability.ToGenerate;\n                }\n            }\n        }\n\n        return Availability.Unavailable;\n    }\n\n    /**\n     * Get the relevant language for the current user\n     * @param translationData The translation data for the podcast\n     * @returns An object with properties 'ready' and 'available'\n     *          - *ready* Is the best language already generated\n     *          - *available* Is the best language not yet generated (or\n     *                        undefined if *ready* is better)\n     */\n    async function getMostRelevantLanguage(translationData: PodcastTranslationData): Promise<RelevantLanguages> {\n        const userLanguage = getLanguage(false);\n\n        // If user language is native, do not go further\n        if (userLanguage === translationData.nativeLanguage) {\n            return { ready: userLanguage };\n        }\n\n        // Compute all available languages. Use language set on site, then\n        // languages defined on browser, then default, and finally native language\n        const languages: string[] = [];\n        [userLanguage, ...navigator.languages, DEFAULT_LANGUAGE, translationData.nativeLanguage].forEach(l => {\n            // For each language, if it is a variant (for example fr-CH), use\n            // only the base language\n            if (l.includes('-')) {\n                l = l.split('-')[0];\n            }\n\n            if (!languages.includes(l)) {\n                languages.push(l);\n            }\n        });\n\n        const podcast = await podcastApi.get(translationData.podcastId);\n        const emission = podcast.emission;\n        const orgaAttributes = await organisationApi.getAttributes(podcast.organisation.id);\n\n        let bestReady: string|null = null;\n        let bestAvailable: string|null = null;\n\n        for (const language of languages) {\n            const avaibility = getLanguageAvailability(language, emission, orgaAttributes, translationData);\n            if (avaibility === Availability.Available && bestReady === null) {\n                bestReady = language;\n                break;\n            }\n\n            if (avaibility === Availability.ToGenerate && bestAvailable === null) {\n                bestAvailable = language;\n            }\n        }\n\n        return { ready: bestReady, available: bestAvailable ?? undefined };\n    }\n\n    /**\n     * Get the relevant translation for the current user\n     * @param translationData The translation data for the podcast\n     * @returns The translation\n     */\n    async function getMostRelevantTranslation(translationData: PodcastTranslationData): Promise<string>;\n    /**\n     * Get the relevant translation for the current user\n     * @param podcastId The ID of the podcast\n     * @returns The translation\n     */\n    async function getMostRelevantTranslation(podcastId: number): Promise<string>;\n\n    /**\n     * Get the relevant translation for the current user\n     * @param translationData The translation data for the podcast\n     * @returns The translation\n     */\n    async function getMostRelevantTranslation(data: PodcastTranslationData|number): Promise<string> {\n        let translationData: PodcastTranslationData;\n        if (typeof data === 'number') {\n            translationData = await transcriptionApi.getTranslations(data);\n        } else {\n            translationData = data;\n        }\n\n        const { ready } = await getMostRelevantLanguage(translationData);\n\n        // Finally get translation with chosen language\n        const podcastId = translationData.podcastId;\n        return await transcriptionApi.getTranslation(podcastId, ready);\n    }\n\n    return {\n        convertSrtToPlainText,\n        getMostRelevantLanguage,\n        getMostRelevantTranslation,\n        getTranslationConfig\n    }\n};\n"],"mappings":"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"}