import { computed, makeObservable, observable } from 'mobx' import { TranslationData } from '../interfaces' import { MainStore } from '.' export const LANGUAGE_MAP: Record = { 'cs-CZ': 'cs', 'sk-SK': 'sk', 'en-US': 'en', 'it-IT': 'it', } interface Language { key: string code: string name: string locale: string } export class TranslationStore { main: MainStore locale = 'en' translations: Record = {} languages: Language[] = [] constructor(main: MainStore) { makeObservable(this, { locale: observable, translations: observable.shallow, languages: observable, t: computed, }) this.main = main } get t() { return this.translations[this.locale] } translationsForOrg = () => { return this.t?.organization?.[this.main.userStore.organization.id] } async setupBackendTranslations(language: string): Promise { const locale = LANGUAGE_MAP[language] if (locale) { this.locale = locale const translations = await this.main.translations.getTranslations(language) if (!translations.ok || !translations.data) { return } this.translations[locale] = { ...(this.translations[locale] || {}), ...translations.data, } } } getLanguages = async () => { if (this.languages.length > 0) { return } const languagesRequest = await this.main.translations.getLanguages() if (!languagesRequest.ok || !languagesRequest?.data) { console.warn('Cannot load languages') return } this.languages = Object.entries(languagesRequest.data).map( ([key, value]) => ({ key, ...value, }), ) } getTranslatedType = (type: string): string | null => { const typeWithoutScope = extractTypeWithoutScope(type) const forOrg = this.translationsForOrg() // exact e.g. `organization-Car` const exactTranslation = forOrg?.element?.[type] || this.t?.element?.[type] // This would be without the organization scope e.g. `Car` const bareTranslation = forOrg?.element?.[type] || this.t?.element?.[typeWithoutScope] const overrideTranslation = forOrg?.typeOverrides?.[type]?.name return overrideTranslation || exactTranslation || bareTranslation || type } getTranslatedClusterHeader = ( type: string | undefined, title: string, ): string => { const forOrg = this.translationsForOrg() return ( forOrg?.typeOverrides?.[type || '']?.group_header?.[title] || forOrg?.typeOverrides?.[type || '']?.attribute?.[title] || forOrg?.group_header?.[title] || forOrg?.attribute?.[title] || this.t?.group_header?.[title] || this.t?.attribute?.[title] || title ) } getTranslatedTab = (tabId: string): string | undefined => { const forOrg = this.translationsForOrg() return forOrg?.tabs?.[tabId] } getTranslatedMenuItem = (menuId: string): string | undefined => { const forOrg = this.translationsForOrg() return forOrg?.navigation?.[menuId] } getTranslatedAttribute = ( type: string | undefined, translationKey: string, ): string => { const forOrg = this.translationsForOrg() return ( forOrg?.typeOverrides?.[type || '']?.attribute?.[translationKey] || forOrg?.attribute?.[translationKey] || this.t?.attribute?.[translationKey] || translationKey ) } getTranslatedAttributeValue = ( type: string | undefined, value: string, ): string => { const forOrg = this.translationsForOrg() return ( forOrg?.typeOverrides?.[type || '']?.attribute_value?.[value] || forOrg?.attribute_value?.[value] || this.t?.attribute_value?.[value] || value ) } getTranslatedButton = (title: string): string => { const forOrg = this.translationsForOrg() return forOrg?.buttons?.[title] || title } } export const extractTypeWithoutScope = (type: string): string => { /* Explainer: Element types created in editors V2 use $scope/$type encoded into type as $scope-$type. If type contains `-`, we need to extract the type without scope. */ if (type.includes('-')) { // V2 type const typeFragments = type.split('-') const last = typeFragments.pop() return last || type } // Legacy element type return type }